> ## Documentation Index
> Fetch the complete documentation index at: https://waffo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook ペイロードのフィールド FAQ

> Webhook のボディのどのフィールドが自社の注文番号なのか、カードの BIN と下 4 桁が実際にはどこにあるのか、送金の手数料フィールドはどれを使うべきか、失敗した課金期間はどう表現されるのか、そして通知のボディが対応する照会レスポンスとどう異なるのかを説明します。

イベントの一覧と「これはどの照会に対応するか」の対応表は
[Webhook イベントタイプ一覧](/docs/ja/developer-docs/webhook/event-types) にあります。
完全なフィールドのスキーマは [API リファレンス](/docs/api-reference/introduction) にあります。
配信のルール — タイムアウト、受理されるレスポンス、再試行、URL の解決 — は
[Webhook 配信契約 FAQ](/docs/ja/support/webhook-delivery-contract-faq) にあります。

**このページが答えるのはフィールドレベルの疑問** — ハンドラーを書いていて、期待した値が
見つからないときに出てくる疑問です。

## 外側のエンベロープには何が入っていますか？

ちょうど 2 つのキーです。

```json theme={null}
{
  "eventType": "PAYMENT_NOTIFICATION",
  "result": { }
}
```

トップレベルにタイムスタンプ、通知 ID、バージョン、加盟店 ID は**ありません**。署名はボディ
ではなく `X-SIGNATURE` ヘッダーで運ばれます。したがって `eventType` でディスパッチし、
それ以外はすべて `result` から取得してください。

## `eventType` でディスパッチすべきですか、それとも `result` の中の何かでですか？

`eventType` でディスパッチしてください。それがどのイベント系統かを示し、したがって `result` の
形が決まります。`result` の中のステータスフィールドはその後、*何が起きたか*を示します。
逆にすると、1 つのイベントタイプが複数のステータスを運ぶケースで壊れます。たとえば決済通知は、
オーソリ段階でも最終状態でも同じ `eventType` です。

指針はこうです。`eventType` がパーサーを選び、`result` のステータスが業務の分岐を選びます。

## どのフィールドが自社の注文番号ですか？

どのペイロードも、貴社側と Waffo 側の両方の識別子を運びます。自社のデータベースへの結合キー
としては貴社のものを、サポートとのやり取りには Waffo のものを使ってください。

| ペイロード | 貴社の識別子 | Waffo の識別子 |
| - | - | - |
| 決済 | `merchantOrderId`、`paymentRequestId` | `acquiringOrderId` |
| 返金 | `merchantRefundOrderId`、`refundRequestId`、`origPaymentRequestId` | `acquiringRefundOrderId`、`acquiringOrderId` |
| サブスクリプション | `subscriptionRequest`、`merchantSubscriptionId` | `subscriptionId` |
| 送金 | `payoutRequestId` | `payoutOrderId` |
| チャージバック | `merchantOrderId`、`originalPaymentRequestId` | `chargebackId`、`originalOrderId` |

時間を節約する注意点が 3 つあります。

* **`paymentRequestId` は、そのリクエストのために貴社が生成した冪等性キーでもあります。**
  だからこそ、異なる金額や通貨で再利用すると `A0011` が返ります。`refundRequestId` と
  `subscriptionRequest` についても同じです。
* **チャージバックは、係争対象の注文を `originalOrderId` と呼びます。** 他のすべての
  ペイロードのように `acquiringOrderId` とは呼びません。命名のパターンが崩れる唯一の
  ペイロードであり、Portal の Webhook ログで自社の注文番号からチャージバックを検索しても
  見つかりません。
  [Webhook イベント辞書と一括再送](/docs/ja/support/webhook-events-and-resend-faq) を参照してください。
* サブスクリプション課金の決済ペイロードや返金ペイロードは、`subscriptionId`、`period`、
  `subscriptionRequest` を持つネストされた `subscriptionInfo` も運びます。これによって
  決済注文を課金期間に紐づけられます。

## カードの BIN と下 4 桁はどこにありますか？

