Webhook エンドポイントで Stripe イベントを受信する
AWS アカウントにイベントを送信する
Amazon EventBridge での Stripe イベント受信のサポートをプライベートベータで開始しています。 早期アクセスをご希望の場合は、eventbridge.stripe.dev にご登録ください。
Webhook を使用する理由
Stripe のシステムを構築する際、自社のアプリが Stripe アカウントで発生するイベントを受信できるようにすることをお勧めします。こうすることで、バックエンドシステムは適宜アクションを実行できます。
Webhook イベントを有効にするには、Webhook エンドポイントを登録する必要があります。登録すると、Stripe アカウントで Event (イベント) が発生した際に、Stripe はリアルタイムのイベントデータを貴社のアプリの Webhook エンドポイントに追加することができます。Stripe は HTTPS を使用して、Event (イベント) オブジェクトを含む JSON ペイロードとして Webhook イベントをアプリに送信します。
Webhook イベントの受信は、顧客の銀行が支払いを確定したとき、顧客が支払いに対して不審請求を申請したとき、継続支払いが成功したとき、サブスクリプションの支払いを回収するときなど、非同期イベントをリッスンする際に特に便利です。
イベントの概要
Stripe はお客様のアカウントでアクティビティーがあった際にイベントデータを生成し、送信します。
イベントが発生すると、Stripe は新たに Event (イベント) オブジェクトを作成します。1 つの API リクエストで複数のイベントが作成されることがあります。たとえば、顧客に新しいサブスクリプションを作成すると、customer.subscription.created
イベントと payment_intent.succeeded
イベントを受信することになります。
Webhook エンドポイントを Stripe アカウントに登録すると、Stripe は、お客様のアプリケーションがホストする登録済みの Webhook エンドポイントに、POST リクエストの一部として Event (イベント) オブジェクトを自動的に送信できるようになります。Webhook エンドポイントが Event を受信すると、アプリでバックエンドアクションを実行できます (たとえば、payment_intent.succeeded
イベントを受信した後に、配送プロバイダーの API を呼び出して、配送の予定を設定するなど)。
Event オブジェクト
Stripe が Webhook エンドポイントに送信する Event (イベント) オブジェクトでは、変更されたオブジェクトのスナップショットが提供されます。該当する場合、変更を示す previous_attributes
プロパティが含まれることがあります。
Stripe が貴社の Webhook に送信するイベントタイプの一覧をご覧ください。
イベントペイロードの例
以下のイベントは、トライアル終了時のサブスクリプションの更新を示しています。
{ "id": "evt_1MqqbKLt4dXK03v5qaIbiNCC", "object": "event", "api_version": "2024-04-10", "created": 1680064028,
イベントオブジェクトの構造
イベントオブジェクトの構造を確認すると、イベントと、そのイベントが提供する基となる情報に対する理解を深めることができます。
イベントタイプ
設定で Webhook エンドポイントがリッスンするすべての event type (イベントタイプ) のイベントを受信します。受信したイベントの type
を使用して、アプリケーションで実行が必要な処理を決定します。各イベントの type
に対応する data.object
はさまざまです。
本番環境とテスト環境
エンドポイントに対する、本番環境とテスト環境の両方のイベント送信リクエストを受信することがあります。これが該当するのは、本番環境とテスト環境の両方で 1 つのエンドポイントを使用している場合や、Connect プラットフォームで本番環境の Standard 連結アカウントに対してテスト環境のリクエストを行っている場合です。livemode
属性を使用して、オブジェクトが本番環境とテスト環境のどちらに存在するかを確認し、イベントの適切な処理を判断します。
API バージョン
api_version
は、イベントの API バージョンを示し、含まれている data.object の構造を指定します。エンドポイントは、設定されている API バージョンを使用してイベントを受信しますが、アカウントのデフォルトの API バージョンやイベントに関連するリクエストの API バージョンと異なる場合があります。この属性は、送信先のエンドポイントによって決定され、異なる API バージョンを使用して複数のエンドポイントに同じイベントが送信される可能性があることを示します。Stripe の Java、.NET、Go のクライアントライブラリを使用する場合、クライアントに固定されている API バージョンを使用するようにエンドポイントの API バージョンを設定してください。そうしなければ、イベントオブジェクトをデシリアライズ (逆シリアル化) できなくなる場合があります。
API から Event オブジェクトを取得する場合、data.object
構造の API バージョンを管理することはできません。代わりに、適切な API エンドポイントからそのオブジェクトを取得して、Stripe-Version
ヘッダーを使用し、API バージョンを指定してください。
API リクエストイベント
API リクエストの結果としてイベントが生成されると、そのリクエストは request.id
として表示されます。リクエストを行うときに idempotency_key
を使用する場合は、それが request.idempotency_key
として含まれます。イベントの原因を調査する場合は、この request
ハッシュを確認します。
データオブジェクトと以前の属性
*.updated
イベントの場合、イベントペイロードには、Stripe オブジェクトの変更内容を調べることができる data.previous_attributes
が含まれています。上記の例の customer.subscription.updated
イベントの previous_attributes
は、サブスクリプションの変更前の値が status: trialing
であったことなどを示しています。data.object
は、active
のステータスを示しているため、サブスクリプションがトライアル期間から移行したことを示しています。
保留中の送信
このイベントに設定されているエンドポイントのうち、送信に対して正常に応答していない数を判断するには、pending_webhooks
を使用します。最初の送信時には、エンドポイントが正常に応答していないため、この値が 1 以上になります。このイベントを後から取得する場合、各エンドポイントが正常に応答するため、pending_webhooks
は最小 0 まで減ります。これは invoice.created
イベントにとって重要です。送信が失敗すると、インボイスの確定が遅れる可能性があるためです。
連結アカウントのイベント
連結アカウントから Connect エンドポイントに送信されるイベントには、account
が含まれます。account
を使用してオブジェクトが属している連結アカウントを追跡し、プラットフォームがイベントデータを適切に処理できるようにします。
Event オブジェクトが作成される理由
この表は、Event (イベント) オブジェクトの生成をトリガーする複数のシナリオを説明したものです。
ソース | トリガー |
---|---|
ダッシュボード | Stripe ダッシュボードで Stripe リソースを変更することによって、API を呼び出す場合。 |
API | アプリまたはウェブサイトでのユーザーアクションによって API コールが行われる場合。 |
API | Stripe CLI を使用して手動でイベントをトリガーする場合。 |
API | Stripe CLI で直接 API を呼び出す場合。 |
始める
自社のアプリで Webhook イベントを受け取るには、以下のステップに従って Webhook エンドポイントを作成して登録します。
- Webhook エンドポイントハンドラを作成して、イベントデータの POST リクエストを受信します。
- Stripe CLI を使用して、ローカルで Webhook エンドポイントハンドラをテストします。
- ダッシュボードまたは API を使用して、Stripe 内にエンドポイントを登録します。
- Webhook エンドポイントを保護します。
1 つのエンドポイントを登録、作成して、複数のイベントタイプを一度に処理するか、特定のイベントに個別のエンドポイントを設定することができます。
ハンドラを作成する
POST メソッドを使用して、Webhook リクエストの受け付けが可能な HTTP または HTTPS エンドポイント関数を設定します。ローカルマシンでエンドポイント関数を開発中の場合、HTTP を使用できます。公開アクセスが可能になったら、Webhook エンドポイント関数は HTTPS を使用する必要があります。
エンドポイント関数を設定し、以下を行うようにします。
- Event (イベント) オブジェクトで構成される JSON ペイロードを使用して、POST リクエストを処理します。
- タイムアウトを引き起こす可能性のある複雑なロジックの前に、成功のステータスコード (
2xx
) を素早く返します。たとえば、会計システムで顧客の請求書を支払い済みとして更新する前に、200
のレスポンスを返す必要があります。
注
別の方法として、インタラクティブな Webhook エンドポイントビルダーを使用して、ご使用のプログラム言語で Webhook エンドポイント関数を構築することもできます。
エンドポイントの例
このコードスニペットは、イベントタイプが受信されたことを確認し、イベントを処理して、コード 200 のレスポンスを返すよう設定された Webhook 関数です。
ハンドラをテストする
Webhook エンドポイント関数を本番環境に移行する前に、アプリケーションの連携をテストすることをお勧めします。これを行うには、自身のローカルマシンにイベントを送信するようローカスリスナーを設定し、テストイベントを送信します。テストには、CLI を使用する必要があります。
ローカルエンドポイントにイベントを転送する
ローカルエンドポイントにイベントを転送するには、CLI で以下のコマンドを実行し、ローカルリスナーを設定します。--forward-to
フラグは、テスト環境のすべての Stripe イベントをローカルの Webhook エンドポイントに送信します。
stripe listen --forward-to localhost:4242/stripe_webhooks
注
Stripe Shell で Stripe リッスンコマンドを実行して、Stripe Shell 端末からイベントを確認することもできますが、Shell からローカルエンドポイントにイベントを転送することはできません。
ローカルリスナーでのテストに役立つ便利な設定として、以下のようなものがあります。
- HTTPS 証明書の検証を無効にするには、
--skip-verify
のオプションフラグを使用します。 - 特定のイベントのみを転送するには、
--events
のオプションフラグを使用して、カンマで区切ったイベントのリストを渡します。
stripe listen --events payment_intent.created,customer.created,payment_intent.succeeded,checkout.session.completed,payment_intent.payment_failed \ --forward-to localhost:4242/webhook
- Stripe に登録済みの公開 Webhook エンドポイントからローカルの Webhook エンドポイントにイベントを転送するには、
--load-from-webhooks-api
のオプションフラグを使用します。これにより、登録されたエンドポイントにイベントが読み込まれ、パスとその登録イベントが解析され、そのパスが--forward-to path
のローカルの Webhook エンドポイントに関連付けられます。
stripe listen --load-from-webhooks-api --forward-to localhost:5000
- Webhook の署名を確認するには、リッスンコマンドの初期出力から
{{WEBHOOK_SIGNING_SECRET}}
を使用します。
Ready! Your webhook signing secret is '{{WEBHOOK_SIGNING_SECRET}}' (^C to quit)
テストイベントをトリガーする
テストイベントを送信するには、Stripe ダッシュボードでオブジェクトを手動で作成し、イベントの送信先が登録しているイベントタイプをトリガーします。あるいは、Stripe Shell または Stripe CLI で次のコマンドを使用できます。
この例では、payment_intent.succeeded
イベントをトリガーします。
stripe trigger payment_intent.succeeded Running fixture for: payment_intent Trigger succeeded! Check dashboard for event details.
注
VS Code 向けの Stripe を使用してイベントをトリガーする方法をご紹介します。
Stripe でエンドポイントを登録する
Webhook エンドポイント関数をテストしたら、Stripe がイベントの送信先を把握できるように、開発者ダッシュボードまたは API の Webhook セクションを使用して、Webhook エンドポイントのアクセス可能な URL を登録します。Stripe では最大 16 の Webhook エンドポイントを登録することができます。登録された Webhook エンドポイントは、パブリックアクセスが可能な HTTPS URL である必要があります。
Webhook の URL 形式
Webhook エンドポイントを登録するための URL 形式は、次のとおりです。
https://<your-website>/<your-webhook-endpoint>
たとえば、ドメインが https://mycompanysite.com
で、Webhook エンドポイントへのルートが @app.route('/stripe_webhooks', methods=['POST'])
の場合、エンドポイント URL には https://mycompanysite.com/stripe_webhooks
を指定します。
Webhook エンドポイントを追加する
注
アカウントでワークベンチを有効にした場合は、ワークベンチを使用して Webhook エンドポイントを登録する必要があります。
Stripe は、「アカウント」と「Connect」の 2 つのエンドポイントタイプに対応しています。Connect アプリケーションを作成している場合を除き、「アカウント」でエンドポイントを作成します。次のステップを使用して、開発者ダッシュボードで Webhook エンドポイントを登録します。Stripe アカウントごとに最大 16 の Webhook エンドポイントを登録できます。
- Webhook ページに移動します。
- エンドポイントを追加をクリックします。
- エンドポイント URL に、Webhook エンドポイントの HTTPS URL を追加します。
- 「Stripe Connect」アカウントをお持ちの場合は、説明を入力してから連結アカウントでイベントをリッスンするをクリックします。
- イベントを選択では、ローカル Webhook エンドポイントで現在受信しているイベントタイプを選択します。
- エンドポイントを追加をクリックします。
Stripe API を使用して Webhook エンドポイントを登録する
プログラムで Webhook エンドポイントを作成することもできます。
連結アカウントからイベントを受信するには、connect パラメーターを使用します。
次の例では、支払いが成功または失敗したときに通知するエンドポイントを作成します。
エンドポイントを保護する
ハンドラですべての Webhook リクエストが Stripe によって生成されたものであることを確認して、実装を保護することを強くお勧めします。公式ライブラリを使用して Webhook の署名を検証するか、手動で検証するかを選択できます。
Webhook との連携のデバッグを行う
Webhook エンドポイントにイベントを送信する際に、以下のような複数のタイプの問題が発生することがあります。
- Stripe が Webhook エンドポイントにイベントを送信できない可能性がある
- Webhook エンドポイントで SSL の問題が発生している可能性がある
- ネットワーク接続が断続的である
- Webhook エンドポイントが、受信する予定のイベントを受信していない
イベントの送信を表示する
注
アカウントでワークベンチを有効にした場合は、ワークベンチを使用してイベントの送信先を管理する必要があります。
特定のエンドポイントのイベント送信を表示するには、Webhook タブで Webhook エンドポイントを選択します。
アカウントでトリガーされたすべてのイベントを確認するには、イベントタブを選択します。
HTTP ステータスコードを修正する
イベントにステータスコード 200
が表示されている場合は、Webhook エンドポイントへの送信が成功したことを示しています。200
以外のステータスコードを受信する場合もあります。次の表で、一般的な HTTP ステータスコードと推奨される解決方法の一覧をご覧ください。
保留中の Webhook ステータス | 説明 | 修正 |
---|---|---|
(接続不可) ERR | 宛先サーバーへの接続を確立できません。 | ホストドメインがインターネットで一般に公開されアクセス可能であることを確認します。 |
(302 ) ERR (またはその他の 3xx ステータス) | 宛先サーバーがリクエストを別の場所にリダイレクトしようとしました。Webhook リクエストへのリダイレクト応答は失敗と見なされます。 | Webhook エンドポイントの送信先を、リダイレクトによって解決される URL に設定します。 |
(400 ) ERR (またはその他の 4xx ステータス) | 宛先サーバーがリクエストを処理できないか、処理しません。これは、サーバーがエラーを検出した場合 (400 )、宛先 URL にアクセス制限が設定されている場合 (401 、403 )、または宛先 URL が存在しない (404 ) 場合に発生することがあります。 |
|
(500 ) ERR (またはその他の 5xx ステータス) | リクエストの処理中に、宛先サーバーでエラーが発生しました。 | アプリケーションのログを確認して、500 エラーが返されている理由を調べます。 |
(TLS エラー) ERR | 宛先サーバーへの安全な接続を確立できませんでした。これらのエラーは通常、宛先サーバーの証明書チェーン内の SSL/TLS 証明書または中間証明書の問題が原因で発生します。 | SSL サーバーテストを実行して、このエラーの原因となった可能性がある問題を見つけます。 |
(タイムアウト) ERR | 宛先サーバーで Webhook リクエストに応答するのに時間がかかりすぎました。 | Webhook 処理コードで複雑なロジックを延期して、成功を示すレスポンスを即時に返すようにしてください。 |
イベント送信の動作
このセクションは、Stripe が Webhook エンドポイントにイベントを送信する際に想定されるさまざまな動作を理解するのに役立ちます。
再試行の動作
本番環境では、Stripe は指数バックオフを使用して最長 3 日間、お客様の Webhook エンドポイントに対する特定のイベントの配信を試行します。ダッシュボードのイベントセクションで、次回の再試行が発生する時期を確認できます。
テスト環境では、Stripe は数時間にわたって 3 回再試行します。これ以降は、ダッシュボードのイベントセクションを使用して、自身の Webhook エンドポイントに対して各イベントの送信を手動で再試行できます。逃したイベントに対してクエリを実行して、任意の期間のデータを照合することもできます。
特定のエンドポイントに対して各 Webhook イベントの送信を手動で再試行して、その再試行が成功した場合でも、自動での再試行は継続されます。
Stripe が再試行しようとしたときに、お客様のエンドポイントが無効であるか削除されていた場合、それ以降、そのイベントは再試行されません。ただし、お客様が Webhook エンドポイントを無効にした後、Stripe から再試行を実行するタイミングより前にその Webhook エンドポイントを再度有効化した場合は、以降の再試行は引き続き行われます。
動作を無効にする
テスト環境と本番環境で、エンドポイントが 2xx
HTTP ステータスコードで応答しない状況が連続して何日も続いた場合、Stripe は、設定が正しくないエンドポイントについて、メールで通知します。このメールには、エンドポイントが自動的に無効化される時期も示されます。
API のバージョン管理
イベント発生時のアカウント設定の API バージョンによって API バージョンが決まり、さらに Webhook で送信される Event
オブジェクトの構造が決まります。たとえば、お客様のアカウントで 2015-02-16 など、以前の API バージョンが設定されている場合、バージョン管理を利用して特定のリクエストの API バージョンを変更しても、生成されお客様のエンドポイントに送信される Event
オブジェクトは 2015-02-16 API バージョンに基づきます。
Event
オブジェクトは、作成後に変更することはできません。たとえば、支払いを更新しても、元の支払いイベントは変更されません。このため、自身のアカウントの API バージョンを後から更新しても、既存の Event
オブジェクトが遡及的に変更されることはありません。新しい API バージョンを使用して /v1/events
を呼び出して以前のイベントを取得しても、受信したイベントの構造には影響しません。
テスト用の Webhook エンドポイントは、デフォルトの API バージョンか、最新の API バージョンのいずれかに設定できます。Webhook URL に送信される Event
は、エンドポイントに指定されているバージョンに従って構造化されます。また、プログラムによって、特定の api_version のエンドポイントを作成することもできます。
イベントの順序付け
Stripe は、イベントが生成された順序で配信されることを保証しません。たとえば、サブスクリプションを作成することで、次のイベントが生成されるとします。
customer.subscription.created
invoice.created
invoice.paid
charge.created
(支払いが付随する場合)
これらのイベントはこの順序どおりに配信されるとは限らないため、お客様のエンドポイントは、状況に応じて配信を処理する必要があります。API を使用して不足しているオブジェクトを取得することもできます (たとえば、最初に受信したイベントが invoice.paid
であった場合は、それに含まれる情報を使用してインボイス、支払い、サブスクリプションの各オブジェクトを取得できます)。
Webhook 使用のベストプラクティス
以下のベストプラクティスを参照して、Webhook のセキュリティを確保し、構築済みのシステムと適切に連携するようにしてください。
重複するイベントを処理する
Webhook エンドポイントは、同じイベントを複数回受信する可能性があります。イベント処理をべき等にすることで、重複するイベントの受信に対処することができます。これを実施する 1 つの方法として、処理したイベントをログに記録し、すでにログに記録したイベントを処理しないようにする方法があります。
構築済みのシステムに必要なイベントタイプのみをリッスンする
必要なイベントのタイプのみを受信するように、Webhook エンドポイントを設定します。その他のイベント (またはすべてのイベント) をリッスンすると、お客様のサーバーに過度の負荷がかかるため、お勧めしません。
ダッシュボードまたは API で、Webhook エンドポイントが受信するイベントを変更できます。
イベントを非同期で処理する
非同期キューで受信したイベントを処理するようにハンドラを設定します。非同期でイベントを処理することを選択した場合は、拡張性の問題が発生する可能性があります。Webhook の配信が急増すると (たとえば、すべてのサブスクリプションが更新される月初など)、エンドポイントホストが対処不可能になる場合があります。
非同期キューを使用することで、同時に発生するイベントをシステムが対応できる速度で処理できるようになります。
Webhook ルートを CSRF 保護から除外する
Rails、Django、その他のウェブフレームワークを使用している場合、貴社のサイトでは、すべての POST リクエストに 「CSRF トークン」が含まれていることを自動的に確認している可能性があります。これは、貴社とそのユーザーをクロスサイトリクエストフォージェリ の試行から保護するための重要なセキュリティ機能です。ただし、このセキュリティ対策は貴社サイトにおける正当なイベントの処理を妨げる可能性があります。この場合は、Webhook ルートを CSRF 保護から除外しなければならない可能性があります。
HTTPS サーバーでイベントを受信する
Webhook エンドポイントに HTTPS URL を使用する場合、Stripe は Webhook データを送信する前に、お客様のサーバーへの接続が安全であることを確認します。これを機能させるには、サーバーが、有効なサーバー証明書で HTTPS をサポートするように正しく設定されている必要があります。本番環境では HTTPS URL が必要です。Stripe の Webhook は現在、TLS v1.3 をサポートしていません。
エンドポイントの署名シークレットを定期的に取り消す
イベントが Stripe から送信されていることを確認するために使用するシークレットは、ダッシュボードの Webhook セクションで変更できます。エンドポイントごとに、シークレットを更新をクリックします。現在のシークレットキーをただちに有効期限切れにすることも、有効期限を最大 24 時間延長して、自社のサーバーの検証コードをご自身で更新する時間を確保することもできます。この間は、エンドポイントに対して複数のシークレットキーが有効です。Stripe は、有効期限までシークレットキーごとに 1 つの署名を生成します。
イベントが Stripe から送信されたことを検証する
Stripe は、設定された IP アドレスリストから Webhook イベントを送信します。これらの IP アドレスから送信されたイベントのみを信頼してください。
この他、Webhook の署名を確認して、受信したイベントが Stripe から送信されたものであることを確かめてください。Stripe はエンドポイントに送信する Webhook イベントに署名するために、各イベントの Stripe-Signature
ヘッダーに署名を含めます。これにより、お客様は、イベントがサードパーティーではなく Stripe によって送信されたことを検証できます。署名を検証するには、Stripe の公式ライブラリを使用するか、自社のソリューションを使用して手動で検証します。
次のセクションでは、Webhook の署名を検証する方法を説明します。
- エンドポイントのシークレットを取得します。
- 署名を検証します。
エンドポイントのシークレットを取得する
ダッシュボードの Webhook セクションを使用します。シークレットを取得するエンドポイントを選択し、ページ右上でシークレットを探します。
Stripe は、エンドポイントごとに一意のシークレットキーを生成します。テスト API キーと本番 API キーの両方に同じエンドポイントを使用する場合、シークレットはそれぞれ異なります。さらに、複数のエンドポイントを使用する場合は、署名を検証するエンドポイントごとにシークレットを取得する必要があります。その後、Stripe はエンドポイントに送信する各 Webhook への署名を開始します。
リプレイ攻撃を防止する
リプレイ攻撃とは、攻撃者が有効なペイロードとその署名を傍受し、それを再送信することを言います。そのような攻撃を低減するために、Stripe は Stripe-Signature
ヘッダーにタイムスタンプを含めています。このタイムスタンプは署名されたペイロードの一部であるため、署名によっても検証され、攻撃者は署名を無効にしなければタイムスタンプを変更できません。署名が有効でもタイムスタンプが古すぎる場合は、アプリケーションにペイロードを拒否させることができます。
Stripe のライブラリには、タイムスタンプと現在時刻の間に 5 分のデフォルトの許容範囲があります。この許容範囲は、署名を検証する際に追加のパラメーターを指定することで変更できます。ネットワークタイムプロトコル (NTP) を使用して、サーバーのクロックが正確であり、Stripe のサーバーの時間と同期していることを確認します。
Stripe は、イベントをエンドポイントに送信するたびにタイムスタンプと署名を生成します。Stripe がイベントを再試行する場合 (たとえば、その前にエンドポイントが 2xx
以外のステータスコードで応答した場合)、新しい配信試行に対して新しい署名とタイムスタンプを生成します。
2xx レスポンスを素早く返す
エンドポイントは、タイムアウトを発生させかねない複雑なロジックの前に、素早く成功のステータスコード (2xx
) を返す必要があります。たとえば、会計システムで顧客の請求書を支払い済みとして更新する前に、200
のレスポンスを返す必要があります。