StripeのWebhookエンドポイントを設定し、生のボディでStripe-Signatureを検証し、stripe listenとstripe triggerでテストして、Checkoutの注文を1回だけ処理する方法を解説します。
Stripe Webhookは、サーバー上のHTTPSエンドポイントで、Stripeがイベントの JSON をPOSTで送ってきます。たとえば支払い後のcheckout.session.completedです。ハンドラーは、エンドポイントのwhsec_シークレットを使い、手を加えていない生のボディに対してStripe-Signatureヘッダーを検証し、すぐに2xxを返し、同じイベントが複数回届いても問題なく処理できる必要があります。
Stripe Webhookの要点(2026年10月にStripeのドキュメントで確認)
うまく動かないStripe連携の多くは、次の3か所のどれかで失敗しています。検証の前にフレームワークがボディを解析してしまった、ハンドラーが重い処理をしてタイムアウトした、再送されたイベントで注文が二重に処理された、のいずれかです。このガイドでは、この3つをすべて避けるハンドラーを順を追って説明します。下のチェッカーではブラウザー上でStripe-Signatureヘッダーを検証できるので、ライブラリが何を計算しているかを正確に確認できます。
ほぼ必ず、検証の前にボディが変更されたことが原因です。たとえばexpress.json()や、JSONを再エンコードするボディパーサーによるものです。Webhookのルートにだけexpress.raw({ type: "application/json" })を設定するか、Next.jsのルートハンドラーでrequest.text()を読み取りましょう。シークレットが間違っている場合も同じメッセージが出ます。
カード決済にはcheckout.session.completed、口座引き落としなどの遅延型の決済方法にはcheckout.session.async_payment_succeededも必要です。Stripeは、顧客に知らせられるようcheckout.session.async_payment_failedも処理することを推奨しています。注文を処理する前に、セッションのpayment_statusを確認しましょう。
いいえ。Stripe自身のドキュメントにも、顧客が支払い後、成功ページが読み込まれる前にタブを閉じる可能性があると書かれています。素早い確認のために成功ページを使ってもかまいませんが、Webhookでも必ず注文処理を起動し、どちらの経路も2回実行されて問題ないようにしてください。
Stripeは順序を保証していません。invoice.paidがcustomer.subscription.createdより先に届くこともあります。イベントIDを記録して重複を見つけ、最新の状態が必要なときはAPIから関連オブジェクトを取得しましょう。
ダッシュボードでイベントの「再送」をクリックする(作成から15日以内なら可能)か、CLIでstripe events resend <event_id> --webhook-endpoint=<endpoint_id>を実行します(30日以内まで)。自動再試行はそれとは関係なく続きます。
express.rawをこのルートだけに設定しているので、ボディは元のバイト列のままconstructEventに届きます。
request.text()で解析前のボディを取得します。constructEvent内で例外が出る場合は、署名かシークレットが間違っています。
listenはこのセッション用のwhsec_シークレットを表示します。それをローカルの環境変数に設定し、2つ目のターミナルでイベントを発生させます。
よく使うStripeのイベントタイプと対応
Stripe-Signatureヘッダー、生のボディ、whsec_シークレットを貼り付けると、ライブラリが行うのと同じ検証を確認できます。Web Cryptoを使ってブラウザー内で動作し、何も送信しません。テストモードのシークレットを使い、本番のシークレットは決して使わないでください。
Stripe-Signatureヘッダー
生のリクエストボディ
エンドポイントのシークレット(whsec_...)
許容時間(秒)
このボディに今すぐ署名
検証
結果
ヘッダーにt=のタイムスタンプがありません。
ヘッダーにv1=の署名がありません。
期待されるv1:{v}
署名が一致しました。
署名が一致しません:ボディが変更されたか、シークレットが間違っています。
タイムスタンプは{n}秒前で、許容時間内です。
タイムスタンプは{n}秒前で、許容時間外です:ライブラリはこれを拒否します。
無料で始める · クレジットカード不要