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 の連携
ProcessOrderJobはOrdersCreateジョブを呼び出し、Shopifyの注文情報をローカルDBへ保存します。ジョブはqueue:workで実行され、retryUntilで最大再試行時間を設定します。
public function handle()
{
try {
// 注文データをDBへ保存
Order::create($this->orderData);
} catch (\Exception $e) {
// 失敗時は再試行
throw $e;
}
}
QueueはRedisやAmazon SQSを利用し、スケールアウトが容易です。
失敗時の再試行とログ記録
LaravelのジョブはtriesとretryAfterを設定できます。失敗時に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を利用して重複注文を検知し、同一注文の二重処理を防止します。これにより、データ整合性が保たれます。
コメント
コメントを投稿