トップレベルにはありません。カードの詳細は `paymentInfo.payMethodResponse` の中にあり、
重要な構造上の点として、**`payMethodResponse` は JSON エンコードされた*文字列*であり、
ネストされたオブジェクトではありません**。中から何かを読み取る前にパースする必要があります。

パースすると、カード関連のキーは次のとおりです。

| キー | 内容 |
| - | - |
| `maskCardData` | 先頭 6 桁と末尾 4 桁を 1 つのマスク文字列にしたもの。例：`402856******9917` |
| `cardBin` | BIN、6〜8 桁 |
| `cardLast4` | 下 4 桁 |
| `cardExpiry` | カードの有効期限 |
| `cardScheme` | カードブランド |
| `cardType`、`subCardType` | カードの区分 |
| `cardIssueCountryCode` | 発行国 |
| `cardIssuerName` | 発行会社名 |
| `schemeTransactionId` | ブランドレベルの取引参照番号 |
| `tokenId` | 決済がトークンを使用した場合の、そのトークン |

同じ文字列の中の他のキーは、為替レート、顧客が支払った金額と通貨、決済手段の参照を扱います。
公開されている説明は [API リファレンス](/docs/api-reference/introduction) を参照してください。

**いつ値が入るのか？** カード系の決済 — カード、およびその下でカードを提示する 2 つの
モバイルウォレット製品 — の場合のみです。それ以外の決済手段では、カード関連のキーは
一切現れません。したがって、パーサーはそれらすべてを任意として扱うように書いてください。
`cardBin` がないのは正常であり、エラーではありません。

`firstSix`、`first6`、`lastFour`、`last4`、`maskedCardNumber`、`cardNo` は、Waffo のどの
ペイロードにも**存在しない**フィールド名です。それらを探しているなら、求めているのは
`maskCardData`、`cardBin`、`cardLast4` です。

## 照会や通知から `userFee` を取得できますか？

いいえ。`userFee` は、加盟店向けのどの照会レスポンスにも通知ペイロードにも存在するフィールド
ではありません。

この名前は、ホスト型チェックアウトを経由しない場合に使う `orderAction` データの説明には登場しますが、
それはそのアクションのペイロードのキーであって、注文のフィールドではありません。注文に対して
実際に返される金額や手数料については
[手数料と税の取り扱い](/docs/ja/support/fee-and-tax-treatment-faq) を参照してください。

## 送金には `actFeeAmount` があります。`feeAmount` はまだ存在しますか？ どちらを使うべきですか？

**`actFeeAmount`** を使ってください。加盟店向けの送金ペイロードに `feeAmount` は存在しません。
`actFeeAmount` がそれを置き換えており、公開されている契約が運ぶのもこのフィールドです。

2 つの関連フィールドと併せて読んでください。

| フィールド | 意味 |
| - | - |
| `actFeeAmount` | 取引が完了したときに実際に徴収された手数料 |
| `feeCurrency` | `actFeeAmount` が建てられている通貨 |
| `feeStatus` | `DEDUCTED`、`RETURNED`、`NONE` |

この関係は記帳にとって重要です。`actFeeAmount` は `feeStatus` が `DEDUCTED` のときは徴収額で
あり、**`feeStatus` が `RETURNED` または `NONE` のときは `0`** です。したがって、
`feeStatus` を確認せずにゼロの手数料を「無料」と読まないでください。返還された手数料と
そもそも徴収されなかった手数料は、どちらもゼロで表示されますが意味が異なります。

命名上の罠が 1 つあります。`feeAmount` は**チャージバック**のペイロードには*まだ*存在し、
そこではチャージバック手数料を意味します。同じフィールド名で無関係な数量です。両者で
デシリアライザーを共有しないでください。

念のため送金の結果フィールドについて。`status` は `IN_PROGRESS`、`SUCCESS`、`FAILURE` です。
戻し処理は `subStatus` の `FULL_REVERSED` または `PARTIAL_REVERSED` で表現されます。
失敗は `failureCode` と `failureReason` を運びます。

## 顧客が支払った後、同じ口座に返金できるよう、その銀行口座を取得できますか？

