> ## 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.

# Payout 请求字段指南

> 构建 Payout 创建请求的逐字段解答：payoutRequestId 幂等到底如何比较请求、哪些收款人字段按国家条件必填、两种不同的日期格式、电话和 PIX key 格式、各通道的银行属性、purpose 取值、金额精度，以及 API 会拒绝哪些字段。

本页是 [Payout FAQ](/docs/zh/support/payout-faq) 的字段级配套页：Payout 创建请求的每个字段
该填什么，以及为什么一个看起来正确的值会被拒绝。关于
你到底可以向哪些通道 Payout，请参见
[Payout 钱包与覆盖范围](/docs/zh/support/payout-wallet-and-coverage-faq)。关于解读拒绝，
请参见 [Payout 错误码与重试](/docs/zh/support/payout-error-codes-and-retry-faq)。

## `payoutRequestId` 是我自己生成的吗？有什么限制？

是的——由你生成，它是幂等键。约束：

| 属性 | 值 |
| - | - |
| 由谁生成 | 你 |
| 最大长度 | 64 个字符 |
| 必填 | 是，每次创建都必填 |
| 唯一性范围 | 按商户账户和请求渠道（API Payout 和 Portal 批量 Payout 是各自独立的空间） |

Waffo 会随之返回自己的 `payoutOrderId`。两者都可用于查询：
`/api/v1/payout/inquiry` 接受 `payoutRequestId` **或** `payoutOrderId`，如果两者都传，
以 `payoutOrderId` 为准。

## 如果我复用同一个 `payoutRequestId`，具体会发生什么？

Waffo 会查找已存在的订单，并把你新请求中的**三个**字段与之比较：

* `payoutAmount`
* `payoutCurrency`
* `payoutInfo.payoutMethodUserAccountNo`

然后：

| 情形 | 结果 |
| - | - |
| 三者全部匹配 | 返回**原**订单及其当前状态。不会创建第二笔 Payout。 |
| 三者中任一不同 | 以 `A0011`（幂等参数不匹配）拒绝。不创建任何内容。 |
| 原订单已以失败结束 | 返回原订单**及其原始失败码**，而不是一次新的尝试。 |
| 两个相同的创建请求并发到达 | 一个以 `A0013` 被拒绝；另一个继续。 |

两个让人中招的后果：

* **在金额、币种和账号完全相同的情况下修改收款人的姓名、证件、地址、国家或方式，
  不会触发 `A0011`。** 比较不覆盖这些
  字段，所以你会拿回原订单，而你修改的信息会被静默忽略。绝不要
  修改收款人后用同一个 `payoutRequestId` 重发——请生成一个新的。
* **你不能用同一个 `payoutRequestId` 重发一笔失败的 Payout。** 它会返回旧的
  失败。要重试失败的 Payout，请用新的 `payoutRequestId` 创建新订单。

## 创建请求返回了 `A0013` "Too many requests"，我被限流了吗？

在 Payout 创建上，不是。那里的 `A0013` 表示针对**同一个 `payoutRequestId`** 的第二个创建请求
已经在处理中——请求按请求 ID 串行化，落败的那个被拒绝。这是
重复提交防护，不是吞吐量限制。稍作暂停后重试同一调用，或
更好的做法是先查询：第一次尝试很可能已经成功了。

## 哪些收款人字段是真正必填的？

请求 schema 在 `payeeInfo` 内只要求 `payeeId` 和 `payeeType`。其他一切都是
条件性的——它们因收款国家、Payout 方式或
收款方自身的规则而变为必填。

| 字段 | 约束 |
| - | - |
| `payeeId` | 必填。你自己对收款人的标识。 |
| `payeeType` | 必填。`INDIVIDUAL` 或 `BUSINESS`；其他任何值都会被拒绝。 |
| `payeeFirstName` / `payeeMiddleName` / `payeeLastName` | 各最长 60 个字符。按通道条件必填。 |
| `payeeFullName` | 在通道接受单个未拆分姓名的地方可用。 |
| `nationality` | 3 位字母国家代码，最长 3 个字符。 |
| `payeePhone` | 格式 `+{country code}-{number}`，例如 `+62-08990013157`。存在时校验。 |
| `payeeEmail` | 存在时校验。 |
| `payeeBirthDay`、`payeeIDIssueDate`、`payeeIDExpiryDate` | `dd/mm/yyyy`。存在时校验。 |
| `payeeIDType`、`payeeIDNumber` | 按国家条件必填——见下文。 |

