エンドポイントは何秒以内に応答する必要がありますか?
15 秒です。これは配信呼び出しの読み取りタイムアウトで、3 秒以内に確立できない接続は それより早く失敗します。どちらを超えても配信失敗として数えられ、そのレコードは再試行 スケジュールに戻されます。 したがって、リクエストの中で業務処理を行わないでください。署名を検証し、イベントを永続化し、 応答し、処理は非同期に行う — これが ベストプラクティスのページ が推奨するパターンです。応答する前に自社のサービスを 3 つ呼び出すハンドラーが、 正しく書かれた連携がFAILED として現れる最も一般的な理由です。
HTTP 200 を返しています。なぜ配信が失敗として数えられるのですか?
判定を決めているのがステータスコードではないためです。判定はレスポンスボディを読み、 配信が成功と数えられるのは次の両方が成り立つ場合だけです。- レスポンスが 2xx であること — 4xx や 5xx はボディが読まれる前に失敗します。
- ボディが、値が
successであるmessageフィールドを持つ JSON オブジェクトであること。
failed や unknown(どちらも「再送してほしい」という意味です)
のボディ、空のボディ、異なるフィールド名、HTML のエラーページ、そもそも JSON として
パースできないボディなどです。
驚きの大半を説明する具体的な点が 3 つあります。
レスポンスの Content-Type は application/json でなければなりませんか?
実務上はそうです —Content-Type: application/json を送ってください。レスポンスは JSON として
読まれるため、text/plain や text/html として配信されたボディはパースできず、
バイト列自体が {"message":"success"} であっても配信は失敗として記録されます。
公開されている 概要 が加盟店のレスポンスに
このヘッダーを示しているのは、まさにこの理由によります。
署名検証に失敗した場合、リクエストを拒否すべきですか、それともとにかく処理すべきですか?
決して処理しないでください。まず検証し、検証が通ってからのみイベントに基づいて行動して ください。これは 受け入れ要件 でもあります。検証に失敗した場合、ローカルの状態を更新してはならず、代わりに照会 API から 本当のステータスを読み取る必要があります。 何を返すかはそこから導かれます。{"message":"failed"} と応答してください。これにより
レコードは再試行スケジュールに残ります。そして原因を突き止めてください。検証が通らない署名は
どちらかの側の設定の問題であり、再試行によって自然に直ることはありません。再試行は修正では
なく猶予として扱い、その間は照会 API で突き合わせてください。
ペイロードを再シリアライズした後にのみ署名検証が失敗する場合、それが原因です。
生のリクエストボディのバイト列に対して検証してください。パースして文字列化し直した
コピーに対しては決して行わないでください。フィールドの順序、空白、数値の書式はすべて
往復によって変わりますが、署名は元のバイト列に対して計算されています。
Webhook 署名検証 を参照してください。
「8 回の再試行」とは正確に何を意味し、間隔は保証されますか?
初回を含めて 8 回の試行で、間隔は広がっていきます。スケジュールは Webhook の再試行 にあり、全体でおよそ 20 時間に わたります。 スケジュールだけでは分からない留保が 2 つあります。- 間隔は最小値であって、約束の時刻ではありません。 再試行は予定時刻に適格になり、 配信ワーカーが次にそれを拾ったときに送出されます。滞留があれば、試行は表が示すより遅く 着地することがあります。再試行が正確な時刻に届くと仮定するロジックは決して作らないでください。
- 予算を使い切ると、そのレコードは最終的に失敗となり、それ以上の自動試行は行われません。
Portal では、次回再試行時刻のない
FAILEDレコードとして表示されます。
「次回再試行時刻」が空になることがあるのはなぜですか?
自動再試行が実際にまだ予定されている間だけ値が入るためです。このフィールドは、失敗しかつ 再試行の予算が残っているレコードでは埋まり、配信済みのレコードや再試行を使い切ったレコード では空になります。 そのため、実際に読むべきはステータス単独ではなく、2 つの列の組み合わせです。すべての試行が失敗した後、どうすればよいですか?
対象オブジェクトの現在の状態をその照会 API から読み取り、突き合わせてください。信頼できる 状態は常に通知ではなくオブジェクト側にあります。 障害からの復旧のガイダンス も同じ 3 つの手順を 挙げています。オブジェクトを照会する、定期的に一括で突き合わせる、そして配信がまったく 届かない場合はサポートに連絡する、です。 エンドポイントを修正した後は、Portal から単一、複数選択、または日付範囲指定のモードで 再送することもできます。1 リクエストあたり最大 50 件です。なお、まだ壊れたままの エンドポイントに対する再送は同じ予算から 1 回分の試行を消費します。まず修正し、それから 再送してください。詳細は Webhook イベント辞書と一括再送 にあります。あるレコードで Resend がグレーアウトしているのはなぜですか?
レコードを再送できない理由はちょうど 3 つです。
このリストにないものに注目してください。すでに配信に成功したレコードは再送できます。
これは意図的です。Waffo が受理として記録した配信であっても、貴社側で処理されていない
可能性があるため、再送が許されています。
再送には、Portal のロールに webhook 再送の権限も必要です。権限がなければ、そのアクションと
行の選択は無効表示になるのではなく、そもそも描画されません。したがって再送のコントロールが
まったく見えない運用者は、レコードの適格性ではなく権限の問題を見ていることになります。
Portal の Admin に依頼してください。
各イベントのコールバック URL はどこから来ますか?
これは「通知が届かなかった」の最も一般的な原因です。URL が解決されず、何も送信されず、 レコードも書き込まれていないのです。
設計に織り込む価値のある帰結が 2 つあります。
- グローバルな決済通知 URL は存在しません。 決済通知は注文作成時に渡した
notifyUrlに のみ送られ、そのフィールドが必須なのはまさにフォールバックが存在しないためです。 Portal で 1 つのアドレスを設定してパラメータの送信をやめる、ということはできません。 - チャージバック通知にはリクエストレベルのパラメータがありません。 Portal の URL が
空の場合、それらのイベントは単に配信されず、ログのレコードも残りません。Webhook ログ
ページでチャージバックの結果が空である場合、ほぼ確実に Chargeback Notify URL が一度も
設定されていません。決済中にトークン化されたカードのトークン化通知についても同じことが
当てはまります。
notifyUrlのない単独のトークン化リクエストも同様に通知されません。
通知 URL を変更しました。すでに再試行キューにある通知はどこに届きますか?
古い URL にです。 コールバック URL は各通知レコードの作成時にそのレコードに保存され、 すべての再試行も、すべての手動再送も、保存された値に送信されます。Portal の設定を編集する、 あるいは新しい注文で別のnotifyUrl を渡すことは、その後に作成されるレコードにのみ
影響します。
URL の移行はそれに合わせて計画してください。新しい URL を保存した瞬間に切り替えるのではなく、
進行中の分がはけるまで古いエンドポイントでトラフィックを受け続けてください。
通知 URL のフィールドは何を受け付けますか? HTTPS でなければなりませんか?
保存時のバリデーションが受け付けるのは次のとおりです。http://またはhttps://で始まる URL- ASCII 文字のみ、空白なし
- ホストを持つパース可能なアドレス — ポート、パス、クエリ文字列はいずれも許可されます
- Refund Notify URL と Chargeback Notify URL は最大 512 文字
- 空の値。設定をクリアします
http:// はバリデーションを通りますが、公開されている
設定要件 は TLS 1.2 以上の HTTPS を求めており、
Webhook は決済データを運びます。
バリデーションのルールからは分かりにくい厳格な制約が 1 つあります。TLS 証明書はパブリックな
認証局によって信頼されている必要があります。 配信クライアントは例外の経路を持たない
デフォルトのトラストストアを使用するため、自己署名やその他の信頼されない証明書は接続に失敗し、
すべての試行が失敗します。プライベート CA はここでは使用できません。
同じイベントが複数回届くことはありますか? 何をキーに重複排除すべきですか?
はい、重複はありえます。ハンドラーは冪等である必要があります。受け入れ基準もまさにこれを テストします。繰り返しの原因には、内部的な再配信、手動再送、そして同じ注文についての オーソリ段階の通知とその後の最終通知が含まれます。 ペイロードにイベント ID や配信 ID はありません。 ボディは{"eventType": ..., "result": {...}} であり、注目すべきヘッダーは署名だけです。したがって、
eventType と result の中の業務識別子 — そのイベントが対象とする決済注文、返金注文、
サブスクリプション、送金注文、出金注文、またはトークン — に、貴社が処理しようとしている
ステータスを組み合わせて重複排除してください。識別子だけで重複排除すると、オーソリをすでに
記録した注文の最終ステータスを取りこぼすことになります。
到着順序は保証されますか?「失敗」が「成功」より先に届くことはありますか?
いいえ、順序は保証されません。そして、はい — 順序が入れ替わった通知を受け取ることがあります。 再試行、キューイング、ネットワーク遅延はいずれも配信の順序を入れ替えます。 これを安全にするルールは ベストプラクティスのページ にあります。 状態機械を到着順序で駆動しないでください。 各通知はトリガーとして扱い、終端の状態は オブジェクトから取得してください。ペイロードのステータスフィールドから、後戻りを防ぐガードを 付けて取得するか、通知のたびに照会 API を呼び出してください。サブスクリプションではこれが 文書化されたパターンです。ステータス通知か期間変更通知のいずれかを受けたら、 サブスクリプション照会を 1 回呼び出し、その結果に対して単一の統一フローを実行します。オーソリ後にキャプチャする注文では、オーソリ済みの段階で通知が届きますか?
はい。それは別のイベントタイプとしてではなく、最終通知と同じ注文に対するPAYMENT_NOTIFICATION として届きます。両者を区別するのはイベントではなく、
ペイロードの注文ステータスです。
これは、注文 ID だけで重複排除するのが誤りである理由でもあります。ここでは 1 つの注文に対して
2 件の通知が想定されており、終端なのはそのうち 1 件だけです。
オーソリとキャプチャ を参照してください。
通知が終端でないステータスを運ぶことはありますか? 再照会すべきですか?
はい — 上の表が示すとおり、注文は進行中のまま通知されることがあります。終端のステータスに 基づいて行動し、終端でないものは記録して待ってください。その時点で確実性が必要なら、 推測するのではなく照会 API を呼び出してください。 貴社が自ら注文をクローズしてはならない唯一のステータスは、結果不明です。E0001 の場合は
注文を開いたままにし、同一のパラメータで再試行し、照会結果か通知を待ってください。
自らクローズすることは文書化された受け入れ不合格です。
連携の受け入れ基準
を参照してください。
注文がキャンセルされた、タイムアウトした、失敗したとき、通知は届きますか?
はい — 3 つともPAYMENT_NOTIFICATION を生成し、3 つとも同じ終端ステータスに着地します。
ORDER_CLOSE です。個別の CANCELLED、EXPIRED、FAILED というステータス値は
存在しません。
これらを区別するには、ペイロードの orderFailedReason が運ぶ失敗の詳細を読んでください。
そこには orderFailedCode と orderFailedDescription が含まれます。したがって正しい
ハンドリングの形はこうです。ORDER_CLOSE は「履行しない」を意味し、orderFailedReason が
顧客に何と伝えるべきか、再試行に意味があるかを教えてくれます。
イベントを購読する必要がありますか、それともすべて自動的に発火しますか?
購読の登録簿はなく、イベントごとのオプトインもありません。イベントは、上の表に従って コールバック URL が解決されるたびに配信されます。つまり、何を受け取るかの制御は、 どの URL が存在するかの制御そのものです。 最小限の連携における実務的な読み方はこうです。注文作成時にnotifyUrl を渡して決済通知を
処理し、ハンドラーを作っていないイベント系統については Portal で設定する URL を空のままに
しておき、それらの状態は代わりに照会 API から拾ってください。列挙できるすべての
オブジェクトでポーリングが機能します。チャージバックは /api/v1/chargeback/list と
/api/v1/chargeback/inquiry、トークンの状態は /api/v1/tokenization/inquiry です。
代償はレイテンシです。そしてチャージバックについては、証拠の提出期限が案件の作成時点から
進行するため、異議申し立てを少しでも扱うなら、ポーリングに頼るのではなく
Chargeback Notify URL を設定してください。
Portal の Webhook ページで、送金と出金の通知を見つけられますか?
このページからは見つけられません。Webhook ログのページが検索するのは固定された 7 つの イベント系統 — 決済、返金、トークン化、チャージバック、そして 3 つのサブスクリプション イベント — であり、送金と出金の通知はそこに含まれていないため、どのようにフィルターしても 表示されません。 それらについては、送金と出金の照会 API から状態を読み取ってください。また、設定上の 非対称性にも注意してください。どちらも Portal で設定する URL を持たないため、その通知先は それらを作成したリクエストで渡した値そのものです。通知が一度も配信されなかったことを、どうすれば分かりますか?
現時点では、知らされるのではなく自分で見にいくことによってです。配信が失敗したときの 加盟店向けのアラートはなく、通知レコードを照会する加盟店向け API もありません。 方法は 2 つです。- Portal の Webhook ログ、その 90 日のウィンドウ内で — 失敗で絞り込み、 次回再試行の列を使って「まだ再試行中」と「最終的に失敗」を切り分けます。
- 照会 API に対する突き合わせ。 終端の状態を期待しているオブジェクトを定期的に照会し、 自社のレコードと比較します。これが推奨される安全網であり、Portal ページが追跡しない イベントもカバーする唯一の方法です。
許可リストに登録できる固定の IP アドレスから配信していますか?
Webhook 配信について公開されている送信元 IP レンジはなく、静的な送信元アドレスも設定されて いません。したがって固定できるものはありません。Waffo のコールバック元を IP で許可リストに 登録することは、設計の前提にすべきものではありません。 代わりにすべきことは、送信元ではなくコールバックそのものを認証することです。すべての Webhook は 生のボディに対する署名を運んでおり、Waffo の秘密鍵で署名され、Merchant Portal → Integration から取得できる Waffo の公開鍵で検証できます。検証済みの署名は送信元 IP の一致より強い保証で あり、インフラが変わっても壊れません。開発中に自分のノート PC でコールバックを受け取るにはどうすればよいですか?
notifyUrl はパブリックなインターネットから到達可能である必要があります。localhost や
プライベートアドレスには到達できません。トンネリングツールを使い、そのトンネルの公開 URL を
notifyUrl として登録してください。公開されている
概要 に、よく使われる 2 つのツールのコマンドが
示されています。
実務上の点が 2 つあります。トンネルのホスト名は再起動のたびに変わるのが普通なので、
URL は Portal の設定に保存するのではなく注文ごとに渡してください。また、提示される証明書は
パブリックに信頼されたものである必要があります。ホスト型のトンネルはそれを提供しますが、
ローカルの自己署名サーバーは提供しません。
サンドボックスの配信も、再試行スケジュールを含めてこの同じ契約に従います。そもそも サンドボックスで何を起こせて何を起こせないかについては サンドボックスのシミュレーション制限 FAQ を参照してください。