いいえ。Payin の通知も注文照会も、顧客の銀行口座番号や口座名義人名を返しません。

それらしく見えるフィールドが 3 つありますが、いずれも違います。

| フィールド | 実際の内容 |
| - | - |
| `paymentInfo.payMethodUserAccountNo`（`payMethodUserAccountType` が `EMAIL`、`PHONE_NO`、`ACCOUNT_ID` のもの） | 注文作成時に**貴社が指定した**アカウント識別子が、そのまま返されたもの |
| `orderAction` の中の銀行情報 | 顧客が**支払い込む先**の Waffo 側の口座 — 方向が逆です |
| **返金**ペイロードの `userInfo.userBankInfo` | **返金リクエストで貴社が指定した**銀行情報。一部の決済手段の種類で、送金区間を実行するために必要です |

安心できる部分もあります。元の支払手段への返金が重要な決済手段では、返金は貴社が指定する
口座へではなく、元の決済を遡って実行されます。したがってその挙動のために口座番号は必要
ありません。返金に銀行情報が必要な場合は、API がそれを求めます。
[返金の資金源](/docs/ja/support/refund-funding-source-faq) と
[決済手段ごとの返金の制限](/docs/ja/support/payment-method-refund-limits-faq)
を参照してください。

## 未払い、キャンセル、タイムアウトの注文は、ペイロードではどう見えますか？

3 つとも `PAYMENT_NOTIFICATION` として届き、3 つとも同じ終端ステータスに着地します —
**`ORDER_CLOSE`** です。キャンセル、期限切れ、失敗を表す個別のステータス値はありません。

受け取りうる注文ステータスの完全な集合は次のとおりです。

| `orderStatus` | 終端か | 意味 |
| - | - | - |
| `AUTHORIZATION_REQUIRED` | いいえ | 顧客のオーソリ待ち |
| `PAY_IN_PROGRESS` | いいえ | 決済処理中 |
| `AUTHED_WAITING_CAPTURE` | いいえ | オーソリ済み。貴社のキャプチャ待ち |
| `CAPTURE_IN_PROGRESS` | いいえ | キャプチャ処理中 |
| `PAY_SUCCESS` | はい | 支払済み |
| `ORDER_CLOSE` | はい | 未払い |

キャンセル、タイムアウト、拒否を区別するには **`orderFailedReason`** を読んでください。
これも **JSON エンコードされた文字列**で、
`{"orderFailedCode":"...","orderFailedDescription":"..."}` という形をしています。
ステータスが `ORDER_CLOSE` のときに**のみ**存在します。成功した注文や進行中の注文では
完全に省略されるため、パーサーはデフォルト値を入れるのではなく、存在しないことを許容する
必要があります。

返金ペイロードでの相当物は `refundFailedReason`、サブスクリプションでは `failedReason` で、
どちらも同じ JSON 文字列の形です。`failReason`、`errorCode`、`errorMsg`、
`channelErrorCode`、`merchantErrorCode` という名前は、これらのペイロードには**存在しません**。

## サブスクリプションの `paymentDetails` は全履歴ですか？ 増え続けますか？

どちらもはいです。そしてこれは、長期の契約者を抱える前に設計しておく価値があります。
`paymentDetails` は**現在の期間までのすべての期間**の配列で、期間の昇順に並び、
**上限も、ページサイズも、カーソルもありません**。何年も続く月次のサブスクリプションでは、
期間ごとに要素が 1 つ増え、ペイロードもそれに伴って大きくなります。

各要素が運ぶのは次のとおりです。

| フィールド | 内容 |
| - | - |
| `acquiringOrderId` | その期間の決済注文 |
| `period` | 期間番号 |
| `orderCurrency`、`orderAmount` | その期間の請求 |
| `orderStatus` | その期間の注文のステータス |
| `orderUpdatedAt` | 最後に変更された日時 |
| `topupDetails` | その期間のアドオン注文（ある場合） |

実務上の帰結が 2 つあります。

