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

# 按支付方式划分的条件必填字段

> 为什么 /api/v1/order/create 上标记为可选的字段——goodsId、goodsUniquePrice、skuName、userFirstName、userPhone、地址等——仍可能因缺失而被拒绝，缺失字段列表中可能出现哪些字段路径，以及为什么正确做法是先提交再读取返回的列表而不是预判。

收单规范把 `goodsInfo`、`addressInfo` 和若干 `userInfo`
字段标记为可选，其底层对象也确实只有长度限制——没有
必填约束。然而，一个通过了 schema 校验的请求仍可能返回
`A0003 Parameter validation failed` 并指出其中某个字段。下文使用的 `payMethodType` 取值
列在[数据参考](/docs/zh/developer-docs/tools-and-references/references/data-reference)中。

## 为什么标记为可选的字段会因缺失被拒绝？

因为"必填"不是 API 的属性——它是**实际使用的支付
方式**加上你所处**场景**的属性。一个集成发送卡支付，不需要
`goodsInfo` 里的任何内容；另一个发送分期付款，需要完整的逐项商品清单。单一的
schema 无法同时标记两者。由此产生两个后果：

* **字段要求不是仅由支付方式决定的稳定函数。** 同一种
  方式可能根据支付的处理方式要求不同的字段，而且这个集合可能在你这边没有任何改动的情况下发生变化，所以在
  集成中硬编码的按方式列表会悄无声息地过时。
* **没有预检发现端点。** `/api/v1/paymethodconfig/inquiry`
  返回可用性、维护窗口、金额范围、币种和退款政策——
  它**不**返回字段要求。

## 那么正确的做法是什么？

提交、读取列表、重新发送。不要预判。

1. 带上你已持有的所有信息发送请求。
2. 如果缺少必填字段，调用会以 `A0003` 失败。专门针对 `A0003`，
   响应的 `msg` 会在括号中附带字段级详情；在
   `/api/v1/order/refund` 上，缺失的路径还会以 `missingFields` 列表返回。
3. 精确填入这些路径并重新发送。

路径以点号形式返回——`userInfo.userFirstName`、`addressInfo.postcode`、
`goodsInfo.goodsUniquePrice`——因此可以直接映射到你的请求体。

**如果你使用托管收银台，通常永远不会遇到这个问题。** 当所选方式
需要你未提供的字段时，Waffo 会把订单路由到收银台，由收银台
为买家渲染这些输入项。上述循环在没有
收银台可回退的场景下最为重要：商户发起的交易（`merchantInitiatedMode`）和
直接结算的代理支付。

## 缺失字段列表中可能出现哪些字段路径？

| 对象 | 可能被要求的路径 |
| - | - |
| `userInfo` | `userFirstName`、`userLastName`、`userPhone`、`userEmail`、`userId`、`userIDNumber` |
| `userInfo.userBankInfo` | `bankAccountNo`、`bankCode`、`bankName`、`bankBranch`（通过转账支付的退款） |
| `addressInfo` | `address`、`city`、`region`、`postcode`、`addressCountryCode` |
| `goodsInfo` | `goodsId`、`goodsName`、`goodsUniquePrice`、`goodsQuantity`、`skuName`、`goodsCategory`、`goodsUrl` |
| `paymentInfo` | `payMethodUserAccountType`（`EMAIL` / `PHONE_NO` / `ACCOUNT_ID`）与 `payMethodUserAccountNo` |
| `payMethodProperties` | 市场特定标识——`cpf`、`curp`、`nin`、`cc`、`ci`、`bankCode`、`accountNumber`、`receiveBank`、`cryptoChain`、`cardToken`、`paymentToken` |
| `extendInfo` | `refundAddress`，作为 `extendInfo` JSON 字符串内的一个键 |

## 大致上各类支付方式会要求什么？

仅供参考——有助于评估你的数据收集工作量，**不是**契约。以
返回的列表为准。同一种方式类型的要求还会因市场而异，这也是
静态列表站不住脚的另一个原因。

