Home
>
Docs
>
>

再試行と冪等性

Webhook配信失敗時の再試行の仕組みと、イベントIDを用いた重複排除の方法について説明します。

エンドポイントがWebhookを2xxレスポンスで確認応答しない場合、Jammは再試行します。これを安全に処理するため、エンドポイントは冪等である必要があります — 同じイベントを2回受信しても、重複した処理が発生してはいけません。


再試行

エンドポイントが2xx以外のレスポンスを返すか、2分以内に応答しない場合、Jammは指数バックオフで配信を再試行します:

  • 最大試行回数: 最大20回の試行。
  • バックオフ: 1時間から始まり、試行ごとに2倍になります(上限3時間)。
  • 期間: 再試行はJammが中止するまで約2日間にわたります。
  • IDの安定性: Webhookのidはすべての試行で変わらないため、重複排除に利用できます。

イベントへの応答

HTTPレスポンスのステータスコードで、Jammが再試行するかどうかが決まります:

状況応答理由
イベントを正常に処理できた2xx確認応答 — 再試行なし。
一時的な失敗(DB停止、タイムアウト、参照先レコードが未作成など)2xx以外(またはタイムアウト)Jammが再送するため、一時的な問題は自然に解消します。
恒久的な失敗(不明なID、不正なデータ、処理対象外のイベント)2xx + 自身でアラート恒久的なエラーは再試行しても解決しません。確認応答したうえで、内部でアラートを出して調査してください。

重要なガイドライン

  • 再試行は競合の解決策ではありません: 再試行は数時間間隔です。2xx以外は、ミリ秒単位の競合の解決策にはなりません。自身のレコードが作成される前にイベントが届き得る場合は、確認応答してAPIで整合を取ってください — 1時間後の再送を待たないでください。
  • 永続化してから確認応答する: 理想的には、イベントを受信・保存できない場合にのみ2xx以外を返してください。保存できたら2xxを返し、処理は自社インフラで独自の再試行により行ってください — Jammの再送をジョブキュー代わりに使わないでください。
  • 上限に達する前にエスカレーションする: 一時的な失敗で2xx以外を返す場合は、同じidが約5回配信失敗したら、2xx + アラート + 整合に切り替えます。

冪等性

再試行により、同じイベントがエンドポイントに複数回届く場合があります。Webhookペイロードのidフィールドを使って重複を排除してください。

idmwh-*形式)は:

  1. イベントごとに一意 — 異なるイベントは異なるIDを持ちます。
  2. 再試行をまたいで不変 — 同じイベントIDがすべての再試行で送信されます。

シンプルな重複排除パターン

async function handleWebhook(payload) {
  if (await alreadyProcessed(payload.id)) {
    return { ok: true }; // 確認応答するが処理はスキップ
  }
  await processEvent(payload);
  await markProcessed(payload.id);
}

⏱️ 保存期間: 処理済みのIDは、少なくともJammの再試行期間(約2日間)の間は保存してください。


取りこぼしたイベントの整合

Webhookの配信を保証されたものとして扱わないでください。確定した状態は常にAPIにあります。そこで確認してください:

  • 決済の結果GetCharge(またはGetCharges)を呼び出してcharge_statusCHARGE_STATUS_SUCCESSCHARGE_STATUS_FAILUREなど)を読み取ります。
  • 返金GetChargeを呼び出してcharge_status = CHARGE_STATUS_REFUNDED(当日キャンセルの場合はCHARGE_STATUS_CANCELLED)を確認します。amount_refundedはbuyerに返金された合計額、initial_amountは元の決済額であり返金可能な上限です。
  • カスタマー/契約の有効化GetCustomerを呼び出してactivatedを確認するか、GetContractで契約状況を確認します。

対象オブジェクトでの冪等性

APIルックアップを行う場合は、Webhook IDではなく対象オブジェクトのIDをキーにしてください。APIルックアップはmwh-*の識別子を持ちません。

  • 決済・返金イベントは決済ID(trx-*をキーにします。
  • 契約・アカウントイベントはカスタマーID(cus-*をキーにします。

ベストプラクティス

  • 速やかに確認応答する — イベントを永続化したらすぐに2xxを返し、重い処理は非同期で行う。
  • IDで重複排除する — 下流の処理を実行する前にmwh-* IDを確認する。
  • 署名を検証する — ペイロードのデータに基づいて処理する前に署名を検証する(Signature Verificationを参照)。
  • 恒久的な失敗ではアラートを出し、再試行させない2xxを返して内部でログ/アラートを出す。
  • 重要な状態の整合を取る — 配信だけに依存せず、GetCustomer / GetChargeで確認する。
  • イベント順序に寛容になる — 再試行ではイベントが順不同で配信される場合があります。到着順ではなくcreated_atevent_typeに依拠してください。
Was this page helpful?
Need help? Coming Soon
Support Center Slack community Contact us
Sign up for our developer newsletter: Coming Soon
You can unsubscribe at any time. Read our
privacy policy and terms and conditions.
jaen