プレイブック
決済システムにおける Webhook の信頼性 (Webhook)
Webhook が繰り返されたり、消えたり、順序が乱れたり、遅れて到着したりします。署名を検証し、迅速な ACK を返し、同期的な重労働を実行しないでください。
分散型決済エンジン
一部 6 の 22
取得と完了の間のギャップを埋める一連の分散型支払いアーキテクチャ。
Webhook は保証されたメッセージではありません
PSP が送信する Webhook は、「このイベントが正しい順序で 1 回だけ発生する」ことを保証しません。むしろ、同じイベントが複数回到着する可能性がある、イベントがまったく到着しない可能性がある、イベントが送信された順序とは異なる順序で到着する可能性がある、イベントが数分遅れて到着する可能性がある、という 4 つの異なる方法に分類できます。```text PSP → Webhook ⚠ Duplicate: aynı olay iki kez ⚠ Missing: olay hiç gelmez ⚠ Out-of-order: capture bildirimi, authorize bildiriminden önce gelir ⚠ Delayed: olay dakikalar sonra ulaşır
## 最初に説明した概念```text
📦 Webhook
Bir dış sistemin (PSP), kendi tarafında gerçekleşen bir olayı bildirmek için sizin uç noktanıza yaptığı HTTP çağrısı.
📦 Signature Verification
Gelen webhook'un gerçekten PSP'den geldiğini, içeriğin değiştirilmediğini doğrulayan kriptografik kontrol.
📦 At-least-once Delivery
Bir olayın en az bir kez, bazen daha fazla kez teslim edileceğini garanti eden; ama sıra veya tekrar sayısı garantisi vermeyen teslimat modeli.
📦 ACK (Acknowledgement)
Webhook alıcısının, olayı aldığını PSP'ye bildiren hızlı HTTP cevabı (genellikle 200).
📦 Durable Write
İşlemin sonucu ne olursa olsun, olayın kalıcı depoya yazılmış olması; bellek içinde kalan bir kayıt değildir.
```これらの概念はすべて、1 つのルールに従っています。つまり、Webhook ハンドラーは、受信イベントが何であれ、最初に安全に記録し、その後で初めて面倒な作業を実行する必要があります。
## 重複: 同じイベントが 2 回発生します
PSP が時間内に 200 応答を受信しなかった場合 (ネットワークの問題、サーバーの遅さ)、同じイベントが再送信されます。この動作はバグではなく、PSP の少なくとも 1 回の保証の自然な結果です。 5 番目のセクションで詳しく説明したイベント ID + 受信箱のパターンが、ここでの防御の第一線となります。```text
Webhook #1: evt_001 → işlenir
Webhook #2: evt_001 (tekrar) → inbox'ta zaten var, işlem atlanır, 200 döner
```## Missing: イベントが来ない
ネットワークの停止、PSP 側のエラー、またはエンドポイントが一時的に到達できないなど、Webhook がまったく到着しない場合があります。 Webhook のみに依存するシステムは、永久に「不明」状態のままになります。だからこそ、Webhook が唯一の真実の情報源ではなく、主要な通知チャネルであるべきなのです。 PSP のステータス クエリ API との定期的な調整は、常に二次的なセーフティ ネットとして機能する必要があります。```text
Webhook (birincil, hızlı)
+ Periyodik durum sorgusu (ikincil, yavaş ama garantili)
= webhook kaybolsa bile gerçek er ya da geç yakalanır
```## 順不同: イベントは順不同で到着します
ネットワーク層は、イベントが送信された順序で到着することを保証しません。たとえば、「キャプチャ」通知は、それより先に到着すると予想されている「許可」通知よりも前に到着する可能性があります。ハンドラーがイベントによって運ばれるタイムスタンプやバージョン番号をチェックせずにステート マシンを更新する場合、ここで 2 番目の部分で説明したガードが機能します。```text
Gelen: payment.captured (t=2)
Gelen: payment.authorized (t=1, ama sonra ulaştı)
→ guard: t=1 olayı, zaten t=2'ye ulaşmış bir state'i geriye alamaz, sessizce reddedilir
```## 遅延: イベントの到着が遅れています
PSP 側のキューイングまたはユーザー側の処理遅延により、Webhook が到着するまでに数分かかる場合があります。この場合、ハンドラーは「現在」と「イベントが発生した瞬間」を区別する必要があります。イベント自体のタイムスタンプではなく、イベントが処理される瞬間に基づいてビジネス上の意思決定が行われる場合、シーケンス エラーはさらに大きくなります。
## ヘビーデューティーを同期的に実行すべきではない理由
Webhook ハンドラーでは、署名の検証、最小限の検証、永続的な書き込み以外の重労働を実行する必要はありません。在庫削減、財務記録、通知の送信などのステップは、別のバックグラウンド ジョブに転送する必要があります。```text
Webhook Handler (hızlı, senkron)
1. İmzayı doğrula
2. Minimal şema kontrolü yap
3. Olayı inbox'a yaz (durable)
4. 200 OK döndür
Arka plan Job (yavaş, asenkron)
5. İnbox'taki olayı oku
6. Gerçek iş kararlarını uygula (stok, finans, bildirim)
```この区別は 2 つの理由から重要です。まず、PSP は通常、Webhook 応答に短いタイムアウト (数秒) を課します。負荷がこの時間を超えると、PSP はリクエストが失敗したとみなして再送信するため、重複の数が増加します。次に、高負荷の同期操作により、Webhook ハンドラーが外部システムのパフォーマンスに依存するようになります (ストック サービスが遅い場合)。この依存関係により、Webhook 自体がタイムアウトになる可能性もあります。
## このエピソードで最も混乱を招く対戦```text
❌ Webhook, tek ve güvenilir gerçek kaynağıdır
✓ Webhook birincil bildirim kanalıdır; periyodik durum sorgusu ikincil güvenlik ağıdır
❌ 200 dönmek, işin tamamlandığı anlamına gelir
✓ 200, olayın güvenle alındığı anlamına gelir; işin tamamlanması ayrı bir asenkron adımdır
❌ Webhook'lar her zaman gönderildiği sırayla ulaşır
✓ Sıralama garanti edilmez; guard'lar olmadan state machine geriye kayabilir
❌ İmza doğrulaması opsiyoneldir, IP allowlist yeterlidir
✓ İmza doğrulaması, sahte veya değiştirilmiş webhook'lara karşı asıl savunmadır
Webhook ハンドラーのチェックリスト
- Webhook ハンドラーはすべてのリクエストで署名検証を実行しますか、それとも IP ホワイトリストにのみ依存しますか?
- イベントを受信箱に書き込む前に、ハンドラーはどのような重いタスクを同期的に実行しますか?
- Webhook が届かない場合、システムがそれに気づくまでに何時間/何日かかりますか?和解の仕事はありますか?
- 2 つの Webhook が順番どおりに到着しないと、ステート マシンが無効な状態になる可能性がありますか?警備員をテストしましたか?
- PSP の Webhook タイムアウトはどれくらいですか? ハンドラーはそのタイムアウトをどれくらい使用していますか?
これら 5 つの質問のいずれかに対して「いいえ、確認しませんでした」と答えた場合、あなたの Webhook の信頼性はおそらくテストされていない仮定に基づいています。
このセクションで覚えておくべきこと
- Webhook が重複したり、欠落したり、順序が乱れたり、遅れたりする可能性があります。ハンドラーは 4 つすべてを前提として考慮する必要があります。
- 署名の検証は、不正な Webhook に対する主な防御線です。 IP 許可リストだけでは十分ではありません。
- ハンドラーは高速 ACK を発行し、面倒な作業を非同期ジョブに引き渡す必要があります。同期的な負荷の高い作業では、タイムアウトと重複の両方のリスクが増加します。
- Webhook は主要なチャネルですが、唯一の真実の情報源ではありません。定期的なステータスのポーリングは、常に二次的なセーフティ ネットである必要があります。
「将来」として Webhook に依存するのは仕様ではありません。 「来ないかもしれない、また来るかもしれない、故障するかもしれない」ということをデザインするのがデザインです。
FAQ
よくある質問
Webhookとは何ですか?
外部システム (PSP) からエンドポイントへの HTTP 呼び出し。エンドポイントで発生したイベントを通知します。
署名検証とは何ですか?
受信 Webhook が実際に PSP から送信されたものであること、およびコンテンツが変更されていないことを検証する暗号化コントロール。
「Webhook が唯一信頼できる真実の情報源である」というのは本当ですか?
Webhook は主要な通知チャネルです。定期的なステータスクエリは二次的なセーフティネットです
このセクションでは何を修正しますか?
このセクションでは、Webhook ハンドラーをこれら 4 つのシナリオに対して回復力のあるものにする方法について説明します。 Webhook は重複したり、欠落したり、順序が乱れたり、遅れたりする可能性があります。ハンドラーは 4 つすべてを前提として考慮する必要があります。 PSP が送信する Webhook は、「このイベントが正しい順序で 1 回だけ発生する」ことを保証しません。むしろ、同じイベントが複数回到着する可能性がある、イベントがまったく到着しない可能性がある、イベントが送信された順序とは異なる順序で到着する可能性がある、イベントが数分遅れて到着する可能性がある、という 4 つの異なる方法に分類できます。
学んだエンジニアリング原則
- Webhook ハンドラーは署名を検証し、イベントを永続的に記録し、高速 ACK を発行します。面倒な作業は常に非同期ジョブに委任されます。
- Webhook は主要な通知チャネルであり、唯一の信頼できる情報源ではありません。定期的なステータスのポーリングは、常に二次的なセーフティ ネットである必要があります。
- 重複、欠落、故障、配送の遅延。これは Webhook のデフォルトの動作であり、例外ではありません。
続きを読む
続きを読む
シリーズの次のシリーズ
決済システムにおける送信箱/受信箱のパターン
データベースへの書き込みとイベントのパブリッシュが同じトランザクション内にない場合、そのうちの 1 つが失われるか、繰り返されます。送信トレイのブロードキャスト、コンシューマでの受信トレイの重複排除。
シリーズの次のシリーズ
API (アプリケーション プログラミング インターフェイス) リクエストを超えた冪等性 (反復可能で安全なトランザクション)
冪等性は単一のヘッダーではありません。これは、API キーからステップ ポインターまで、5 つの異なるレイヤーで個別に設定する必要がある防御スタックです。
同じシリーズ
支払い証明書と支払いステータス: 混同すべきではない理由
PSPがそう言っているのが証拠です。状態はあなたが決めるものです。これら 2 つを同じレジストリに保存しておくと、回復中にどちらを信頼すればよいかがわかります。