Shopify Laravel Webhook非同期

Shopify Laravel Webhook非同期

Shopify+LaravelでWebhookを受け取る

Shopifyは注文が発生するとWebhookで通知を送信します。Laravel側では、routes/web.phpにエンドポイントを定義し、ShopifyWebhookControllerで処理します。ここでは、POST /shopify/webhookを想定し、Shopifyから送られるJSONペイロードを取得します。

Route::post('/shopify/webhook', [ShopifyWebhookController::class, 'handle']);

Laravelのリクエストオブジェクトからヘッダーとボディを取得し、後続の処理へ渡します。

署名検証とセキュリティ

ShopifyはX-Shopify-Hmac-Sha256ヘッダーに署名を付与します。Laravel側で検証することで、改ざんや偽装を防止します。以下は検証ロジックの例です。

$hmacHeader = $request->header('X-Shopify-Hmac-Sha256');
$calculatedHmac = base64_encode(hash_hmac('sha256', $request->getContent(), config('shopify.secret'), true));
if (!hash_equals($hmacHeader, $calculatedHmac)) {
    abort(401, 'Invalid signature');
}

署名検証に失敗したリクエストは即座に拒否し、ログに記録します。

イベントリスナーと非同期処理

Webhook受信後、イベントを発火させます。ShopifyOrderCreatedイベントを定義し、OrderCreatedListenerで非同期ジョブをキューに投入します。これにより、HTTPレスポンスは即座に返却され、Shopify側のタイムアウトを回避します。

event(new ShopifyOrderCreated($orderData));

イベントリスナーはShouldQueueを実装し、handleメソッドでProcessOrderJobをdispatchします。

Jobs/OrdersCreate と Queue の連携

ProcessOrderJobOrdersCreateジョブを呼び出し、Shopifyの注文情報をローカルDBへ保存します。ジョブはqueue:workで実行され、retryUntilで最大再試行時間を設定します。

public function handle()
{
    try {
        // 注文データをDBへ保存
        Order::create($this->orderData);
    } catch (\Exception $e) {
        // 失敗時は再試行
        throw $e;
    }
}

QueueはRedisやAmazon SQSを利用し、スケールアウトが容易です。

失敗時の再試行とログ記録

LaravelのジョブはtriesretryAfterを設定できます。失敗時にfailedメソッドでログを残し、Slackやメールで通知します。

public function failed(\Exception $exception)
{
    Log::error('Order processing failed', [
        'order_id' => $this->orderData['id'],
        'exception' => $exception->getMessage(),
    ]);
}

再試行は指数バックオフで行い、過負荷を防止します。

タイムアウト対策とデータ同期の最適化

ShopifyはWebhook送信時に5秒以内にレスポンスを返す必要があります。非同期ジョブを使用することで、処理時間を短縮し、タイムアウトを回避します。また、queue:retryで失敗したジョブを再投入し、データ同期を確実にします。

さらに、Cacheを利用して重複注文を検知し、同一注文の二重処理を防止します。これにより、データ整合性が保たれます。

この記事はAIによって作成されました。

ショピファイ+ララベル課金実装

ショピファイ+ララベル課金実装

Shopify+Laravelでの課金実装概要

ShopifyのアプリをLaravelで構築する際、課金実装は重要な要素です。ShopifyはBilling APIを提供し、アプリ側でサブスクリプションや単発課金を管理できます。LaravelのEloquentやサービスプロバイダを活用すれば、課金ロジックをシンプルに保つことが可能です。

Billing APIとRecurringApplicationChargeの使い方

Billing APIはRESTfulエンドポイントで、POST /admin/api/2024-01/recurring_application_charges.json を呼び出すことでRecurringApplicationChargeを作成します。リクエストボディにはプラン名、価格、期間、試用期間などを設定し、Shopify側で支払い承認を促します。承認後はactiveステータスが付与され、アプリは利用可能になります。

プラン作成と課金フロー設計

プラン作成は、まずLaravel側でプラン情報をDBに保存し、Billing APIに送るJSONを生成します。課金フローは以下のように設計します。

  1. ユーザーがアプリをインストール
  2. プラン選択画面でRecurringApplicationChargeを作成
  3. Shopifyが支払い承認を要求
  4. 承認後、Laravelでactiveを確認し、機能を有効化

試用期間とアップグレード処理

試用期間はtrial_daysパラメータで設定できます。試用終了時に自動で課金が開始されるようにWebhookを利用し、charge_activatedイベントを監視します。アップグレードは既存のRecurringApplicationChargeをキャンセルし、新しいプランを作成することで実現します。

課金ステータスの監視と支払い承認

課金ステータスはstatusフィールドで確認できます。pendingacceptedactiveの遷移を追跡し、失敗時はdeclinedをハンドリングします。支払い承認はShopify側で完了した後、Webhookで通知されるため、Laravel側で即座に機能を切り替えることが可能です。

この記事はAIによって作成されました。

Shopify Laravel GraphQLで高速取得

Shopify Laravel GraphQLで高速取得

Shopify+LaravelでGraphQL APIを活用する

ShopifyはREST APIだけでなくGraphQL APIを提供しており、Laravelとの組み合わせで高速かつ柔軟なデータ取得が可能です。GraphQL APIは必要なフィールドだけをリクエストできるため、ネットワーク帯域を節約し、レスポンス時間を短縮します。LaravelではHTTPクライアントを使って簡単にGraphQLエンドポイントへリクエストを送ることができ、認証にはShopifyのアクセストークンを利用します。

GraphqlQueryとMutationの実装例

