Webhook エンドポイントで Stripe イベントを受信する
Webhook エンドポイントの Stripe アカウントでイベントをリッスンし、実装で自動的にリアクションをトリガーできるようにします。
AWS アカウントにイベントを送信する
イベントの送信先を使用して Amazon EventBridge に直接、イベントを送信できるようになりました。
Stripe のシステムを構築する際、自社のアプリが Stripe アカウントで発生するイベントを受信できるようにすることをお勧めします。こうすることで、バックエンドシステムは適宜アクションを実行できます。
HTTPS Webhook エンドポイントでイベントを受信するためのイベントの送信先を作成します。Webhook エンドポイントを登録すると、Stripe は、Stripe アカウントで Event (イベント) が発生した際に、リアルタイムのイベントデータをアプリの Webhook エンドポイントにプッシュできます。Stripe は、HTTPS を使用して、Event オブジェクトを含む JSON ペイロードとして Webhook イベントをアプリに送信します。
Webhook イベントの受信は、顧客の銀行が支払いを確定したとき、顧客が支払いに対して不審請求を申請したとき、継続支払いが成功したとき、サブスクリプションの支払いを回収するときなど、非同期イベントをリッスンする際に特に便利です。
イベントの送信先を指定して Amazon EventBridge でイベントを受信することもできます。
始める
アプリで 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/webhook
注
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:4242/webhook
- Webhook の署名を確認するには、リッスンコマンドの初期出力から
{{WEBHOOK_
を使用します。SIGNING_ SECRET}}
Ready! Your webhook signing secret is '{{WEBHOOK_SIGNING_SECRET}}' (^C to quit)
テストイベントをトリガーする
テストイベントを送信するには、Stripe ダッシュボードでオブジェクトを手動で作成し、Webhook が登録されているイベントタイプをトリガーします。あるいは、Stripe Shell または Stripe CLI で次のコマンドを使用できます。
この例では、payment_
イベントをトリガーします。
stripe trigger payment_intent.succeeded Running fixture for: payment_intent Trigger succeeded! Check dashboard for event details.
Stripe for VS Code を使用してイベントをトリガーする方法をご確認ください。
エンドポイントを登録する
Webhook エンドポイント関数をテストしたら、Stripe がイベントの送信先を把握できるように、開発者ダッシュボードまたは API の Webhook セクションを使用して、Webhook エンドポイントのアクセス可能な URL を登録します。Stripe では最大 16 の Webhook エンドポイントを登録することができます。登録された Webhook エンドポイントは、パブリックアクセスが可能な HTTPS URL である必要があります。
Webhook の URL 形式
Webhook エンドポイントを登録するための URL 形式は、次のとおりです。
https://<your-website>/<your-webhook-endpoint>
たとえば、ドメインが https://mycompanysite.
で、Webhook エンドポイントへのルートが @app.
の場合、エンドポイント URL には https://mycompanysite.
を指定します。
新しい Webhook エンドポイントを作成する
You can create new event destinations for webhook and AWS EventBridge destinations.
注
既存の開発者ダッシュボードはワークベンチに置き換えられます。開発者ダッシュボードを引き続き使用している場合は、新しい 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 証明書または中間証明書の問題によって発生します。Stripe では、TLS バージョン v1.2 以降が必要です。 | SSL サーバーテストを実行して、このエラーの原因となった可能性がある問題を見つけます。 |
(タイムアウト) ERR | 宛先サーバーで Webhook リクエストに応答するのに時間がかかりすぎました。 | Webhook 処理コードで複雑なロジックを延期して、成功を示すレスポンスを即時に返すようにしてください。 |
イベント送信の動作
このセクションは、Stripe が Webhook エンドポイントにイベントを送信する際に想定されるさまざまな動作を理解するのに役立ちます。
再試行の動作
本番環境では、Stripe は指数バックオフを使用して最長 3 日間、お客様の Webhook エンドポイントに対する特定のイベントの配信を試行します。ダッシュボードのイベントセクションで、次回の再試行が発生する時期を確認できます。
テスト環境では、Stripe は数時間にわたって 3 回再試行します。これ以降は、ダッシュボードの Event セクションで、Webhook エンドポイントに対して各イベントの送信を手動で再試行できます。見逃したイベントに対してクエリを実行して、任意の期間のデータを照合することもできます。
特定のエンドポイントに対して各 Webhook イベントの送信を手動で再試行して、その再試行が成功した場合でも、自動での再試行は継続されます。
Stripe が再試行しようとしたときに、お客様のエンドポイントが無効であるか削除されていた場合、それ以降、そのイベントは再試行されません。ただし、お客様が Webhook エンドポイントを無効にした後、Stripe から再試行を実行するタイミングより前にその Webhook エンドポイントを再度有効化した場合は、以降の再試行は引き続き行われます。
動作を無効にする
テスト環境と本番環境で、エンドポイントが 2xx
HTTP ステータスコードで応答しない状況が連続して何日も続いた場合、Stripe は、設定が正しくないエンドポイントについて、メールで通知します。このメールには、エンドポイントが自動的に無効化される時期も示されます。
API のバージョン管理
イベント発生時のアカウント設定の API バージョンによって API バージョンが決まり、さらに Webhook で送信される Event
オブジェクトの構造が決まります。たとえば、お客様のアカウントで以前の API バージョン (2015-02-16 など) が設定されている場合、バージョン管理を利用して特定のリクエストの API バージョンを変更しても、生成され、お客様のエンドポイントに送信される Event
オブジェクトは API バージョン 2015-02-16 に基づきます。
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.
であった場合は、それに含まれる情報を使用して請求書、支払い、サブスクリプションの各オブジェクトを取得できます)。
Webhook 使用のベストプラクティス
以下のベストプラクティスを参照して、Webhook のセキュリティを確保し、構築済みのシステムと適切に連携するようにしてください。
重複するイベントを処理する
Webhook エンドポイントは、同じイベントを複数回受信する可能性があります。処理したイベント ID をログに記録し、すでにログに記録したイベントを処理しないようにすることで、重複するイベントの受信に対処することができます。
一部のケースでは、2 つの別々の Event オブジェクトが生成され、送信されます。これらの重複を識別するには、event.
とともに data.
のオブジェクトの ID を使用します。
構築済みのシステムに必要なイベントタイプのみをリッスンする
必要なイベントのタイプのみを受信するように、Webhook エンドポイントを設定します。その他のイベント (またはすべてのイベント) をリッスンすると、お客様のサーバーに過度の負荷がかかるため、お勧めしません。
ダッシュボードまたは API で、Webhook エンドポイントが受信するイベントを変更できます。
イベントを非同期で処理する
非同期キューで受信したイベントを処理するようにハンドラを設定します。非同期でイベントを処理することを選択した場合は、拡張性の問題が発生する可能性があります。Webhook の配信が急増すると (たとえば、すべてのサブスクリプションが更新される月初など)、エンドポイントホストが対処不可能になる場合があります。
非同期キューを使用することで、同時に発生するイベントをシステムが対応できる速度で処理できるようになります。
Webhook ルートを CSRF 保護から除外する
Rails、Django、その他のウェブフレームワークを使用している場合、貴社のサイトでは、すべての POST リクエストに 「CSRF トークン」が含まれていることを自動的に確認している可能性があります。これは、貴社とそのユーザーをクロスサイトリクエストフォージェリ の試行から保護するための重要なセキュリティ機能です。ただし、このセキュリティ対策は貴社サイトにおける正当なイベントの処理を妨げる可能性があります。この場合は、Webhook ルートを CSRF 保護から除外しなければならない可能性があります。
HTTPS サーバーでイベントを受信する
Webhook エンドポイント (本番環境で必要) に HTTPS URL を使用する場合、Stripe は Webhook データを送信する前に、お客様のサーバーへの接続が安全であることを確認します。これを機能させるには、お客様のサーバーが、有効なサーバー証明書で HTTPS をサポートするように正しく設定されている必要があります。Stripe の Webhook は、TLS バージョン v1.2 および 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 のサーバーの時間と同期していることを確認します。
よくある間違い
許容値 0
は使用しないでください。許容値 0
を使用すると、最新性チェックが完全に無効になります。
Stripe は、イベントをエンドポイントに送信するたびにタイムスタンプと署名を生成します。Stripe がイベントを再試行する場合 (たとえば、その前にエンドポイントが 2xx
以外のステータスコードで応答した場合)、新しい配信試行に対して新しい署名とタイムスタンプを生成します。
2xx レスポンスを素早く返す
エンドポイントは、タイムアウトの原因となる複雑なロジックを実行する前に、成功を示すステータスコード (2xx
) を速やかに返す必要があります。たとえば、会計システムで顧客の請求書を支払い済みとして更新する前に、200
のレスポンスを返さなければなりません。