`addressInfo`（`address`、`city`、`region`、`postcode`、`addressCountryCode`）是一个单独的
可选对象。通用校验中没有任何内容使其成为必填；需要它的通道
会在预检步骤以指明该字段的缺少必填字段错误拒绝 Payout，所以
有的话就传上。

## 为什么有两种不同的日期格式？

因为收款人的证件和请求信封由不同的规则校验，这
是 `A0003` 的常见来源：

| 字段 | 格式 | 示例 |
| - | - | - |
| `payeeBirthDay` | `dd/mm/yyyy` | `05/09/1990` |
| `payeeIDIssueDate` | `dd/mm/yyyy` | `12/01/2021` |
| `payeeIDExpiryDate` | `dd/mm/yyyy` | `12/01/2031` |
| `payoutRequestedAt` | ISO 8601，`yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` | `2026-09-07T02:15:30.000Z` |
| `payoutArrivalTime`、`payoutUpdatedAt`（响应） | ISO 8601，同样形式 | |

## 电话号码需要国家码吗？前导零怎么办？

以 `+{country code}-{number}` 形式发送。国内号码的前导 `0` 有些
通道会去掉，有些不会，所以请遵循通道自身的指引而不是通用规则。对于
电子钱包 Payout，电话号码可能兼作账户标识，此时格式由
收款钱包而不是本字段决定——见下文的账号问题。

## 接受哪些 `payeeIDType` 值，为什么 `PASSPORT` 被拒绝了？

定义的值是 `ID`、`PASSPORT`、`CPF` 和 `CNPJ`，但接受的**集合按
国家收窄**，超出该国家集合的值即使是有效的枚举
成员也会被拒绝：

| 收款国家 | 接受的 `payeeIDType` | 必填？ |
| - | - | - |
| 中国大陆（`CHN`） | `ID`、`PASSPORT` | 是——没有它请求会被拒绝 |
| 巴西（`BRA`） | `CPF`、`CNPJ` | 是，连同 `payeeIDNumber` |
| 其他国家 | 无国家级限制；由收款方校验 | 按通道 |

所以巴西 Payout 上的 `PASSPORT` 被拒绝，是因为巴西接受的集合只有 `CPF` / `CNPJ`。
拒绝消息会指明该字段并列出允许的值。

## 巴西：什么时候用 CPF，什么时候用 CNPJ？

它们跟随 `payeeType`，两者必须一致：

| `payeeType` | 证件类型 | `payeeIDNumber` 格式 |
| - | - | - |
| `INDIVIDUAL` | `CPF` | 11 位数字 |
| `BUSINESS` | `CNPJ` | 14 位数字 |

如果你省略 `payeeIDType`，会据此从 `payeeType` 推断。如果你传了它且
与 `payeeType` 矛盾——比如 `CNPJ` 配 `INDIVIDUAL`——Payout 会被拒绝。`payeeIDNumber`
对该通道始终必填，并按上述位数模式检查。

## `INDIVIDUAL` 和 `BUSINESS` 有什么区别？

`payeeType` 决定哪些 Payout 安排可以服务该请求：一个已签约方式可能
接受个人、公司或两者，而 `payeeType` 不被任何通道接受的 Payout 会
以未签约被拒绝。除路由之外，实际差别就是上述证件规则——
对巴西来说，`BUSINESS` 意味着 `CNPJ`。没有单独的"企业 Payout"对象需要填写。

## 付款前我需要先注册收款人吗？

不需要。没有收款人库，也没有收款人注册调用：每次 Payout 创建都完整携带收款人
信息，Waffo 不会复用之前订单的信息。请自行维护收款人
记录，每次从中填充请求。

