PHPackages                             kyon147/laravel-shopify - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. kyon147/laravel-shopify

ActiveLibrary[API Development](/categories/api)

kyon147/laravel-shopify
=======================

Shopify package for Laravel to aide in app development

v27.0.1(1w ago)485302.1k↓52.5%178[18 issues](https://github.com/Kyon147/laravel-shopify/issues)[10 PRs](https://github.com/Kyon147/laravel-shopify/pulls)MITPHPPHP ^8.2

Since Dec 8Pushed 2mo ago14 watchersCompare

[ Source](https://github.com/Kyon147/laravel-shopify)[ Packagist](https://packagist.org/packages/kyon147/laravel-shopify)[ Fund](https://paypal.me/kyon147)[ GitHub Sponsors](https://github.com/kyon147)[ RSS](/packages/kyon147-laravel-shopify/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (10)Dependencies (34)Versions (57)Used By (0)

Laravel Shopify App
===================

[](#laravel-shopify-app)

[![Tests](https://github.com/kyon147/laravel-shopify/workflows/Package%20Test/badge.svg?branch=master)](https://github.com/kyon147/laravel-shopify/workflows/Package%20Test/badge.svg?branch=master)[![codecov](https://camo.githubusercontent.com/e52930cefcf0f835e98bc85f2c30fefdcd12900e88f2cc54e81b4255476a1dff/68747470733a2f2f636f6465636f762e696f2f67682f6b796f6e3134372f6c61726176656c2d73686f706966792f6272616e63682f6d61737465722f67726170682f62616467652e7376673f746f6b656e3d717155754c4974714a6a)](https://codecov.io/gh/kyon147/laravel-shopify)[![License](https://camo.githubusercontent.com/a6e3a3f9c63fe07568da9c964a055679b8df015789178a53f401422306d4148d/68747470733a2f2f706f7365722e707567782e6f72672f6b796f6e3134372f6c61726176656c2d73686f706966792f6c6963656e7365)](https://packagist.org/packages/osiset/laravel-shopify)

---

This is a maintained version of the wonderful but now deprecated original [Laravel Shopify App](https://github.com/gnikyt/laravel-shopify/). To keep things clean, this has been detached from the original.

---

To install this package run:

```
composer require kyon147/laravel-shopify

```

Publish the config file:

```
php artisan vendor:publish --tag=shopify-config

```

---

A full-featured Laravel package for aiding in Shopify App development, similar to `shopify_app` for Rails. Works for Laravel 8 and up.

[![Screenshot](screenshot.png)](screenshot.png)[![Screenshot: Billable](screenshot-billable.png)](screenshot-billable.png)

Table of Contents
-----------------

[](#table-of-contents)

**\*** *Wiki pages*

- [Goals](#goals)
- [Documentation](#documentation)
- [Installation](../../wiki/Installation)\*
- [Route List](../../wiki/Route-List)\*
- [Usage](../../wiki/Usage)\*
- [Changelog](../../wiki/Changelog)\*
- [Contributing Guide](CONTRIBUTING.md)
- [LICENSE](#license)

For more information, tutorials, etc., please view the project's [wiki](../../wiki).

Goals
-----

[](#goals)

- Per User Auth Working
- Better support for SPA apps using VueJS
- Getting "Blade" templates working better with Shopify's new auth process???

Documentation
-------------

[](#documentation)

For full resources on this package, see the [wiki](../..//wiki).

### Expiring offline access tokens

[](#expiring-offline-access-tokens)

[Shopify requires expiring offline access tokens](https://shopify.dev/changelog/expiring-offline-access-tokens-required-for-public-apps-april-1-2026) for **new public apps** created on or after April 1, 2026. This package supports them when enabled:

1. Run package migrations so your shops table includes `shopify_offline_refresh_token`, `shopify_offline_access_token_expires_at`, and `shopify_offline_refresh_token_expires_at`.
2. Set `SHOPIFY_EXPIRING_OFFLINE_TOKENS=true` in `.env` (see `expiring_offline_tokens`, `auto_migrate_legacy`, and `offline_access_token_refresh_skew_seconds` in `config/shopify-app.php`).
3. Keep `APP_KEY` stable: refresh tokens are stored encrypted with Laravel’s encrypter.

Authorization code exchange, session-token exchange, and `refresh_token` grants are handled inside this package (`Osiset\ShopifyApp\Services\ApiHelper` and `OfflineAccessTokenRefresher`), not via `gnikyt/basic-shopify-api` updates. A valid access token is refreshed automatically before `apiHelper()` builds the API session when the offline token is expired or within the configured skew.

**Migrating existing installs (optional):** Shops that already have a non-expiring offline token are not upgraded automatically when you enable the flag alone. Options:

- **Passive (default):** With `SHOPIFY_AUTO_MIGRATE_LEGACY=true` (default), the first `apiHelper()` call for a legacy shop runs Shopify [Step 4](https://shopify.dev/docs/apps/build/authentication-authorization/access-tokens/offline-access-tokens#step-4-migrate-existing-tokens) token exchange synchronously. Failures are logged and the request continues with the legacy token (fail-open).
- **Batch CLI (serverless-safe):** `php artisan shopify-app:migrate-expiring-offline-tokens` (`--dry-run`, `--shop=example.myshopify.com`) chunks matching shops and dispatches `MigrateShopTokenJob` to the queue — no HTTP in the command itself (suitable for Laravel Vapor).
- **Action:** `MigrateShopToExpiringOfflineAccessToken` — call per shop from your own code; returns `migrated`, `skipped`, `reason`, and `error` keys.
- **API:** `ApiHelper::exchangeNonExpiringOfflineTokenForExpiring($shopDomain, $currentOfflineToken)` then persist with `ShopCommand::setAccessToken`.

Migration is **one-way**: Shopify revokes the old token on successful exchange.

**Long-running jobs:** Token refresh runs when the API client is first built (`$shop->api()` / `$shop->apiHelper()`). If a job reuses the same shop model for hours, the cached client keeps the old access token even after expiry. Options:

- **Opt-in config:** `SHOPIFY_REFRESH_OFFLINE_TOKEN_BEFORE_API_CALL=true` re-checks expiry before each `api()` / `apiHelper()` call and rebuilds the client when needed.
- **Manual helpers on your shop model:**
    - `$shop->offlineAccessTokenIsFresh()` — `true` when the token is outside the refresh skew window
    - `$shop->refreshOfflineAccessTokenIfNeeded()` — refreshes via Shopify and clears the cached client
    - `$shop->resetApiClient()` — clears the cached client so the next API call rebuilds it

```
// Per loop iteration in a bulk job
if (! $shop->offlineAccessTokenIsFresh()) {
    $shop->refreshOfflineAccessTokenIfNeeded();
}
$shop->api()->graph('...');
```

If your `User` model overrides `$casts`, merge `datetime` casts for the two `*_expires_at` columns (the `ShopModel` trait uses `mergeCasts` when `initializeShopModel` runs).

Longer term, consider replacing or forking `gnikyt/basic-shopify-api` for REST/Graph traffic if you need an actively maintained HTTP client; expiring offline OAuth is already decoupled from that dependency.

Issue or request?
-----------------

[](#issue-or-request)

If you have found a bug or would like to request a feature for discussion, please use the `ISSUE_TEMPLATE` in this repo when creating your issue. Any issue submitted without this template will be closed.

License
-------

[](#license)

This project is released under the MIT [license](LICENSE).

Misc
----

[](#misc)

### Repository

[](#repository)

#### Contributors

[](#contributors)

Contributions are always welcome! Contibutors are updated each release, pulled from Github. See [`CONTRIBUTORS.txt`](CONTRIBUTORS.txt).

If you're looking to become a contributor, please see [`CONTRIBUTING.md`](CONTRIBUTING.md).

#### Maintainers

[](#maintainers)

Maintainers are users who manage the repository itself, whether it's managing the issues, assisting in releases, or helping with pull requests.

Currently this repository is maintained by:

- [@kyon147](https://github.com/kyon147)
- [@gnikyt](https://github.com/gnikyt) Original author of the package. See [announcement](https://github.com/gnikyt/laravel-shopify/discussions/1276) for details.

Looking to become a maintainer? E-mail @kyon147 directly.

### Special Note

[](#special-note)

I develop this package in my spare time, with a busy family/work life like many of you! So, I would like to thank everyone who's helped me out from submitting PRs, to assisting on issues, and plain using the package (I hope its useful). Cheers.

###  Health Score

67

—

FairBetter than 99% of packages

Maintenance91

Actively maintained with recent releases

Popularity59

Moderate usage in the ecosystem

Community32

Small or concentrated contributor base

Maturity73

Established project with proven stability

 Bus Factor1

Top contributor holds 63.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~38 days

Recently: every ~14 days

Total

35

Last Release

9d ago

Major Versions

v22.0.1 → v23.0.02025-03-25

v23.1.0 → v24.0.02025-07-16

v24.1.0 → v25.0.02025-11-07

v25.2.0 → v26.0.02026-04-28

v26.1.0 → v27.0.02026-06-20

PHP version history (5 changes)v17.3.3PHP &gt;=7.2

v17.5.0PHP ^7.3 || ^8.0 || 8.1

v18.0.0PHP ^8.0 || 8.1

v23.0.0PHP ^8.0 || ^8.1 || ^8.2 || ^8.3 || ^8.4

v26.0.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/3d4d976667e513ccb0011513744b2feedfd26c978536fd9f52615e93e6e6ad55?d=identicon)[Kyon147](/maintainers/Kyon147)

---

Top Contributors

[![gnikyt](https://avatars.githubusercontent.com/u/2420282?v=4)](https://github.com/gnikyt "gnikyt (462 commits)")[![Kyon147](https://avatars.githubusercontent.com/u/32519106?v=4)](https://github.com/Kyon147 "Kyon147 (70 commits)")[![lucasmichot](https://avatars.githubusercontent.com/u/513603?v=4)](https://github.com/lucasmichot "lucasmichot (47 commits)")[![darrynten](https://avatars.githubusercontent.com/u/3657251?v=4)](https://github.com/darrynten "darrynten (29 commits)")[![JonPurvis](https://avatars.githubusercontent.com/u/7534029?v=4)](https://github.com/JonPurvis "JonPurvis (15 commits)")[![amosmos](https://avatars.githubusercontent.com/u/2318695?v=4)](https://github.com/amosmos "amosmos (12 commits)")[![enmaboya](https://avatars.githubusercontent.com/u/90896143?v=4)](https://github.com/enmaboya "enmaboya (9 commits)")[![bilfeldt](https://avatars.githubusercontent.com/u/30228807?v=4)](https://github.com/bilfeldt "bilfeldt (8 commits)")[![jedimdan](https://avatars.githubusercontent.com/u/757825?v=4)](https://github.com/jedimdan "jedimdan (8 commits)")[![ilamp](https://avatars.githubusercontent.com/u/12907744?v=4)](https://github.com/ilamp "ilamp (7 commits)")[![awebartisan](https://avatars.githubusercontent.com/u/29105478?v=4)](https://github.com/awebartisan "awebartisan (7 commits)")[![squatto](https://avatars.githubusercontent.com/u/748444?v=4)](https://github.com/squatto "squatto (5 commits)")[![oanhnn](https://avatars.githubusercontent.com/u/1757120?v=4)](https://github.com/oanhnn "oanhnn (4 commits)")[![tuimz](https://avatars.githubusercontent.com/u/850235?v=4)](https://github.com/tuimz "tuimz (4 commits)")[![kurakin-oleksandr](https://avatars.githubusercontent.com/u/729966?v=4)](https://github.com/kurakin-oleksandr "kurakin-oleksandr (3 commits)")[![seka19](https://avatars.githubusercontent.com/u/2714877?v=4)](https://github.com/seka19 "seka19 (3 commits)")[![ClaraLeigh](https://avatars.githubusercontent.com/u/2524209?v=4)](https://github.com/ClaraLeigh "ClaraLeigh (3 commits)")[![msonowal](https://avatars.githubusercontent.com/u/6334484?v=4)](https://github.com/msonowal "msonowal (3 commits)")[![nahid](https://avatars.githubusercontent.com/u/3167309?v=4)](https://github.com/nahid "nahid (3 commits)")[![aepnat](https://avatars.githubusercontent.com/u/10273457?v=4)](https://github.com/aepnat "aepnat (3 commits)")

---

Tags

apilaravelsdklaravel-packagedriverfacadewebhookshopifyshopify-apilaravel-shopifycallback-urlscripttagsshopify-app

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/kyon147-laravel-shopify/health.svg)

```
[![Health](https://phpackages.com/badges/kyon147-laravel-shopify/health.svg)](https://phpackages.com/packages/kyon147-laravel-shopify)
```

###  Alternatives

[openai-php/laravel

OpenAI PHP for Laravel is a supercharged PHP API client that allows you to interact with the Open AI API

3.7k9.5M89](/packages/openai-php-laravel)[darkaonline/l5-swagger

OpenApi or Swagger integration to Laravel

3.0k37.6M134](/packages/darkaonline-l5-swagger)[knuckleswtf/scribe

Generate API documentation for humans from your Laravel codebase.✍

2.3k14.2M63](/packages/knuckleswtf-scribe)[mozex/anthropic-laravel

Laravel integration for the Anthropic API: facade, config publishing, install command, testing fakes, messages, streaming, tool use, thinking, and batches.

74331.3k1](/packages/mozex-anthropic-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
