Stripe で決済を扱うアプリにとって、Webhook は「あれば便利」ではなく実装上の必須要素だ。カード決済やサブスクの状態は Stripe 側で非同期に確定するため、その結果を確実に受け取る経路がなければアプリの状態と決済の状態がずれてしまう。

何を通知するか

支払いの成功・失敗、サブスクリプションの作成・更新・終了、返金やチャージバック、請求書の発行と支払い完了——課金まわりで起きるイベントが一通り飛んでくる。たとえば「決済完了 Webhook を受けて初めてアカウントを有効化する」といった設計にすれば、クライアント側の通信断や離脱でも整合性が崩れない。

実装で外せない 2 点

ひとつは署名検証。受信したリクエストが本当に Stripe からのものかを検証しないと、偽のイベントで不正にアカウントを有効化される余地が生まれる。もうひとつはリトライへの対応で、Stripe は配信失敗時に再送するため、ハンドラは同じイベントが複数回届いても結果が変わらない冪等な作りにする必要がある。

イベント順序と遅延という落とし穴

Webhook は必ずしも発生順に届くとは限らず、たとえば invoice.paid より先に customer.subscription.updated が届くこともある。アプリ側で「イベントが来た順に状態を更新する」設計にしていると不整合を招く。確定状態は Webhook の到着順ではなく、必要に応じて API で現在の状態を取り直して判断するのが堅い。テスト時は Stripe CLI でローカルにイベントを転送できるので、本番前に異常系の挙動を一通り確認しておきたい。

コストと範囲

Webhook 自体は無料で、Stripe の決済手数料とは別枠だ。当然ながら Stripe 以外の決済プロバイダのイベントは扱えない。Stripe を採用した時点でセットで設計に組み込むべき仕組みと考えてよい。

テスト環境での検証手順

Webhook はローカル開発環境に外部から届かないため、実装の検証には工夫が要る。Stripe CLI を使えば、ローカルにイベントを転送しつつ、任意のイベントを手動で発火させられる。実際に決済を行わなくても失敗・返金・紛争といったイベントを再現できるため、異常系の実装を確認できる。この手段を知らないと、本番でしか確認できない箇所が残ってしまう。

💡
受信したイベントは生のまま保存しておいてください

受信時に処理して破棄する実装だと、バグで処理に失敗したイベントを後から再処理できません。受信したペイロードをそのまま記録し、処理状態を別に持つ構成にすれば、不具合修正後に取りこぼしを再処理できます。決済という領域では、この復旧手段の有無が効いてきます。

監視すべきイベント

成功系だけを実装して満足しがちだが、運用で効いてくるのは失敗系のイベントだ。支払い失敗、サブスクリプションの更新失敗、紛争(チャージバック)の発生——これらを検知して社内に通知する仕組みがないと、売上の取りこぼしや対応期限の徒過につながる。とくに紛争には応答期限があるため、届いたことに気づける経路を必ず作っておきたい。