web-application-framework laravel

Stripeの支払い成功後、Webhookで購入後の処理を実行する方法をまとめました。

サムネイル

参考

前提

  • Laravelプロジェクトを作成済み
    LaravelプロジェクトをNGINXで動かす方法についてはこちらをご覧ください。
    Reactを使用する場合はこちらをご覧ください。
  • Laravel Cashier (Stripe) をインストール済み
    インストール方法についてはこちらをご覧ください。

環境

  • Windows 11
  • Ubuntu 24.04.3 LTS (WSL2ディストリビューション)
  • Docker Engine 28.4.0
  • Amazon Linux 2023(DockerコンテナのOS)
  • PHP 8.2.29 (fpm-fcgi)
  • NGINX 1.24.0
  • Laravel 12.38.1
  • laravel/cashier 16.0.5

ワークフロー

  1. チェックアウト処理の作成
  2. Stripeイベントリスナーの作成
  3. ローカル環境で確認

1. チェックアウト処理の作成

公式ドキュメントを参考に、次のようにチェックアウト処理を作成します。

use Illuminate\Http\Request;
 
Route::get('/checkout', function (Request $request) {
    $stripePriceId = 'price_deluxe_album';
 
    $quantity = 1;
 
    return $request->user()->checkout([$stripePriceId => $quantity], [
        'success_url' => route('checkout-success'),
        'cancel_url' => route('checkout-cancel'),
    ]);
})->name('checkout');
 
Route::view('/checkout/success', 'checkout.success')->name('checkout-success');
Route::view('/checkout/cancel', 'checkout.cancel')->name('checkout-cancel');

Stripeで作成したprice IDを $stripePriceId に指定してください。
また、checkout.successcheckout.cancel のビューも用意しておく必要があります。

/checkout にアクセスするとStripeのチェックアウト画面が表示されます。 支払いが成功すると /checkout/success にリダイレクトされます。

2. Stripeイベントリスナーの作成

アプリケーションがStripeのイベントを受け取った後に何かしらの処理を実行させるためのイベントリスナーを作成します。
次のArtisanコマンドを実行してください。

php artisan make:listener StripeEventListener --event=WebhookReceived

生成されたリスナーを以下のように編集します。

<?php

namespace App\Listeners;

use Illuminate\Support\Facades\Log;
use Laravel\Cashier\Events\WebhookReceived;

class StripeEventListener
{
    /**
     * Create the event listener.
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     */
    public function handle(WebhookReceived $event): void
    {
        if ($event->payload['type'] === 'payment_intent.succeeded') {
            Log::info('The payment succeeded');
        }
    }
}

payment_intent.succeeded は支払いが成功したときに発火するイベントです。
Stripeのイベント一覧はこちらで確認できます。

次に、AppServiceProvider.phpboot() メソッドでリスナーを登録します。

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Event::listen(WebhookReceived::class, StripeEventListener::class); // 追加
    }

3. ローカル環境で確認

Stripe CLIを使用してローカル環境で動作を確認します。
Stripe CLIのインストール方法はこちらを参照してください。

> stripe login
> stripe listen --forward-to localhost:80/stripe/webhook

アプリケーションのポートとwebhookのパスを指定してください。
Laravel Cashierはデフォルトで /stripe/webhook を使っています。

その後 /checkout にアクセスすると、アプリケーションのログに The payment succeeded と表示されるはずです。

(おまけ) リスナーでmetadataを取得する

リスナーで自分が指定した値を取得したい場合、チェックアウト時に metadata を追加することで好きな値を送ることができます。

Route::get('/checkout', function (Request $request) {
    $stripePriceId = 'price_deluxe_album';
 
    $quantity = 1;
 
    return $request->user()->checkout([$stripePriceId => $quantity], [
        'success_url' => route('checkout-success'),
        'cancel_url' => route('checkout-cancel'),
        // metadataを追加
        'payment_intent_data' => [
            'metadata' => ['test_key' => 'test_value'],
        ],
    ]);
})->name('checkout');

リスナーで metadata を取得します。

    /**
     * Handle the event.
     */
    public function handle(WebhookReceived $event): void
    {
        if ($event->payload['type'] === 'payment_intent.succeeded') {
            Log::info('Test data: ' . $event->payload['data']['object']['metadata']['test_key']); // metadataを表示
        }
    }

Stripe CLIで metadata 付きのイベントをトリガーしたい場合は次のように指定します。

Stripe trigger payment_intent.succeeded --add payment_intent:metadata['test_key']=test_value

関連記事