* **ストリーム処理するかインデックスを作り、丸ごと保持しないでください。** 通知のたびに
  配列全体を差分比較するのではなく、必要な期間 — 通常は最大の `period`、またはまだ記録して
  いないもの — だけを読んでください。
* **`paymentDetails[].orderStatus` はその期間の注文自身のステータスであって、加盟店表示用の
  注文ステータスではありません。** `PAY_SUCCESS` と `ORDER_CLOSE` のほかに、請求がまだ
  保留中または再試行中の間は `INIT`、`TO_PAY`、`NEED_RETRY` になることがあります。
  最終とみなしてよいのは前者の 2 つだけです。

関連する非対称性として、サブスクリプション照会の契約では同じ名前が 2 つの異なる意味を
持ちます。**リクエスト**では `paymentDetails` はその配列を要求するフラグ（`0` または `1`、
既定は `0`）であり、**レスポンス**ではその配列そのものです。

## サブスクリプションはまだ ACTIVE ですが、ある期間の請求が失敗しました。何が届きますか？

**`SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION`** が届きます。しかも、**その期間の再試行が
尽きた後**にのみ届きます。途中の失敗した試行では通知はまったく発火しません。その期間の注文は
`NEED_RETRY` になって待機します。

ペイロードが伝える内容は次のとおりです。

| 場所 | 内容 |
| - | - |
| `subscriptionStatus` | まだ `ACTIVE` — 更新期間の失敗はサブスクリプションをクローズしません |
| `paymentDetails[].period` | どの期間が失敗したか |
| `paymentDetails[].orderStatus` | その期間については `ORDER_CLOSE` |
| `productInfo.currentPeriod` | サブスクリプションが現在いる期間 |

理由については期待値を調整してください。これは実際の制約です。トップレベルの `failedReason` は
**サブスクリプションの**失敗の詳細であって、失敗した期間のものではありません。したがって
その期間がなぜ拒否されたのかを確実に説明するものではなく、期間の要素自体は失敗コードを
持ちません。試行ごとの失敗理由を得るには、`PAYMENT_NOTIFICATION` も購読してください。
これはすべての決済試行で発火し、その試行の `orderFailedReason` を運びます。これはまさに
[サブスクリプション通知の選び方のガイド](/docs/ja/developer-docs/webhook/event-types)
が「最小」と「完全」の組み合わせの間で示している区別です。

## 更新の再試行が尽きると、サブスクリプションはキャンセルされますか？

どの期間が失敗したかによります。2 つのケースは異なる振る舞いをします。

| 再試行を使い切った期間 | サブスクリプションの結果 | イベント |
| - | - | - |
| 初回の請求（開始を遅らせた場合の有効化時の請求を含む） | サブスクリプションは `CLOSE` になる | `subscriptionStatus` が `CLOSE` の `SUBSCRIPTION_STATUS_NOTIFICATION` |
| 更新期間 | サブスクリプションは **`ACTIVE` のまま**で、次の期間も試行される | `SUBSCRIPTION_PERIOD_CHANGED_NOTIFICATION` のみ — ステータス通知はなし |

したがって、更新の再試行の尽きをキャンセルとして扱わないでください。また、期間変更の通知
だけで権利を剥奪しないでください。期間が失敗した後にアクセスを停止すべき製品であれば、
それは期間イベントに対して貴社が実装すべき方針です。Waffo が代わりにサブスクリプションを
クローズすることはありません。

**再試行は何回か？** 単一の数値はありません。再試行の回数と間隔は、貴社の加盟店契約の
更新再試行ストラテジーから来ており、期間の種類 — 日次、週次、月次、四半期、年次、
またはデフォルト — ごとに解決されます。数値を仮定するのではなく、貴社のアカウントに設定された
数値を連携サポートに確認してください。また
[サブスクリプションの再試行と決済手段](/docs/ja/support/subscription-retry-and-payment-methods-faq)
を参照してください。

## 顧客がウォレットアプリの中でキャンセルしました。どのステータスが届きますか？

**`subscriptionStatus` が `USER_CANCELLED` の `SUBSCRIPTION_STATUS_NOTIFICATION`** です。

