決済サービスとしてシェアが伸びている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すごい!!