| `payMethodType` | 常见要求 |
| - | - |
| `BNPL` | 最大的集合：逐项商品清单（`goodsId`、`goodsName`、`goodsUniquePrice`、`goodsQuantity`、`skuName`、`goodsCategory`、`goodsUrl`）加上买家姓名、电话、邮箱和完整的收货地址 |
| `EWALLET` | 通常不需要额外内容；有的要求买家电话，有的要求钱包账户对（`payMethodUserAccountType` + `payMethodUserAccountNo`） |
| `ONLINE_BANKING`、`DIGITAL_BANKING` | 买家姓名和联系方式；这些通道上的**退款**通常需要银行账户信息 |
| `VA`、`OTC` | 一个小集合——通常是买家的名和姓 |
| `CREDITCARD`、`DEBITCARD` | 不需要 `goodsInfo` 里的任何内容；某些市场需要通过 `payMethodProperties` 传国家身份标识 |

## 其中哪些实际上是无条件必填的？

不要在本来就是必填的字段上花精力。在 `/api/v1/order/create` 上，
`userInfo.userId`、`userInfo.userTerminal` 和 `orderDescription` 对每个
请求都是必填的。`userInfo.userEmail` 实际上也是必填的：如果没有收集到真实地址，
请发送 `userId@examples.com` 形式的唯一兜底值——绝不要用共享或占位
值，那可能触发风控。在 `goodsInfo` 内，契约要求**要么**传
`goodsUrl` **要么**传 `appName`（不能都传）用于合规和风控审核；创建调用
本身不会因它们缺失而拒绝——只有支付方式的条件规则
会通过上述缺失字段列表来拒绝。

## 由场景而非支付方式驱动的要求

由你*如何*集成触发，并在任何支付方式特定规则运行之前检查：

| 场景 | 额外必填 |
| - | - |
| 在 API 中直接传卡数据或 `paymentTokenData` | `userInfo.userBrowserIp` 和 `userInfo.userAgent`，加上卡字段——卡号、有效期月和年、CVV、持卡人姓名 |
| 设置了 `merchantInitiatedMode` | `userPaymentAccessToken` |
| 托管模式下的代理支付 | `successRedirectUrl` |
| 对稳定币订单退款 | `extendInfo` 内的 `refundAddress` |

## 退款使用同一份列表吗？

不是。退款有自己的检查，可能要求支付从不需要的身份和付款信息，
因为资金往往通过转账退回，而不是在原支付上做冲正
——这也是退款请求接受 `userInfo`（包括
`userBankInfo`）、`addressInfo` 和 `extendInfo` 的原因。同样的提交-读取循环。

## 字段已经传了但仍被拒绝，为什么？

格式规则适用于你发送的每个字段，无论它是否被要求：

| 字段 | 规则 |
| - | - |
| 任何字符串字段 | 空字符串会被规范化为缺失——发送 `""` 等同于省略它，无法满足缺失字段要求 |
| `userPhone` | `+CountryCode-Number`，例如 `+62-08990013157`——必须以 `+` 开头并包含 `-` |
| `userEmail` | 必须是有效的邮箱地址——无效邮箱是唯一**不**返回 `A0003` 的格式失败：它返回 `B0007 Invalid email format` |
| `goodsQuantity` | 整数或数字字符串；其他任何内容都会在解析时被拒绝 |
| `userBirthDay`、`userIDIssueDate`、`userIDExpiryDate` | `dd/MM/yyyy` |
| `addressCountryCode`、`nationality` | 可识别的 ISO 国家代码 |
| `userIDType` | 目前为 `ID` |

长度限制是另一回事，在收单规范中按字段列出，
同样会产生指明字段的 `A0003`。

***

按响应要求的内容原样重新发送后仍然被阻塞？
[联系支持](mailto:support@waffo.com)，附上 `paymentRequestId` 和完整的
`A0003` 消息。


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