すべてで分岐できるよう、ステータスの完全な集合は次のとおりです。

| `subscriptionStatus` | 設定される契機 |
| - | - |
| `IN_PROGRESS` | サブスクリプションが作成され、初回の請求が進行中 |
| `AUTHORIZATION_REQUIRED` | 顧客のオーソリ待ち |
| `ACTIVE` | 有効 |
| `CLOSE` | 初回の請求が最終的に失敗した後にクローズされた |
| `MERCHANT_CANCELLED` | 貴社のキャンセル API 呼び出し、または Portal からのキャンセル |
| `USER_CANCELLED` | 顧客がウォレットまたはサブスクリプション管理ページでキャンセルした |
| `CHANNEL_CANCELLED` | 決済手段の側で、基礎となる支払手段のバインドが解除された |
| `PLATFORM_CANCELLED` | Waffo によるキャンセル — `cancelReason` に値が入る唯一のステータス |
| `EXPIRED` | サブスクリプションの終了時刻を過ぎた |

なお `PLATFORM_CANCELLED` は、配信されうるにもかかわらず、サブスクリプションのステータス
フィールドの公開されている列挙一覧から抜けています。キャンセル系統の一部として扱ってください。
`MERCHANT_CANCELLED`、`USER_CANCELLED`、`CHANNEL_CANCELLED`、`PLATFORM_CANCELLED` は
いずれも「もう課金されない」を意味します。

## 通知のボディは本当に照会レスポンスと同一ですか？

たいていはそうですが、常にではありません。そして、その例外こそが驚かせるものです。

| ペイロード | 照会の `data` と同一か |
| - | - |
| 決済、返金、チャージバック、サブスクリプション変更 | はい — 対応する照会と同じコードで構築されます |
| サブスクリプションのステータス / 期間変更 | **いいえ。** 通知には**常に**完全な `paymentDetails` 配列が含まれます。サブスクリプション照会は、要求しない限りそれを省略します |
| 送金 | 送金照会と同じ型に加えて、貴社が渡した `notifyUrl` がボディにそのまま返されます |

含意が 2 つあります。

* **照会レスポンスとの差分でサブスクリプションのハンドラーを作らないでください。**
  余分な配列は想定どおりでバグではなく、サブスクリプションの Webhook が、比較した照会より
  劇的に大きくなりうる理由でもあります。
* **キーの順序が安定していると仮定しないでください。** 通知ボディのフィールドの並び順は
  何かと一致することを保証されていません。これが問題になるのは、ボディを自分でハッシュ化
  または正規化しようとしていた場合だけです。その必要はありません。受信した生のバイト列に
  対して `X-SIGNATURE` を検証してください。
  [Webhook 署名検証](/docs/ja/developer-docs/webhook/signature-verification) を参照してください。

## すべてのイベントタイプについて、完全で実際のボディの例をもらえますか？

イベントごとの例は、ここではなく [API リファレンス](/docs/api-reference/introduction)
で管理されています。各 `result` は対応する照会のレスポンスであり、API リファレンスは
稼働中の契約から生成されるためです。それが、ずれることのない唯一の写しになります。

それをフィクスチャの元にするときの注意が 2 つあります。

* 公開されているリファレンスは定期的に再生成されるため、ペイロードに存在するフィールドが
  しばらくリファレンスに載っていないことがあります。`payMethodResponse` の中のカード関連の
  キーと、サブスクリプションのアドオンの詳細が現在の例です。これらは配信されているのに、
  一部しか記述されていません。ペイロードはスーパーセットとして扱い、未知のフィールドに
  寛容なパーサーにしてください。
* **本物を捕まえられるなら、ドキュメントからフィクスチャを作らないでください。**
  サンドボックスでフローを実行し、自社のエンドポイントに届いたものを記録してください。
  それは貴社の加盟店設定と貴社の決済手段によるペイロードであり、ハンドラーが実際に
  乗り越えなければならないものです。
  [サンドボックスのシミュレーション制限 FAQ](/docs/ja/support/sandbox-simulation-limits-faq)
  を参照してください。

***


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.