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

# 集成验收标准

> 商户完成 Waffo 集成后的验收标准，涵盖功能测试、异常处理、传参要求与数据完整性。

商户完成集成后，需在沙盒环境通过以下验收标准方可上线。

## 验收材料提交

API 集成完成后，请下载并填写对应验收用例模板：

* <a href="/docs/files/developer-docs/acceptance/one-time-payment-acceptance-cases.json" data-waffo-download-file="one-time-payment-acceptance-cases.xlsx">一次性支付验收用例模板</a>
* <a href="/docs/files/developer-docs/acceptance/subscription-acceptance-cases.json" data-waffo-download-file="subscription-acceptance-cases.xlsx">订阅支付验收用例模板</a>

填写完成后，将验收结果提交给 Waffo 技术对接群确认。Waffo 会根据模板中的执行结果、商户交易 ID、Webhook 处理结果和异常场景处理逻辑进行验收。

> **补充说明**：验收模板中的部分异常场景通过沙盒特殊金额触发。如果你在沙盒环境中传入这些金额，接口会按预设返回对应错误。详见 [沙盒模拟器](/docs/zh/developer-docs/tools-and-references/developer-tools/sandbox-simulator) 中的“特殊金额触发异常”。

## 功能测试

### 支付（必测）

* 支付成功：创建订单 → 完成支付 → 订单状态更新 → 业务逻辑执行正确
* 支付失败：使用失败测试卡 → 订单状态更新 → 业务逻辑**未执行**
* Webhook 接收：成功和失败的通知均已正确处理
* Webhook 幂等：重复收到同一通知时，业务逻辑只执行一次

### 退款（如集成）

* 退款成功：对已支付订单发起退款 → 状态正确更新
* 退款通知：Webhook 到达后状态正确更新

### 订阅（如集成）

* 首期支付成功 → 订阅激活
* 续费模拟：通过沙盒管理页触发下期扣款 → 业务处理正确
* 取消订阅 → 状态正确更新

***

## 一次性支付验收用例

请按实际接入范围执行以下用例，并在模板中记录执行结果和商户交易 ID。

### 必测场景

* 创建订单后模拟支付成功，商户 `notifyUrl` 收到终态成功通知，并校验 `paymentRequestId`、`orderCurrency`、`orderAmount` 与商户订单一致
* 创建订单后模拟支付失败，商户 `notifyUrl` 收到终态失败通知，并校验订单信息一致
* 支付成功后查询订单，确认 `orderStatus = PAY_SUCCESS`
* 支付失败后查询订单，确认 `orderStatus = ORDER_CLOSE`
* 支付成功通知验签通过后更新商户侧订单状态
* 支付失败通知验签通过后不执行业务发货或权益发放逻辑
* 通知验签失败时不处理该通知，并通过查询接口获取订单状态

### 异常场景

* 渠道拒绝：模拟 `C0005 Payment Channel Rejection`
* 幂等冲突：相同 `paymentRequestId` 使用不同金额或币种时返回 `A0011`
* 系统不可用：模拟 `C0001 System Error`
* Unknown 状态：模拟 `E0001 Unknown Status`，不独自关单，等待查询结果或 Webhook 通知

### 条件接入场景

* 如接入取消订单：支付前取消成功后查询到 `ORDER_CLOSE`
* 如接入取消订单：支付成功后取消返回 `A0013`
* 如接入退款：退款成功后校验 `refundRequestId`、`refundAmount` 和退款状态
* 如接入退款查询或退款通知：能识别退款中、全额退款、部分退款、退款失败等状态

## 订阅支付验收用例

请按实际接入范围执行以下用例，并在模板中记录执行结果、商户交易 ID 和商户交易时间。

### 必测场景

* 创建订阅后模拟首期支付成功，商户收到订阅状态通知和订阅支付通知
* 创建订阅后模拟首期支付失败，商户收到失败通知并跳转到失败页
* 查询未支付订阅，能根据 `subscriptionAction` 或 `orderAction` 引导用户完成授权
* 查询支付成功订阅，确认订阅状态为 `ACTIVE`
* 查询支付失败订阅，确认订阅状态为关闭终态
* 订阅状态通知验签通过后，校验 `subscriptionRequest`、金额、币种、周期和试用期参数与商户侧记录一致
* 订阅支付通知验签通过后，按 `subscriptionRequest` 和 `period` 匹配到对应周期订单，并校验金额与币种
* 订阅支付通知验签失败时不更新状态，并通过查询接口获取真实状态

### 续费与取消

* 在订阅管理页模拟下期支付成功，商户收到对应周期的支付成功通知
* 在订阅管理页模拟下期支付失败，商户收到对应周期的支付失败通知
* 如接入订阅取消：商户取消成功后查询到 `MERCHANT_CANCELLED`
* 如支持渠道侧取消：能处理 `CHANNEL_CANCELLED` 通知

### 异常场景

* 订阅渠道拒绝：模拟 `C0005 Payment Channel Rejection`
* 幂等冲突：相同请求 ID 使用不同金额或币种时返回 `A0011`
* 系统不可用：模拟 `C0001 System Error`
* Unknown 状态：模拟 `E0001 Unknown Status`，不独自关闭订阅，等待查询结果或 Webhook 通知
* 如复用退款能力：按一次性支付退款验收规则验证退款、退款查询和退款通知

***

## 支付方式覆盖

不需要逐一测试每个已签约的支付方式，按类型选取代表即可：

| 规则                     | 示例                       |
| ---------------------- | ------------------------ |
| 卡类至少 1 个               | CC\_VISA                 |
| 每个国家每种类型至少 1 个         | 印尼电子钱包选 DANA 或 ShopeePay |
| 有特殊参数的必测               | OVO（需手机号）、PIX（需 CPF）     |
| VA 至少 1 个              | BCA\_VA                  |
| Apple Pay / Google Pay | 需在真实设备上手动测试              |

***

## 异常处理要求

以下异常场景 Waffo 会在验收时检查你的处理逻辑：

| 场景                    | 你需要做的                                                                      |
| --------------------- | -------------------------------------------------------------------------- |
| Unknown Status（E0001） | **不要关单**。用相同参数重试，仍失败则等待查询结果或 Webhook 通知                                    |
| 渠道拒绝 / 系统不可用          | 向用户展示友好提示，引导重试或切换支付方式                                                      |
| Webhook 签名验证失败        | 不处理该通知，通过查询 API 获取正确状态                                                     |
| 幂等冲突（A0011）           | 确保每次请求使用独立生成的 ID（paymentRequestId / refundRequestId / subscriptionRequest） |

***

## 传参要求

| 字段                     | 要求                                                |
| ---------------------- | ------------------------------------------------- |
| 金额                     | String 类型（如 `"100.00"`），非浮点数                      |
| `orderDescription`     | 传入确切描述，不能是 "test" 占位符                             |
| `goodsName`            | 必填                                                |
| `goodsUrl` 或 `appName` | 至少传入一个（合规和风控要求）                                   |
| `userEmail`            | 真实邮箱或 `userId@examples.com` 格式（避免 test 字符，避免多人共用） |
| 时间字段                   | UTC+0，以 `Z` 结尾，毫秒不超过 3 位                          |

***

## 数据完整性

* `paymentRequestId` 在调用 API **之前**已持久化（网络超时时用于恢复查询）
* `acquiringOrderID` 支付成功后已存储
* 跳转 URL（successRedirectUrl / failedRedirectUrl）已设置