GraphqlQueryは読み取り専用のクエリ、Mutationはデータ変更を行う操作です。Laravelのサービスクラスで以下のように実装します。

public function getProducts()
{
    $query = <<<'GRAPHQL'
{
  products(first: 10) {
    edges {
      node {
        id
        title
        variants(first: 5) {
          edges { node { id price } }
        }
      }
    }
  }
}
GRAPHQL;
    return $this->client->post('/admin/api/2026-01/graphql.json', [
        'json' => ['query' => $query]
    ]);
}

Mutationの例として、商品を作成するリクエストは次のようになります。

public function createProduct($title, $price)
{
    $mutation = <<<'GRAPHQL'
mutation ($input: ProductInput!) {
  productCreate(input: $input) {
    product { id title }
    userErrors { field message }
  }
}
GRAPHQL;
    $variables = ['input' => ['title' => $title, 'variants' => [['price' => $price]]]];
    return $this->client->post('/admin/api/2026-01/graphql.json', [
        'json' => ['query' => $mutation, 'variables' => $variables]
    ]);
}

データ取得とクエリ作成のベストプラクティス

GraphqlQueryを作成する際は、必要なフィールドだけを指定し、不要なデータを排除します。これにより、API制限に引っかかりにくく、レスポンスサイズを小さく保てます。また、Laravelのキャッシュ機能を利用して頻繁にアクセスされるデータをローカルに保存し、API呼び出し回数を削減することも重要です。

エラーハンドリングとページネーション

GraphQL APIはレスポンスにerrorsフィールドを含む場合があります。Laravel側で例外を捕捉し、ユーザーに分かりやすいメッセージを返すようにします。ページネーションはedgespageInfoを利用し、hasNextPageendCursorで次ページの取得を制御します。

if ($response['data']['products']['pageInfo']['hasNextPage']) {
    $cursor = $response['data']['products']['pageInfo']['endCursor'];
    // 次ページを取得
}

カーソルと効率的な取得、API制限への対策

カーソルベースのページネーションは、インデックスベースよりも安定したデータ取得を可能にします。Shopifyは1分あたりのリクエスト数に制限があるため、カーソルを使って必要なデータだけを順次取得し、リクエスト数を最小化します。さらに、batch機能を活用して複数のクエリを1回のリクエストで送ることで、API制限を超えにくくなります。

この記事はAIによって作成されました。

Shopify Laravel ルート設

Shopify Laravel ルート設計

Shopify+Laravelの概要

ShopifyとLaravelを組み合わせることで、eコマースサイトのバックエンドを高速に構築できます。Laravelの豊富な機能(Eloquent、ミドルウェア、サービスプロバイダー)を活用し、ShopifyのAPIと連携することで、商品管理や注文処理をシームレスに行えます。まずは、Shopifyのアプリを作成し、OAuth認証を設定して、Laravel側でアクセストークンを取得します。

ルーティングとコントローラーの実装

Laravelでは、routes/web.phpにルート定義を記述します。ShopifyからのWebhookや認証コールバックを受け取るエンドポイントを設定し、Auth Middlewareで保護します。以下は典型的なルート定義例です。

Route::middleware(['auth', 'signed'])->group(function () {
    Route::post('/shopify/webhook', [ShopifyWebhookController::class, 'handle']);
    Route::get('/shopify/callback', [ShopifyAuthController::class, 'callback']);
});

ここでAuth MiddlewareはLaravelの認証ガードを利用し、signedミドルウェアは署名付きリクエストを検証します。コントローラー実装では、リクエストを受け取り、ビジネスロジックを実行し、レスポンスを返します。例としてWebhookハンドラを示します。

class ShopifyWebhookController extends Controller
{
    public function handle(Request $request)
    {
        // 署名検証済み
        $payload = $request->all();
        // 受信データを処理
        // ...
        return response('OK', 200);
    }
}

レスポンスはシンプルに文字列を返すだけでなく、JSONやXMLを返すことも可能です。リダイレクト処理が必要な場合は、redirect()ヘルパーを使用します。

認証と署名付きリクエストの処理

ShopifyのWebhookは署名付きリクエストで送信されます。Laravelのsignedミドルウェアを使うと、リクエストヘッダーに含まれるHMACを自動で検証できます。検証に失敗した場合は403が返されます。認証ガードは、Shopifyのアクセストークンをセッションやデータベースに保存し、Auth::guard('shopify')->user()で取得します。

リダイレクト処理は、認証が必要なページにアクセスした際にShopifyの認可ページへ誘導する際に重要です。以下はリダイレクト例です。

public function redirectToShopify()
{
    $url = config('shopify.auth_url') . '?client_id=' . config('shopify.api_key')
        . '&scope=read_products,write_orders&redirect_uri=' . route('shopify.callback')
        . '&state=' . Str::random(40);
    return redirect()->away($url);
}

このように、ルート定義、コントローラー実装、Auth Middleware、認証ガード、署名付きリクエスト、レスポンス、リダイレクト処理を組み合わせることで、Shopify+Laravelアプリケーションは堅牢かつ拡張性の高い構造になります。

この記事はAIによって作成されました。

shopifyのCustomerAccesstokenの有効期限

公式には記載されているのがないので、

メモがてら記載しておきます。

実際にcustomerAccessTokenCreateを利用して確認した所。

expiresAtの値を見た所、42日となってました。


12月8日 18時00分(日本時間) (2025-12-08T09:00:00Z)に実行した所、

1月19日 18時00分(日本時間)(2026-01-19T09:00:00Z)と返って来ました


参考になればと思います。