## 我该选哪个 `payoutMethodType`，`payoutMethodName` 何时必填？

| `payoutMethodType` | `payoutMethodName` | `payoutMethodProperty` |
| - | - | - |
| `EWALLET` | **必填**——钱包名称；空值会被拒绝 | 非必填 |
| `BANK_ACCOUNT` | 留空 | **必填**——一个 JSON 对象；空值会被拒绝 |

只有这两个值。`productName` 会对照你账户拥有的产品校验，
所以未为你开通的 Payout 产品会在该字段上被拒绝；`ONE_TIME_PAYOUT` 是
单次、非周期性 Payout 的值。

## 银行 Payout 的 `payoutMethodProperty` 里放什么？

它是一个 JSON 字符串。重要的键及其执行位置：

| 键 | 何时必填 |
| - | - |
| `bankCode` | **除**中国大陆外的每笔 `BANK_ACCOUNT` Payout 必填 |
| `bankName` | 中国大陆必填，且必须包含中文字符 |
| `bankSub` | 中国大陆在卡号**不**以 `62` 开头时必填，且必须包含中文字符。在其他通道中用作分行标识。 |
| `accountType` | 某些通道要求——巴西为 `CRN`、`PAC`、`SVN` 之一 |
| `accountName` | 可选；当账户名称无法通过 `payeeInfo` 的姓名字段表达时提供 |

该字段中格式错误的 JSON 本身就是 `A0003`。在通道维护按银行的分行和
账号模式的地方，预检步骤会据此校验，并以指明 `bankSub` 或账号的
缺失或无效字段错误拒绝不匹配的情况。

## 我从哪里获取银行代码？

没有公开的银行代码查询端点，文档中也没有可下载的银行列表。
银行代码是通道特定的：在构建之前，请向 Waffo 索取覆盖你 Payout
协议中通道的列表。中国大陆是例外，完全不需要 `bankCode`
——发送 `bankName`（中文），以及对于不以 `62` 开头的卡，发送 `bankSub`。

## 中国银行 Payout 的账户名称需要是中文吗？

`bankName` 必须包含中文字符，适用 `bankSub` 时 `bankSub` 也必须如此。
账户持有人的姓名本身放在 `payeeInfo` 的姓名字段中；只有当账户名称
是那些字段无法承载的名称时，才使用 `payoutMethodProperty` 内的 `accountName`。

## `payoutMethodUserAccountNo` 里放什么？

取决于方式：

| 方式 | 值 |
| - | - |
| `BANK_ACCOUNT` | 收款人的银行账号 |
| `EWALLET` | 钱包为收款人提供的公开用户标识，或者——在钱包接受的情况下——按该钱包指定格式的收款人手机号 |

对于接受电话号码的钱包，数字采用钱包自身的格式，而不是
`payeePhone` 格式：去掉国内前导零并包含国家码，所以
印尼号码以 `628` 开头发送，而不是 `0` 或 `+62-0`。

## 巴西 PIX：哪些 key 类型可用？允许随机（EVP）key 吗？

五种标准 key 类型全部接受，类型从值本身推断——
没有 key 类型字段需要设置：

| Key 类型 | 接受的形式 |
| - | - |
| CPF | 11 位数字 |
| CNPJ | 14 位数字 |
| Phone | E.164，例如 `+5511987654321` |
| Email | 有效的邮箱地址 |
| EVP（随机 key） | 由收款人银行发放的 UUID |

所以是的，EVP 可用。不匹配五种中任何一种的值会在
`payoutMethodUserAccountNo` 上被拒绝。

## 如果账号和收款人姓名不匹配会怎样？

在收款方在预检期间返回账户持有人姓名的地方，Waffo 会把它
与你发送的进行比较，不匹配时以 `B0004`（"User info does not match"）使 Payout 失败。
这个比较比人们预期的要窄：

* 只比较**名**和**姓**。`payeeMiddleName` 不比较。
* 比较**不区分大小写**。
* 如果任一方的值为空，该部分检查通过。

