Laravel + Stripe CLIでWebhookのテストをする

stripe cliとLaravelでwebhookのテストをしよう

決済サービスとしてシェアが伸びているStripeのWebhookを使ったローカルテストの仕方を解説します。

今回は、「checkout.session.complete」になったら、DBに取引を登録するという内容をテストします。

サーバーサイドはLaravelです。

Stripeのアカウントは事前に取得しておき、Laravelのプロジェクトに

composer require stripe/stripe-php

しておきます。

Stripe CLIをインストールする

Mac OSの場合はHomebrewを使用してStripe CLIをインストールします。

$ brew install stripe/stripe-cli/stripe

私の場合、5分ほどかかりました。パソコンに何かをインストールするときはいつもちょっとドキドキします。

Stripe CLIにログインする

インストールが完了したら、そのままターミナルに

$ stripe login

と打ちます。すると、

Me-no-MBP:~ Me$ stripe login
Your pairing code is: happy-puppy-candy-baby
This pairing code verifies your authentication with Stripe.
Press Enter to open the browser (^C to quit)

と出てきます。

そのままEnterキーを押すと、ブラウザに下記のような画面が立ち上がるので「アクセスを許可」してください。

これでStripe CLIと自分のStripeアカウントがペアリングされ、90日間有効となりました。

Laravelの設定

次にLaravelのルーティングとコントローラーを設定しましょう。

ルーティング設定

web.phpにルートの設定を記述します。(もしかしてapi.phpの方が良いのかな?)

Route::post('/webhooks', 'WebhookController@webhook');

この/webhookがエンドポイントです。

CSRF解除

LaravelのPOST送信では、セキュリティ上の理由でCSRFプロテクションが作動します。

WebhookはStripeのサーバーからpostされるためcsrfトークンが含まれていません。このままでは419エラーが出ます。

そのため、/app/Http/Middleware/VerifyCsrfToken.phpに次を追記します。

protected $except = [
        '/webhooks'
    ];

コントローラー作成

artisanでコントローラーを作成します。

$ php artisan make:controller WebhookController

WebhookController.phpができたので、ここにアクションを書いていきます。

アクション1:webhook

Stripe CLIには「$ stripe」から始まるいろいろなメソッドが用意されています。

その中でも、「triger」は、決済の間に行われる下記のようなイベントを発火させます。

  • payment_intent.created(新規支払いの作成)
  • customer.created(新規顧客の作成)
  • charge.succeeded(請求)
  • payment_method.attached(支払い方法を顧客に追加)
  • payment_intent.succeeded(支払い成功)
  • checkout.session.completed(セッション完了)

これらは「トリガー」としてwebhookを起動させます。

Stripe CLIの使い方はあとで見ていくので、今は理解できなくても問題ありません。

このトリガーによって、先ほどのルーティングで設定したWebhookController@webhookが起動するので、こちらの中身を書いていきます。

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

use Stripe\Exception\SignatureVerificationException; //追記
use Stripe\Exception\UnexpectedValueException; //追記
use Stripe\Stripe; //追記
use Stripe\Webhook; //追記

public function webhook()
    {
        Stripe::setApiKey(config('services.stripe.secret')); //envに設定しているのを引っ張っている
        $endpoint_secret = 'whsec_...'; //Stripe CLIを起動するときに出てくる(あとで解説します)

        $payload = @file_get_contents('php://input');
        $sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
        try {
            $event = Webhook::constructEvent(
                $payload,
                $sig_header,
                $endpoint_secret
            );
        } catch (UnexpectedValueException $e) {
            http_response_code(400);
            exit();
        } catch (SignatureVerificationException $e) {
            http_response_code(400);
            exit();
        }
        if ($event->type == 'checkout.session.completed') {
            $session = $event->data->object;
            $this->handle_checkout_session($session); //次に作成する
        }

        http_response_code(200);
    }

こちらは公式にあるものを少しLaravel用にアレンジしたものです。

$endpoint_secretは、Stripe CLIを使用するときに与えられる”whsec”から始まるキーです。実際にStripe CLIを使う段階で解説します。

アクション2:イベント

先ほどのコードで、

if ($event->type == 'checkout.session.completed') {
            $session = $event->data->object;
            $this->handle_checkout_session($session); //次に作成する
        }

という部分がありました。webhookのトリガーとなってくれるイベントが「checkout.session.completed」のときにhandle_checkout_session関数を動かす、というものです。

今度はこのhandle_checkout_sessionを作ります。

public function handle_checkout_session($session)
    {
        //ちょっとめんどくさいので省略します(笑)
    }

とりあえず、この中で取引内容をDBに登録する処理を書けばOK(これを読んでいる人はできるはず)!

$sessionの中にはpayment_intent(取引ごとのユニークなid)やdisplay_items(販売した商品の内容)などが入っているので、デバッグして中身を確認してみてください。

Stripe CLIを動かす

Stripe CLIを動かすには、ターミナルを2つ起動します。

1つはイベントトリガー用、もう1つはHTTP statusの200や500エラーなど、サーバーの返事をきく用です。

きく用

$ stripe listen

これが基本です。でもこれではLaravel内のアクションをlistenしてくれないのでHTTP statusは返ってきません。

Laravel内のアクションをlistenするには次のように書きます。

$ stripe listen --forward-to http://127.0.0.1:8000/webhooks

すると

> Ready! Your webhook signing secret is whsec_...

と出てくるので、先ほどのWebhookController.phpの$endpoint_secretのところに書き足します。

トリガー用

もう1つのターミナルではイベントを打ち込んでいきます。

$ stripe trigger checkout.session.completed

これできく用のターミナルにステータスコードが返ってくると思います。

以上でーす!Stripeすごい!!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)