所以这个检查是真实存在的，但不能依赖它作为完整的姓名验证：不返回
姓名的通道完全不做检查，一笔 Payout 可能成功付到持有人与你提供的姓名
不同的账户。请在发送前在你这边核实收款人信息。

## `purpose` 是必填的吗？有效值有哪些？

对**中国大陆** Payout 必填，并对照固定列表校验。对其他
国家，国家校验不要求它，但个别通道可能拒绝
没有它的 Payout。

| `purpose` |
| - |
| `SALARY_PAYMENT` |
| `SERVICE_CHARGES` |
| `ADVISORY_FEES` |
| `ADVERTISING_EXPENSES` |
| `CONSTRUCTION_EXPENSES` |
| `PROPERTY_RENTAL` |
| `TAX_PAYMENT` |
| `LIBERALIZED_REMITTANCE` |

列表之外的值会被拒绝，并回显违规值。请选择
真实描述该笔付款的值；它是一项监管申报，不是标签。

## `description` 会展示给收款人吗？会被截断吗？

会——它出现在收款人的银行或钱包账单上，这也是它为必填字段的原因。最长
128 个字符，但请写得比这短得多：收款银行和钱包会截断，所以目标是
大约 16 个英文单词或 10 个中文字符，并把关键标识放在最前面。
Waffo 不会为你截断；收款方会，且不可预测。

## `extendInfo` 里可以放什么，我能拿回来吗？

序列化为字符串的 JSON 对象，例如 `{"key1":"value1","key2":"value2"}`。它在
`/api/v1/payout/inquiry` 和 Payout Webhook 通知中原样返回。无法解析为
JSON 的值会以 `A0003` 拒绝。它是放你自己关联 ID 的正确位置；它不会
传给收款人。

## 金额可以有几位小数？

`payoutAmount` 是字符串，接受的精度是**收款币种自身的精度**，而不是
固定位数。小数位多于币种允许的值会被**拒绝**，返回指明
`payoutAmount` 的 `A0003`——绝不会被静默四舍五入。字段自身的模式允许最多
8 位小数，所以你的代码必须满足的是币种检查，而不是模式。

金额还受你该通道 Payout 协议中最小值和最大值的约束，
这就是一个看起来在范围内的金额反而得到 `A0008` 的地方。两个边界都在
Portal 的 Service → Payout 页面上。

## 我能设置收款人收到的币种吗？

不能在请求上设置。在单笔 Payout API 上，`payeeCurrency` 和 `payeeAmount` **如果你传了会被
拒绝**——它们是输出，不是输入。你设置 `payoutCurrency` 和 `payoutAmount`；
收款人币种来自你该通道 Payout 协议中的币种对。

对于跨币种 Payout，创建订单时可能还不知道确切的到账金额，
所以 `payeeAmount` 在首次查询时可能为空，稍后才填充。不要在请求时
向收款人承诺确切数字。从你这里扣除的是 `prefundAmount`——
换算后的金额加上该订单的手续费——在
[Payout 钱包与覆盖范围](/docs/zh/support/payout-wallet-and-coverage-faq)中有描述。

## `notifyUrl` 是可选的吗？它会覆盖 Portal 中配置的内容吗？

对于通过 API 创建的 Payout，`notifyUrl` 是**必填的**——没有它的创建会被拒绝。
它必须以 `http://` 或 `https://` 开头。没有账户级的 Payout 通知 URL 可以
回退，也没有什么可覆盖的：Payout Webhook 通知只发到该订单上的 URL，不发到其他任何
地方，所以没有它而创建的 Payout 就是一笔你永远不会收到通知的 Payout。

## `merchantInfo` 是干什么的？

`merchantInfo.merchantId` 必填，是你的 Waffo 商户 ID；`merchantInfo.subMerchantId`
可选，仅当你的账户设置了子商户时才相关。两者在查询时都会
回显。

***

在本页未解释的字段上被拒绝？`A0003` 消息会指明该字段——参见
[Payout 错误码与重试](/docs/zh/support/payout-error-codes-and-retry-faq)了解如何解读，或
[联系支持](mailto:support@waffo.com)，附上 `payoutRequestId`。


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