# 统一收银台 API 接口对接文档

> 首次接入请先阅读 [简洁商户入口](./api-docs.html)，按国家、币种筛选代收支付类型、代付支付类型和账户要求。当前支持范围以 [正式配置目录](./开放接口附录-支持类型目录.md) 为准；本文保留完整协议参考。

## 文档说明
- 版本：v1.3
- 更新时间：2026-04-19
- 基础 URL：`https://your-domain.com/api`（以实际部署域名为准）
- 请求与响应 JSON 字段名均为 **camelCase**（与开放接口 JSON 一致）。
- 本版本统一要求请求包含 `timestamp`、`nonce`、`apiVersion`、`sign`。**建议将 `sign` 放在 JSON Body**；部分接口支持 Header `sign` 或 Query `sign` 作为兼容，**以各接口说明为准**（见下文「sign 传递位置」）。
- 业务成功时 **`rspCode` 为 `PAY_000`**；失败时为 `PAY_XXX_NNN` 业务码，详见 `rspMsg`。在已识别商户且签名密钥可用于响应签名时，成功或业务失败响应通常含 `timestamp`、`nonce`、`apiVersion`、`sign`；**商户不存在、IP 白名单拒绝、密钥不可用、签名算法不支持等前置安全失败**的响应可能**不带有效 `sign` 或 `sign` 为空**，商户应优先根据 `rspCode`/`rspMsg` 诊断，勿强行验签。

## 签名规则
1. 取参与签名参数，排除 `sign` 字段。
2. 过滤 `null` 值。
3. 复杂对象先扁平化为路径键值对，再参与签名（路径键最终转小写）。
4. 参数名按 ASCII 升序排序。
5. 组装 `key=urlEncode(value)` 并用 `&` 连接。
6. 末尾追加 `&key=商户签名密钥`。
7. 对完整字符串做 MD5，得到 **32 位十六进制字符串**；平台生成与返回的签名为 **默认小写**，验签时建议使用**大小写不敏感**比较。

### sign 传递位置（与实现一致）

| 接口 | Body `sign` | Header `sign` | Query `sign` |
|------|:---:|:---:|:---:|
| `UnifiedPay` | 支持 | 支持 | 支持 |
| `UnifiedPayout` | 支持 | 支持 | 支持 |
| `QueryPayOrder` | 支持 | 支持 | 不支持 |
| `QueryPayoutOrder` | 支持 | 支持 | 不支持 |
| `QueryMerchantBalance` | 支持 | 支持 | 不支持 |
| `GenerateCashierToken` | **须使用** | 不支持 | 不支持 |

### 复杂对象扁平化规则
- 顶层字段：`payerEmail=xxx`（键名参与签名时转小写为 `payeremail`）
- 嵌套对象：`instrument.bankCode=xxx`、`ext.scene=checkout`
- 数组：`items[0].id=1`、`items[1].id=2`

示例：

```json
{
  "appId": "appid_759665ede",
  "payerEmail": "user@example.com",
  "instrument": { "bankCode": "ICBC" },
  "items": [ { "id": 1 }, { "id": 2 } ]
}
```

扁平化后参与签名（键名最终为小写路径）：

```text
appid=appid_759665ede
instrument.bankcode=ICBC
items[0].id=1
items[1].id=2
payeremail=user@example.com
```

## 安全规则
- `timestamp`：Unix 时间戳（秒），与服务端 UTC 时间偏差不超过 5 分钟。
- `nonce`：单次请求随机串，10 分钟内不可重复。
- `apiVersion`：默认使用 `v1.0`。`UnifiedPay`、`MerchantHostedPay`、`QueryPayOrder` 额外支持 `v1.1`；两个版本都按实际响应字段验签。
- 查询响应和回调中 `providerKey`、`providerName` 有值时会返回实际使用的渠道，并按签名参数名 `providerkey`、`providername` 参与验签。

## 证件类型标准

代收付款人证件类型 `payerIdType` 与代付普通证件类型 `identityType` 都使用平台标准枚举。商户不要传上游原始编码，平台会按渠道、国家和币种转换为上游所需编码。

| 枚举值 | 中文含义 | 说明 |
|---|---|---|
| `PASSPORT` | 护照 | 护照号码配套放在 `payerIdNumber` 或 `identityNo`。 |
| `ID_CARD` | 本国法定身份证 | 国民身份证、居民身份证、国家身份证等同类证件。 |
| `TAX_ID` | 报税身份/税号 | 用于上游明确要求普通税号证件类型的场景。巴西 CPF/CNPJ 代付优先按 `payeeType=PIX_CPF/PIX_CNPJ` 与 `payeeIdCard` 传。 |
| `DRIVING_LICENSE` | 驾驶证 | 仅在对应渠道明确要求时传。 |
| `RESIDENCE_PERMIT` | 居留证/外籍居民证 | 外籍居民、外劳、移民局签发的身份证明。 |
| `MILITARY_ID` | 军官证/军人证 | 用于上游文档要求军官证、军人证等证件类型的场景。 |

传参规则：如果传 `payerIdNumber` 或 `identityNo`，必须同时传对应的 `payerIdType` 或 `identityType`；如果渠道不要求证件，两个字段都不要传。`payeeIdCard` 只承载税号、CPF、CNPJ 等税务实名编号，不承载普通证件号。

### 响应码 `rspCode`
| 取值 | 含义 |
|------|------|
| `PAY_000` | 业务成功（在响应含有效 `sign` 时须验签后再信任业务字段） |
| `PAY_SIGN_*` / `PAY_SEC_*` | 签名或安全相关错误 |
| `PAY_MCH_*` | 商户配置类错误 |
| `PAY_ORDER_*` | 订单类错误（如重复单号、不存在） |
| 其他 `PAY_*` | 路由、渠道、参数等业务错误；具体文案见 `rspMsg` |

> **说明（主数据与 PAY 码表）**：正文与附录中出现的 `payMethodCode` / `payTypeCode` / `channelCode` 等**仅为示例**；**实际可用取值**以**平台当前生效的支付产品目录、路由配置**及商户后台为准。`PAY_*` **简体中文模板**见 **`website/pay-codes-zh-CN.json`**（`api-docs.html` 中「PAY 业务码全表」由该文件动态渲染；与线上一致）。**`payTypeCode` 目录（按代收/代付拆分）**见 **`website/pay-method-type-master.json`**（含 `acquire` / `payout`；由平台按当前生效清单导出；`api-docs.html`「主数据编码」§2～§3 由该文件动态渲染）。**币种/国家/语言建议/渠道（`channelCode` 与各渠道键对应关系）**见 **`website/main-data-reference.json`**（§4～§7 由该文件动态渲染）。**路由四字段语义**见 **`website/开放接口附录-路由字段语义说明.md`**；**参数与路由错误排查**见 **`website/开放接口附录-常见参数与路由错误排查.md`**。**产品维度补充提示（银行 / 身份 / 手机）**见 **`website/pay-type-code-field-hints.json`**（与 `api-docs.html` 代收/代付 `payTypeCode` 表合并展示）。**代收 / 代付产品总目录入口**见 **`website/开放接口附录-代收pay_type_code接入说明.md`**、**`website/开放接口附录-代付pay_type_code接入说明.md`**；**附录变更记录**见 **`website/开放接口附录-CHANGELOG.md`**。其它语言以平台提供的 `PayCodes.*.json` 为准。排障以**实际响应**的 `rspCode` / `rspMsg` 为准。

---

## 一、统一下单

### 接口
- `POST /api/PayRequest/UnifiedPay`

### 接口概述
- 创建支付订单；平台会按商户开通的产品、国家、币种和路由配置选择真实支付方式。
- `channelCode`、`payTypeCode`、`payMethodCode` 都不是必传字段；传了表示按指定路由条件下单，不传则由系统自动路由。
- `channelCode` 如果有传，则交易限定在指定渠道下。
- `payTypeCode` 如果有传，则交易限定在指定渠道下的具体支付类型下。
- 请求签名使用 MD5，服务端按相同规则验签；需配置商户 API 白名单 IP。
- 在可通过商户密钥对响应签名的情况下，响应含 `rspCode`、`rspMsg`、`timestamp`、`nonce`、`apiVersion`、`sign`；**`rspCode === PAY_000` 表示受理成功**，商户须先验签再读业务字段。前置安全失败类响应可能无有效 `sign`（见文档说明）。
- `amount` 按分传输，必须为正整数。
- `displayAmount` 为代收收银台展示金额（分）：不传、空值或 `0` 按真实 `amount` 显示；小于 `0` 隐藏金额；大于 `0` 按该值展示。该字段只影响收银台页面显示，不影响真实订单金额、路由、上游提交或结算；传入非空值时参与签名。
- 多国家代收场景下，不同 `payTypeCode` 的传参要求不同。接入 NovaVexis 渠道时，请同时参考附录 [开放接口附录-NovaVexis代收pay_type_code接入说明.md](./开放接口附录-NovaVexis代收pay_type_code接入说明.md)。
- 接入 CowPay 渠道时，请同时参考附录 [开放接口附录-CowPay代收pay_type_code接入说明.md](./开放接口附录-CowPay代收pay_type_code接入说明.md)。
- 接入 Eqpay 渠道时，请同时参考附录 [开放接口附录-Eqpay代收pay_type_code接入说明.md](./开放接口附录-Eqpay代收pay_type_code接入说明.md)。
- 接入 Fzpay 渠道时，请同时参考附录 [开放接口附录-Fzpay代收pay_type_code接入说明.md](./开放接口附录-Fzpay代收pay_type_code接入说明.md)。
- 接入 Ynuopay 渠道时，请同时参考附录 [开放接口附录-Ynuopay代收pay_type_code接入说明.md](./开放接口附录-Ynuopay代收pay_type_code接入说明.md)。
- 接入 XLPay 渠道时，请同时参考附录 [开放接口附录-XLPay代收pay_type_code接入说明.md](./开放接口附录-XLPay代收pay_type_code接入说明.md)。
- 接入 TopPay 渠道时，请同时参考附录 [开放接口附录-TopPay代收pay_type_code接入说明.md](./开放接口附录-TopPay代收pay_type_code接入说明.md)。

- 接入 gmylhxe 渠道时，请同时参考附录 [开放接口附录-gmylhxe接入说明.md](./开放接口附录-gmylhxe接入说明.md)，按平台标准 `payTypeCode` 传参，不传上游 SKU。
- 接入 khpay 柬埔寨渠道时，请参考 [开放接口附录-khpay代收pay_type_code接入说明.md](./开放接口附录-khpay代收pay_type_code接入说明.md)，仅传平台标准 `wing`、`acl`、`aba`；并至少提供一个稳定的 `buyerId` 或 `payerOpenId`，用于映射上游必填的付款人标识。
- 接入 TarsPay 印尼渠道时，请参考 [开放接口附录-tarspay代收pay_type_code接入说明.md](./开放接口附录-tarspay代收pay_type_code接入说明.md)。商户仅传平台标准 `payTypeCode`；平台订单号映射上游 `mchOrderNo`，`payOrderId` 是上游订单号，二者不得反置。
- 接入 tigerpay 孟加拉渠道时，请参考 [tigerpay 孟加拉接入说明](./开放接口附录-tigerpay孟加拉接入说明.md)。代收使用平台标准 `bkash/nagad`，上游产品码由平台映射。

### 请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| appId | string | 是 | 应用ID |
| merchantOrderNo | string | 是 | 商户订单号 |
| amount | long | 是 | 支付金额（分，正整数） |
| displayAmount | long | 否 | 代收收银台展示金额（分）；不传/空/`0` 按真实金额显示，`<0` 隐藏金额，`>0` 按该值展示；仅影响收银台展示，传入非空值时参与签名 |
| currency | string | 是 | 币种（ISO 4217，如 CNY/USD） |
| payMethodCode | string | 否 | 支付方式编码（如 qr、h5、bank_transfer 等）；不传时由平台按 `payTypeCode`、国家、币种和商户路由自动选择，传入时作为路由收窄条件 |
| channelCode | string | 否 | 渠道编码（可选；传了则交易限定在指定渠道下，不传则由系统自动路由） |
| timestamp | string | 是 | Unix时间戳（秒） |
| nonce | string | 是 | 随机字符串 |
| apiVersion | string | 是 | API版本，支持 `v1.0`、`v1.1` |
| sign | string | 是 | 请求签名 |
| subject | string | 否 | 订单标题 |
| notifyUrl | string | 否 | 异步通知地址（不传则可用商户后台默认） |
| returnUrl | string | 否 | 同步跳转地址（不传则可用商户后台默认） |
| country | string | 否 | 国家代码（ISO 3166-1 alpha-2，跨境场景） |
| payTypeCode | string | 否 | 支付类型编码（可选；传了则交易限定在指定渠道下的具体支付类型下，不传则由系统自动路由） |
| languageCode | string | 否 | 语言代码（ISO 639-1，影响 `rspMsg` 等文案） |
| clientIp | string | 否 | 付款方公网 IP（可选；用于风控等，参与签名） |
| payerName | string | 否 | 付款人姓名 |
| payerIdType | string | 否 | 付款人证件类型，使用平台标准枚举，见「证件类型标准」 |
| payerIdNumber | string | 否 | 付款人证件号；有值时必须同时传 `payerIdType`。Todaypay 阿根廷 ARS 代收未传时由平台稳定生成 8 位数字 DNI；显式传入时须配套 `payerIdType=ID_CARD` 且为 8 位 ASCII 数字 |
| payerEmail | string | 否 | 付款人邮箱 |
| payerPhone | string | 否 | 付款人手机号 |
| payerOpenId | string | 否 | 付款人 OpenId（如微信） |
| buyerId | string | 否 | 付款人 BuyerId（如支付宝）。特别说明：Otomatis QRIS/VA 代收必须传下游商户侧付款用户名称或用户标识，平台会作为上游 `username` 上送。 |
| instrument | object | 否 | 支付工具信息 |
| ext | object | 否 | 扩展参数 |

### instrument 对象（可选）
| 参数名 | 类型 | 说明 |
|---|---|---|
| cardToken | string | 卡Token |
| bankCode | string | 银行编码/联行号 |
| mandateId | string | 代扣协议号 |
| holderName | string | 持卡人姓名 |
| brand | string | 卡组织品牌 |
| expMonth | string | 到期月（MM） |
| expYear | string | 到期年（YYYY） |
| last4 | string | 卡号后四位 |
| bin6 | string | 卡BIN前6位 |
| masked | string | 卡号掩码 |

### ext 对象（可选）
- 类型：`Dictionary<string, string>`
- 说明：扩展键值对，签名时按 `ext.xxx` 扁平化参与签名。

### 响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| appId | string | 应用ID（回显） |
| rspCode | string | 业务码，`PAY_000` 为成功 |
| rspMsg | string | 与 `rspCode` 配套的多语言说明；失败时含原因摘要，完整码表见 `pay-codes-zh-CN.json` / `api-docs.html` |
| platformOrderNo | string | 平台订单号 |
| upstreamSubmitOrderNo | string | `v1.0`、`v1.1` 均支持。仅当平台实际提交给上游的订单号与 `platformOrderNo` 不同时返回，返回时参与响应签名 |
| acquire | object | 收单结果 |
| instruction | object | 银行转账指引 |
| timestamp | string | 响应时间戳 |
| nonce | string | 响应随机串 |
| apiVersion | string | API版本 |
| sign | string | 响应签名 |

### acquire 对象（可选）
| 参数名 | 类型 | 说明 |
|---|---|---|
| upstreamTxnId | string | 上游交易ID |
| status | string | 订单状态（如 `AWAIT_PAY` / `PENDING` / `SUCCESS` / `FAILED`） |
| codeUrl | string | 二维码地址（`qr` / `crypto` 常见） |
| clientParams | object | 客户端调起参数 |
| paymentUrl | string | 上游支付页 URL（`h5` 等场景常见） |
| raw | string | 上游原始响应 |

### instruction 对象（可选）
| 参数名 | 类型 | 说明 |
|---|---|---|
| accountName | string | 收款账户名 |
| accountNo | string | 收款账号 |
| bankName | string | 收款银行名称 |
| routingNo | string | 路由号/联行号 |
| refCode | string | 转账附言/备注 |
| expireAt | datetime | 指引过期时间（UTC） |

### 响应验签说明
- 在响应含有效 `sign` 时：商户取响应业务字段，排除 `sign` 后按与请求相同的规则重算并比对；不一致则判定验签失败。
- `v1.0`、`v1.1` 均按实际非空响应字段验签。`upstreamSubmitOrderNo` 非空时，以小写键名 `upstreamsubmitorderno` 参与响应签名；它是平台发送给上游的订单引用号，不等于上游返回的 `acquire.upstreamTxnId`。
- 商户不存在、IP 拒绝、密钥不可用、签名算法不支持等**前置安全失败**时，响应可能**无有效 `sign`**，请以 `rspCode`/`rspMsg` 为准。

### 请求示例
```json
{
  "appId": "appid_demo_001",
  "merchantOrderNo": "ORD202603080001",
  "amount": 10025,
  "displayAmount": 9900,
  "timestamp": "1772945400",
  "nonce": "c2aa0a95e6f74271",
  "apiVersion": "v1.1",
  "currency": "CNY",
  "channelCode": "wallet",
  "languageCode": "zh",
  "payerEmail": "demo@example.com",
  "payerOpenId": "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o",
  "instrument": {
    "bankCode": "ICBC"
  },
  "ext": {
    "scene": "checkout"
  },
  "subject": "购买VIP会员",
  "sign": "5E7D3A2C4FBE1D7E5E5A7E0C2F8F6A8C"
}
```

### 签名前待加密串示例
以下示例对应上面的请求体，已完成：
- 排除 `sign`
- 复杂对象扁平化
- 参数名转小写
- 按 ASCII 升序排序
- 对值执行 `urlEncode`

```text
amount=10025&apiversion=v1.1&appid=appid_demo_001&channelcode=wallet&currency=CNY&displayamount=9900&ext.scene=checkout&instrument.bankcode=ICBC&languagecode=zh&merchantorderno=ORD202603080001&paymethodcode=qr&payeremail=demo%40example.com&payeropenid=oUpF8uMuAJO_M2pxb1Q9zNjWeS6o&subject=%E8%B4%AD%E4%B9%B0VIP%E4%BC%9A%E5%91%98&timestamp=1772945400&key=YOUR_SIGN_KEY
```

### 响应示例
```json
{
  "appId": "appid_demo_001",
  "rspCode": "PAY_000",
  "rspMsg": "",
  "platformOrderNo": "PLT20260308000001",
  "upstreamSubmitOrderNo": "PLT20260308000001_A02",
  "acquire": {
    "status": "AWAIT_PAY",
    "codeUrl": "weixin://wxpay/bizpayurl?pr=abc123xyz"
  },
  "timestamp": "1772945401",
  "nonce": "4d56f98ecb1f4df4",
  "apiVersion": "v1.1",
  "sign": "2E0D3D1E5A2B4C9A613C1F4BA5099A3A"
}
```

---

## 二、统一代付

### 接口
- `POST /api/PayRequest/UnifiedPayout`

### 接口概述
- 创建代付（提现）订单；`channelCode` 保留但非必填。不传时平台按 `currency`、`countryCode`、`payeeType`、金额、商户启用产品、通道状态和渠道台账余额自动选择一个可完整出款的通道；填写时表示尝试指定通道，但仍需通过币种、国家、账户类型、金额、状态、余额和风控校验。
- 请求签名使用 MD5，服务端按相同规则验签；需配置商户 API 白名单 IP。
- 在可通过商户密钥对响应签名的情况下，响应含 `rspCode`、`rspMsg`、`timestamp`、`nonce`、`apiVersion`、`sign`；**`rspCode === PAY_000` 表示受理成功**（大额等场景可能返回 `auditStatus=PENDING` 进入人工审核，无上游结果）。前置安全失败类响应可能无有效 `sign`（见文档说明）。
- `applyAmount` 按分传输；**`currency` 可不传，平台按默认 `CNY` 参与服务端验签**。即：即使请求 JSON 未出现 `currency` 字段，签名串中仍须包含 `currency=CNY`（与平台规则一致）；**建议请求中显式传 `currency`** 以避免歧义。
- 多国家代付场景下，不同 `payTypeCode` 的必填参数不同。接入 NovaVexis 渠道时，请同时参考附录 [开放接口附录-NovaVexis代付pay_type_code接入说明.md](./开放接口附录-NovaVexis代付pay_type_code接入说明.md)。
- 接入 CowPay 渠道时，请同时参考附录 [开放接口附录-CowPay代付pay_type_code接入说明.md](./开放接口附录-CowPay代付pay_type_code接入说明.md)。
- 接入 Eqpay 渠道时，请同时参考附录 [开放接口附录-Eqpay代付pay_type_code接入说明.md](./开放接口附录-Eqpay代付pay_type_code接入说明.md)。
- 接入 Fzpay 渠道时，请同时参考附录 [开放接口附录-Fzpay代付pay_type_code接入说明.md](./开放接口附录-Fzpay代付pay_type_code接入说明.md)。
- 接入 Ynuopay 渠道时，请同时参考附录 [开放接口附录-Ynuopay代付pay_type_code接入说明.md](./开放接口附录-Ynuopay代付pay_type_code接入说明.md)。
- 接入 XLPay 渠道时，请同时参考附录 [开放接口附录-XLPay代付pay_type_code接入说明.md](./开放接口附录-XLPay代付pay_type_code接入说明.md)。
- 接入 TopPay 渠道时，请同时参考附录 [开放接口附录-TopPay代付pay_type_code接入说明.md](./开放接口附录-TopPay代付pay_type_code接入说明.md)。
- 接入 gmylhxe 渠道时，请同时参考附录 [开放接口附录-gmylhxe接入说明.md](./开放接口附录-gmylhxe接入说明.md)，商户只传平台标准 `payTypeCode`、`payeeType` 和 `payeeBankCode`，不得传上游原始产品码或银行码。
- 接入 khpay 柬埔寨渠道时，请参考 [开放接口附录-khpay代付账户类型说明.md](./开放接口附录-khpay代付账户类型说明.md)：钱包/支付机构使用页面列出的品牌 `payeeType`；银行使用 `payeeType=BANK` 与平台标准 `KH-BANK-*` 码，不得提交上游原始 `channelCode`。
- 接入 TarsPay 印尼渠道时，请参考 [开放接口附录-tarspay代付账户类型说明.md](./开放接口附录-tarspay代付账户类型说明.md)。银行代付的 `payeeBankCode` 必须传平台印尼标准银行码；钱包代付传平台标准 `payeeType`，不得直接传 `BANK_* / EWALLET_*` 上游原始码。
- 接入 tigerpay 孟加拉渠道时，请参考 [tigerpay 孟加拉接入说明](./开放接口附录-tigerpay孟加拉接入说明.md)。钱包代付使用标准 `payeeType=BKASH/NAGAD`，`payeeAccount` 为钱包账号，无需传上游原始银行字段。

### 请求参数
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| appId | string | 是 | 应用ID |
| merchantOrderNo | string | 是 | 商户代付订单号 |
| balanceType | string | 否 | 余额类型：BALANCE / PROFIT_BALANCE |
| applyAmount | long | 是 | 代付金额（分，正整数） |
| currency | string | 否 | 币种（默认 CNY） |
| channelCode | string | 否 | 代付通道编码，保留但非必填；不传时平台自动路由选择单一可完整出款通道，填写时表示尝试指定通道但仍需通过币种、国家、账户类型、金额、状态、余额和风控校验。 |
| payeeType | string | 是 | 平台标准账户类型：如 BANK、PIX_EMAIL、PIX_CPF、GCASH 等 |
| payeeAccount | string | 是 | 收款账号 |
| timestamp | string | 是 | Unix时间戳（秒） |
| nonce | string | 是 | 随机字符串 |
| apiVersion | string | 是 | API版本，支持 `v1.0`、`v1.1` |
| sign | string | 是 | 请求签名 |
| payeeName | string | 条件 | 收款人完整姓名。完整姓名渠道按字段矩阵填写；要求独立名/姓的产品不得用本字段替代 |
| payeeFirstName | string | 条件 | 收款人名，必须与 `payeeLastName` 同时提交；Kilipay 智利及字段矩阵标注的美国拆分姓名产品必填 |
| payeeLastName | string | 条件 | 收款人姓，必须与 `payeeFirstName` 同时提交；平台不从 `payeeName` 猜测拆分 |
| payeeBankCode | string | 否 | 收款银行编码 |
| payeeBankName | string | 否 | 收款银行名称 |
| payeeBranchName | string | 否 | 支行名称 |
| payeeProvince | string | 否 | 省份 |
| payeeCity | string | 否 | 城市 |
| payeeMobile | string | 否 | 收款人手机号 |
| payeeIdCard | string | 否 | 税号、CPF、CNPJ、RUT 等税务实名编号；普通证件号使用 `identityNo` |
| payeeEmail | string | 否 | 收款人邮箱 |
| ifsc | string | 否 | 印度 IFSC；印度银行代付统一放这里 |
| identityType | string | 否 | 普通证件类型，使用平台标准枚举，见「证件类型标准」 |
| identityNo | string | 否 | 普通证件号码；有值时必须同时传 `identityType` |
| payeeBranchCode | string | 否 | 支行号/分支号 |
| notifyUrl | string | 否 | 异步通知地址 |
| subject | string | 否 | 代付主题 |
| remark | string | 否 | 备注 |
| merchantUserId | string | 否 | 商户用户ID |
| countryCode | string | 否 | 国家代码（ISO 3166-1 alpha-2） |
| payTypeCode | string | 否 | 代付类型编码 |
| languageCode | string | 否 | 响应文案语言；未传、空白或无法识别时默认英文，不按商户国家或币种推断。明确传入受支持的中文语言码时允许中文；非中文响应中的中文失败详情使用英文兜底。代付回调仍按商户国家、币种选语言。 |
| ext | object | 否 | 扩展键值对（`Dictionary<string,string>`），签名按 `ext.xxx` 扁平化参与 |

> CloudPay 智利代付：新商户标准必传 `identityType + identityNo`，其中 `identityType` 仅支持 `ID_CARD/TAX_ID`，`identityNo` 填智利 RUT；标准证件对只传其中一个时直接拒绝。旧接入仅在两个标准字段均未传时兼容 `payeeIdCard`；两组同时存在时忽略旧字段且不比较一致性。最终 RUT 归一化后必须恰好 9 位数字。`payeeType` 必须显式传 `CHECKING/RUT_ACCOUNT/SAVINGS/VISTA`，分别映射为上游 `reserve1=1/2/3/4`；不支持 `BANK`，不根据账号位数推断账户类型，最终 RUT 映射到上游 `reserve2`。

> 智利收款人姓名：Kilipay 必须分别传 `payeeFirstName` 和 `payeeLastName`，两者缺一即拒绝，`payeeName` 不用于自动拆分。其他智利渠道可传 `payeeName`，或同时传完整的名和姓；两组都有值时优先使用 `payeeName`，没有 `payeeName` 时才组合“名 + 空格 + 姓”。

### 响应参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| appId | string | 应用ID（回显） |
| rspCode | string | 业务码，`PAY_000` 为成功 |
| rspMsg | string | 与 `rspCode` 配套的多语言说明；失败时含原因摘要，完整码表见 `pay-codes-zh-CN.json` / `api-docs.html` |
| platformOrderNo | string | 平台订单号 |
| auditStatus | string | 审核状态：`AUTO_APPROVED`（自动通过并尝试调上游）/ `PENDING`（待人工审核）等 |
| payout | object | 上游代付结果（通常仅在 `AUTO_APPROVED` 且已调上游时有值） |
| message | string | 提示信息 |
| timestamp | string | 响应时间戳 |
| nonce | string | 响应随机串 |
| apiVersion | string | API版本 |
| sign | string | 响应签名 |

### payout 对象（可选）
| 参数名 | 类型 | 说明 |
|---|---|---|
| upstreamTxnId | string | 上游交易ID |
| status | string | 上游处理状态 |
| raw | string | 上游原始响应（JSON字符串） |

### 响应验签说明
- 在响应含有效 `sign` 时，商户排除 `sign` 后按相同规则重算并比对；验签失败时不要据此更新代付状态。
- 前置安全失败类响应可能无有效 `sign`，请以 `rspCode`/`rspMsg` 为准。

### 请求示例
```json
{
  "appId": "appid_demo_001",
  "merchantOrderNo": "WD202603080001",
  "applyAmount": 50000,
  "balanceType": "BALANCE",
  "currency": "CNY",
  "channelCode": "bank_out",
  "payeeType": "BANK",
  "payeeName": "张三",
  "payeeAccount": "6222021234567890123",
  "payeeBankCode": "ICBC",
  "payeeBankName": "中国工商银行",
  "payeeBranchName": "科技园支行",
  "payeeProvince": "广东省",
  "payeeCity": "深圳市",
  "payeeMobile": "13800138000",
  "identityType": "ID_CARD",
  "identityNo": "440101199001010011",
  "merchantUserId": "U10001",
  "countryCode": "IN",
  "payTypeCode": "12001",
  "languageCode": "zh",
  "notifyUrl": "https://merchant.example.com/payout-notify",
  "timestamp": "1772945402",
  "nonce": "2dc93fe6a2e24dcb",
  "apiVersion": "v1.0",
  "sign": "5F9E2737B4EA7AD8B01A9721C0CCF8E2"
}
```

### 签名前待加密串示例
```text
apiversion=v1.0&applyamount=50000&balancetype=BALANCE&channelcode=bank_out&countrycode=IN&currency=CNY&identityno=440101199001010011&identitytype=ID_CARD&languagecode=zh&merchantorderno=WD202603080001&merchantuserid=U10001&nonce=2dc93fe6a2e24dcb&notifyurl=https%3A%2F%2Fmerchant.example.com%2Fpayout-notify&payeeaccount=6222021234567890123&payeebankcode=ICBC&payeebankname=%E4%B8%AD%E5%9B%BD%E5%B7%A5%E5%95%86%E9%93%B6%E8%A1%8C&payeebranchname=%E7%A7%91%E6%8A%80%E5%9B%AD%E6%94%AF%E8%A1%8C&payeecity=%E6%B7%B1%E5%9C%B3%E5%B8%82&payeemobile=13800138000&payeename=%E5%BC%A0%E4%B8%89&payeeprovince=%E5%B9%BF%E4%B8%9C%E7%9C%81&payeetype=BANK&paytypecode=12001&timestamp=1772945402&key=YOUR_SIGN_KEY
```

### 响应示例
```json
{
  "appId": "appid_demo_001",
  "rspCode": "PAY_000",
  "rspMsg": "",
  "platformOrderNo": "PLT_OUT_20260308000001",
  "auditStatus": "AUTO_APPROVED",
  "payout": {
    "upstreamTxnId": "BANK_OUT_ABC123",
    "status": "PENDING"
  },
  "message": "自动审核通过，已提交上游处理",
  "timestamp": "1772945403",
  "nonce": "9538f40e15bc433e",
  "apiVersion": "v1.0",
  "sign": "6BB0BAFA3B0143C6770A29C08D52E912"
}
```

---

## 三、订单查询

### 3.1 查询代收订单
- `POST /api/PayRequest/QueryPayOrder`

接口概述：
- 按 `appId + merchantOrderNo` 查询代收订单。
- 请求签名字段 `sign` 请放在 **JSON Body** 或 **Header**（不支持 Query `sign`）。
- 在响应含有效 `sign` 时须验签；前置安全失败可能无有效 `sign`。
- 响应中的 `feeAmount`、`feeCurrency`、`merchantFeeRate`、`merchantCostRate`、`merchantCostAmount`、`merchantCostCurrency` 在非空时参与响应签名（包括数值 0）；新增字段适用于 v1.0/v1.1。

请求参数：

| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| appId | string | 是 | 应用ID |
| merchantOrderNo | string | 是 | 商户订单号 |
| timestamp | string | 是 | Unix时间戳（秒） |
| nonce | string | 是 | 随机字符串 |
| apiVersion | string | 是 | API版本，固定`v1.0` |
| sign | string | 是 | 请求签名 |
| languageCode | string | 否 | 语言代码（影响 `statusText` / `rspMsg` 等） |

响应参数：

| 参数名 | 类型 | 说明 |
|---|---|---|
| appId | string | 应用ID（回显） |
| rspCode | string | 业务码，`PAY_000` 为成功 |
| rspMsg | string | 与 `rspCode` 配套的多语言说明；失败时含原因摘要，完整码表见 `pay-codes-zh-CN.json` / `api-docs.html` |
| platformOrderNo | string | 平台订单号 |
| upstreamSubmitOrderNo | string | `v1.0`、`v1.1` 均支持。仅当实际提交给上游的订单号与 `platformOrderNo` 不同时返回，返回时参与响应签名 |
| merchantOrderNo | string | 商户订单号 |
| amount | long | 订单金额（分，整数） |
| paidAmount | long | 用户实际支付金额（分，整数）。默认等于 `amount`；转账类产品上游明确返回实付金额时以本字段为准。 |
| currency | string | 币种（ISO 4217） |
| providerKey | string | 本单实际使用的渠道标识；有值时参与响应签名 |
| providerName | string | 本单实际使用的渠道名称；有值时参与响应签名 |
| actualAmount | long? | 代收订单的商户侧实际实收/可结算净额（分，整数，可空） |
| feeAmount | long? | 平台向商户收取的手续费（分，可空）：Mode1 为技术服务费，Mode2 为交易手续费。Mode1 按订单锁定的原费率及计费基数计算，不使用退款冲正后的剩余服务费；Mode2 优先原商户手续费金额快照，缺失时按订单锁定费率及计费基数计算，无法可靠确定时为空 |
| feeCurrency | string | 订单手续费币种；与 `feeAmount` 同时返回 |
| merchantFeeRate | decimal? | 平台向商户收费的订单费率快照：Mode1 技术服务费率，Mode2 交易手续费率；小数表示（如 `0.009` 表示 0.9%） |
| merchantCostRate | decimal? | 商户侧交易成本费率快照；Mode1 为自有上游成本费率，Mode2 等于 merchantFeeRate，不暴露平台内部上游成本。小数表示，如 0.02 表示 2% |
| merchantCostAmount | long? | 商户侧交易手续费（分），不含另收的平台技术服务费；Mode1 使用渠道成本金额快照，缺失时为空；Mode2 与 feeAmount 为同一笔费用，不能重复相加 |
| merchantCostCurrency | string? | merchantCostAmount 的 ISO 4217 币种；金额与币种完整时成对返回，Mode2 与 feeCurrency 一致 |
| status | string | 机器可读状态字，如 `CASHIER_PENDING`、`INIT`、`PROCESSING`、`SUCCESS`、`FAILED`、`CLOSED`、`REFUNDED`、`UNKNOWN` |
| statusText | string | 状态说明（多语言） |
| payMethodCode | string | 支付方式编码（可能为空，视订单数据而定） |
| subject | string | 订单标题 |
| channelOrderNo | string | 上游返回的交易流水/渠道订单号；不等于 `upstreamSubmitOrderNo` |
| createdTime | datetime | 创建时间 |
| updatedTime | datetime | 更新时间 |
| timestamp | string | 响应时间戳 |
| nonce | string | 响应随机串 |
| apiVersion | string | API版本 |
| sign | string | 响应签名 |

签名前待加密串示例：

```text
apiversion=v1.1&appid=appid_demo_001&merchantorderno=ORD202603150001&nonce=qpay8d17ac4f77a1&timestamp=1773542400&key=YOUR_SIGN_KEY
```

请求示例：

```json
{
  "appId": "appid_demo_001",
  "merchantOrderNo": "ORD202603150001",
  "timestamp": "1773542400",
  "nonce": "qpay8d17ac4f77a1",
  "apiVersion": "v1.1",
  "sign": "4E2DF2A34D54C4EFA789F8C0B0B31A77"
}
```

响应示例：

```json
{
  "appId": "appid_demo_001",
  "rspCode": "PAY_000",
  "rspMsg": "",
  "platformOrderNo": "PLT20260315000001",
  "upstreamSubmitOrderNo": "PLT20260315000001_A02",
  "merchantOrderNo": "ORD202603150001",
  "amount": 10000,
  "paidAmount": 10000,
  "currency": "CNY",
  "providerKey": "mock_sandbox",
  "providerName": "Mock Sandbox",
  "actualAmount": 9910,
  "feeAmount": 90,
  "feeCurrency": "CNY",
  "merchantFeeRate": 0.009,
  "merchantCostRate": 0.009,
  "merchantCostAmount": 90,
  "merchantCostCurrency": "CNY",
  "status": "SUCCESS",
  "statusText": "支付成功",
  "payMethodCode": "qr",
  "subject": "购买VIP会员",
  "channelOrderNo": "UP202603150001",
  "createdTime": "2026-03-15T09:00:00",
  "updatedTime": "2026-03-15T09:02:00",
  "timestamp": "1773542401",
  "nonce": "9d64f5c0d2be4d19",
  "apiVersion": "v1.1",
  "sign": "E24D646AF1BA8CA984A34A380684E5E0"
}
```

费用口径说明：

- **Mode1 自建上游**：merchantCostAmount 是自有上游渠道成本，feeAmount 是另收的平台技术服务费。例如 1,000 PHP 订单、渠道成本费率 2%，merchantCostAmount 为 2,000 分 PHP；技术服务费另按 feeCurrency 核算，不同币种不可直接相加。
- **Mode2 平台上游**：上面的成功示例为 Mode2。新旧字段分别表示同一笔费用，merchantCostAmount 与 feeAmount 不能重复相加。
- 费用与费率仅使用订单快照，不读取当前配置。合作模式未知时，三个 merchantCost 字段为空；金额快照不足时金额和币种为空，费率可独立返回。空值不表示免费，0 表示已确定的零费用。
- 账务快照是平台记录的计费结果，不是上游实际扣款凭证；费用有值本身不代表已扣款，按费率快照计算的金额同样不能作为已扣款证明。

### 3.2 查询代付订单
- `POST /api/PayRequest/QueryPayoutOrder`

接口概述：
- 按 `appId + merchantOrderNo` 查询代付订单。
- 请求签名字段 `sign` 请放在 **JSON Body** 或 **Header**（不支持 Query `sign`）。
- 在响应含有效 `sign` 时须验签；前置安全失败可能无有效 `sign`。
- 响应中的 `feeAmount`、`merchantFeeRate`、`withdrawFeeAmount` 参与响应签名（空值按统一签名规则过滤）。

请求参数：

| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| appId | string | 是 | 应用ID |
| merchantOrderNo | string | 是 | 商户代付订单号 |
| timestamp | string | 是 | Unix时间戳（秒） |
| nonce | string | 是 | 随机字符串 |
| apiVersion | string | 是 | API版本，固定`v1.0` |
| sign | string | 是 | 请求签名 |
| languageCode | string | 否 | 响应文案语言；未传、空白或无法识别时默认英文，不按商户国家或币种推断。明确传入受支持的中文语言码时允许中文；非中文响应中的中文失败详情使用英文兜底。代付回调仍按商户国家、币种选语言。 |

响应参数：

| 参数名 | 类型 | 说明 |
|---|---|---|
| appId | string | 应用ID（回显） |
| rspCode | string | 业务码，`PAY_000` 为成功 |
| rspMsg | string | 与 `rspCode` 配套的多语言说明；失败时含原因摘要，完整码表见 `pay-codes-zh-CN.json` / `api-docs.html` |
| platformOrderNo | string | 平台代付订单号 |
| merchantOrderNo | string | 商户订单号 |
| applyAmount | long | 申请金额（分，整数） |
| currency | string | 币种（ISO 4217） |
| providerKey | string | 本单实际使用的渠道标识；有值时参与响应签名 |
| providerName | string | 本单实际使用的渠道名称；有值时参与响应签名 |
| feeAmount | long | 手续费（分，整数） |
| merchantFeeRate | decimal? | 下单时锁定的商户费率，小数表示（如 `0.009` 表示 0.9%） |
| withdrawFeeAmount | long | 下单时锁定的提现手续费（分，整数） |
| actualAmount | long | 实际出款金额（分，整数） |
| status | string | 机器可读状态字：`INIT`、`PENDING`、`SUCCESS`、`FAILED`、`CLOSED`、`AUDITING`、`UNKNOWN` |
| statusText | string | 状态说明（多语言） |
| payMethodCode | string | 代付方式编码（可空） |
| payeeType | string | 收款方类型 |
| payeeName | string | 收款人姓名 |
| payeeAccount | string | 收款账号 |
| payeeBankName | string | 收款银行名称 |
| createdTime | datetime | 创建时间 |
| settledTime | datetime | 完成/结算时间 |
| failCode | string | 失败代码；仅失败或有失败代码时输出 |
| failReason | string | 失败原因 |
| remark | string | 备注 |
| timestamp | string | 响应时间戳 |
| nonce | string | 响应随机串 |
| apiVersion | string | API版本 |
| sign | string | 响应签名 |

签名前待加密串示例：

```text
apiversion=v1.0&appid=appid_demo_001&merchantorderno=WD202603150001&nonce=qpout0e8cf98ab122&timestamp=1773542402&key=YOUR_SIGN_KEY
```

请求示例：

```json
{
  "appId": "appid_demo_001",
  "merchantOrderNo": "WD202603150001",
  "timestamp": "1773542402",
  "nonce": "qpout0e8cf98ab122",
  "apiVersion": "v1.0",
  "sign": "5B9C4F2BAE5B8279D287432595FD4712"
}
```

响应示例：

```json
{
  "appId": "appid_demo_001",
  "rspCode": "PAY_000",
  "rspMsg": "",
  "platformOrderNo": "PLT_OUT_20260315000001",
  "merchantOrderNo": "WD202603150001",
  "applyAmount": 50000,
  "currency": "CNY",
  "providerKey": "mock_sandbox",
  "providerName": "Mock Sandbox",
  "feeAmount": 500,
  "merchantFeeRate": 0.009,
  "withdrawFeeAmount": 500,
  "actualAmount": 49500,
  "status": "SUCCESS",
  "statusText": "代付成功",
  "payMethodCode": "bank_card_payout",
  "payeeType": "BANK",
  "payeeName": "张三",
  "payeeAccount": "6222021234567890123",
  "payeeBankName": "中国工商银行",
  "createdTime": "2026-03-15T10:00:00",
  "settledTime": "2026-03-15T10:05:00",
  "remark": "银行卡代付",
  "timestamp": "1773542403",
  "nonce": "80d83a5ff4a14781",
  "apiVersion": "v1.0",
  "sign": "0AD0B82F0D5E24D8E471A7ABCC8E5C31"
}
```

### 3.3 查询商户余额
- `POST /api/PayRequest/QueryMerchantBalance`

接口概述：
- 按商户 `appId` 查询渠道维度余额，返回各渠道 + 币种的可用、冻结、待结算、可提现、在途、分润可用、分润冻结等字段。
- 同时返回该商户已配置的全部代付能力；启用、停用和临时不可用能力均保留，并通过 `status` 说明当前状态。
- 响应中的金额字段单位均为 **分**；请求签名字段 `sign` 请放在 **JSON Body** 或 **Header**（不支持 Query `sign`）；IP 白名单、防重放与查询订单接口一致。
- 在响应含有效 `sign` 时须验签；前置安全失败可能无有效 `sign`。

请求参数：

| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| appId | string | 是 | 应用ID |
| timestamp | string | 是 | Unix时间戳（秒） |
| nonce | string | 是 | 随机字符串 |
| apiVersion | string | 是 | API版本，固定 `v1.0` |
| sign | string | 是 | 请求签名 |
| languageCode | string | 否 | 语言代码，影响 `rspMsg` 的多语言返回 |

签名前待加密串示例：

```text
apiversion=v1.0&appid=appid_demo_001&languagecode=zh-CN&nonce=bal7f4c3a8d09ef12&timestamp=1773542404&key=YOUR_SIGN_KEY
```

请求示例：

```json
{
  "appId": "appid_demo_001",
  "languageCode": "zh-CN",
  "timestamp": "1773542404",
  "nonce": "bal7f4c3a8d09ef12",
  "apiVersion": "v1.0",
  "sign": "A8B1C2D3E4F5061728394A5B6C7D8E9F"
}
```

响应参数：

| 参数名 | 类型 | 说明 |
|---|---|---|
| appId | string | 应用ID（回显） |
| rspCode | string | 业务码，`PAY_000` 为成功 |
| rspMsg | string | 与 `rspCode` 配套的多语言说明；失败时含原因摘要，完整码表见 `pay-codes-zh-CN.json` / `api-docs.html` |
| amountUnit | string | 响应内金额单位，固定为 `CENT`（分） |
| items | array | 按渠道 + 币种分行的余额列表 |
| items[].channelKey | string | 渠道 key |
| items[].channelName | string | 渠道名称 |
| items[].currency | string | 币种（ISO 4217） |
| items[].availableAmount | long | 可用余额（分） |
| items[].frozenAmount | long | 冻结余额（分） |
| items[].unsettledAmount | long | 待结算余额（分） |
| items[].withdrawableAmount | long | 可提现余额（分） |
| items[].inTransitAmount | long | 在途/处理中余额（分） |
| items[].profitAvailableAmount | long | 分润可用余额（分） |
| items[].profitFrozenAmount | long | 分润冻结余额（分） |
| payoutCapabilities | array | 当前商户已配置的全部代付能力，包含停用状态 |
| payoutCapabilities[].channelCode | string | 统一代付可提交的渠道编码 |
| payoutCapabilities[].channelName | string | 渠道展示名称 |
| payoutCapabilities[].countryCode | string | 国家/地区代码 |
| payoutCapabilities[].currency | string | 代付币种 |
| payoutCapabilities[].payTypeCode | string | 平台标准支付类型，不是上游产品编码 |
| payoutCapabilities[].payTypeName | string | 支付类型展示名称 |
| payoutCapabilities[].payeeType | string | 平台标准收款账户类型 |
| payoutCapabilities[].limits | object | 单笔、日、月和笔数限额，金额单位为分 |
| payoutCapabilities[].status.available | bool | 是否具备基础路由资格，不承诺本次代付必然成功 |
| payoutCapabilities[].status.code | string | `AVAILABLE`、`DEGRADED`、`DISABLED` 或 `TEMPORARILY_UNAVAILABLE` |
| payoutCapabilities[].status.reasons | array | 停用、降级或临时不可用原因码 |
| payoutCapabilities[].status.configurationStatus | string | 商户代付配置状态 |
| payoutCapabilities[].status.channelStatus | string | 渠道综合状态 |
| payoutCapabilities[].status.methodStatus | string | 支付方式综合状态 |
| payoutCapabilities[].status.payTypeStatus | string | 平台支付类型状态 |
| payoutCapabilities[].status.circuitStatus | string | `CLOSED`、`HALF_OPEN` 或 `OPEN` |
| payoutCapabilities[].requestFields | array | 对应代付能力的平台标准请求字段说明 |
| timestamp | string | 响应时间戳 |
| nonce | string | 响应随机串 |
| apiVersion | string | API版本 |
| sign | string | 响应签名 |

响应示例：

```json
{
  "appId": "appid_demo_001",
  "rspCode": "PAY_000",
  "rspMsg": "操作成功",
  "amountUnit": "CENT",
  "items": [
    {
      "channelKey": "fastpay66",
      "channelName": "FastPay66",
      "currency": "CNY",
      "availableAmount": 1250000,
      "frozenAmount": 50000,
      "unsettledAmount": 120000,
      "withdrawableAmount": 1180000,
      "inTransitAmount": 0,
      "profitAvailableAmount": 32000,
      "profitFrozenAmount": 0
    },
    {
      "channelKey": "vcpay",
      "channelName": "VCPay",
      "currency": "USD",
      "availableAmount": 860500,
      "frozenAmount": 10000,
      "unsettledAmount": 25000,
      "withdrawableAmount": 850500,
      "inTransitAmount": 0,
      "profitAvailableAmount": 12600,
      "profitFrozenAmount": 0
    }
  ],
  "payoutCapabilities": [
    {
      "channelCode": "fastpay66",
      "channelName": "FastPay66",
      "countryCode": "IN",
      "currency": "INR",
      "payTypeCode": "upi",
      "payTypeName": "UPI",
      "payeeType": "UPI",
      "limits": {
        "amountUnit": "CENT",
        "singleMinAmount": 10000,
        "singleMaxAmount": 100000000,
        "dailyAmountLimit": null,
        "monthlyAmountLimit": null,
        "dailyCountLimit": null,
        "periodTimeZone": "UTC"
      },
      "status": {
        "available": false,
        "code": "DISABLED",
        "reasons": ["ROUTE_CONFIGURATION_DISABLED"],
        "configurationStatus": "DISABLED",
        "channelStatus": "ENABLED",
        "methodStatus": "ENABLED",
        "payTypeStatus": "ENABLED",
        "circuitStatus": "CLOSED"
      },
      "requestFields": []
    }
  ],
  "timestamp": "1773542405",
  "nonce": "5d39470a8f62488b",
  "apiVersion": "v1.0",
  "sign": "1F2E3D4C5B6A79887766554433221100"
}
```

说明：
- `items` 可能为空数组，表示该商户当前没有启用中的币种总账记录。
- `payoutCapabilities` 只返回该商户已配置且结构有效的代付能力，不返回平台未分配给该商户的渠道；停用能力不会被过滤。
- `status.available=true` 仅表示当前配置具备基础路由资格，实际出款仍会校验金额、渠道账户余额、累计限额、收款参数、风控和上游实时状态。
- 所有金额字段均为整数分；商户展示为元时请自行除以 100。
- 商户收到响应后，应先排除 `sign` 字段并按同规则验签，验签通过后再使用余额结果。

### 3.4 生成收银台令牌
- `POST /api/PayRequest/GenerateCashierToken`

接口概述：商户服务端用 **MD5 签名** 换收银台跳转令牌；返回 `cashierUrl`、`qrCodeBase64`、`platformOrderNo`（预订单号，可立即用于 `QueryPayOrder`）、`expiresAt`、`cashierStyle`、`cashierBrandName` 等。`appId + merchantOrderNo` 幂等：重复请求返回同一短链（在令牌仍有效时），并返回首次生成链接绑定的收银台页面风格和展示品牌名。

**重要：** 本接口验签**仅读取 JSON Body 中的 `sign`**，请勿将 `sign` 仅放在 Header（将无法通过验签）。`displayAmount`、`languageCode`、`cashierStyle`、`cashierBrandName` 为可选请求字段，传入时均参与签名。

请求参数（业务字段）：

| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| appId | string | 是 | 应用ID |
| merchantOrderNo | string | 是 | 商户订单号 |
| amount | long | 是 | 金额（分） |
| displayAmount | long | 否 | 代收收银台展示金额（分）；不传/空/`0` 按真实金额显示，`<0` 隐藏金额，`>0` 按该值展示；仅影响收银台展示，不影响真实订单金额、路由、上游提交或结算；传入非空值时参与签名 |
| currency | string | 是 | 币种 |
| subject | string | 是 | 订单标题 |
| languageCode | string | 否 | 语言码，影响 `rspMsg` 等；参与签名 |
| payMethodCode | string | 否 | 预选支付方式编码 |
| country | string | 否 | 国家代码 |
| payTypeCode | string | 否 | 支付类型编码 |
| notifyUrl / returnUrl | string | 否 | 回调与回跳，不传可用商户后台默认 |
| expiresIn | int | 否 | 令牌有效秒数（默认 1800，以平台为准） |
| cashierStyle | string | 否 | 收银台页面风格，可选 `default`、`clean`、`compact`、`brand`；不传或空值使用 `default`。非法值返回参数错误。 |
| cashierBrandName | string | 否 | 收银台展示品牌名，最长 32 个字符；不传或空值使用 `AllOnePay`。仅影响收银台页面标题和顶部品牌展示，不影响路由、账务或订单。非法字符（如 `<`、`>`、控制字符）返回参数错误。 |
| timestamp、nonce、apiVersion、sign | | 是 | 公共信封字段；**`sign` 必须置于 Body** |

说明：请求体中若存在 `clientIp`、付款人相关顶层字段、`displayAmount`、`cashierStyle`、`cashierBrandName` 等，是否参与签名遵循统一扁平化规则；**当前版本**预订单以客户连接 IP 为准，不保证 `clientIp` 透传至后续支付请求，接入时请勿依赖其业务效果。

### 商户自有收银台的支付名称

`POST /api/PayRequest/MerchantHostedPaymentMethods` 返回的 `methods[].name` 和 `methods[].shortName` 用于展示；下单仍将原 `paymentId` 传回 `MerchantHostedPay`，不能用名称代替编码。

商户可在后台“自助路由”的代收支付类型处编辑支付名称与短名称，按当前商户应用、国家、币种和标准支付类型生效。同类型的多个上游通道共用名称；平台收银台也使用该配置。

| 字段 | 展示规则 |
|---|---|
| `name` | 商户完整名称；未填时沿用平台当前语言及默认名称规则 |
| `shortName` | 商户短名称 → 商户完整名称 → 平台原短名称 |

两项留空保存或恢复平台名称后，实时跟随平台默认值。自定义文字适用于所有语言，`locale` 仍表示平台翻译的命中语言。名称不影响路由、金额、银行编码或订单身份；商户自行缓存列表时须刷新后才能看到新名称。平台响应仍按原规则包含名称字段参与签名。

### 3.5 联调生成签名（可选）
- **公开试算（匿名，仅建议测试环境）：** `POST /api/PayRequest/GenerateSignaturePublic`  
  请求体传入 `parameters`（键值与统一下单等接口一致）与 `key`（商户签名密钥），服务端按平台规则返回 MD5 签名，便于与本地算签对齐。

- **管理端接口（不对商户开放）：** `POST /api/PayRequest/GenerateSignature` 需后台登录鉴权，由平台按 `appId` 取密钥算签；**请勿**作为开放对接文档中的默认联调路径。

生产环境请在商户服务端**本地**按本文「签名规则」计算 `sign`。

---

### 3.6 产品附录

当商户已经确定具体 `payTypeCode` 时，建议直接进入对应附录查看必填字段、条件必填字段和最小请求示例：

| 附录 | 适用范围 |
|---|---|
| [开放接口附录-代收pay_type_code接入说明.md](./开放接口附录-代收pay_type_code接入说明.md) | 代收方向总目录（按渠道跳转各附录） |
| [开放接口附录-代付pay_type_code接入说明.md](./开放接口附录-代付pay_type_code接入说明.md) | 代付方向总目录（按渠道跳转各附录） |
| [开放接口附录-CHANGELOG.md](./开放接口附录-CHANGELOG.md) | 附录与主数据配套文件变更摘要 |
| [开放接口附录-多渠道联调最小请求示例汇总.md](./开放接口附录-多渠道联调最小请求示例汇总.md) | 测试商户快速联调入口 |
| [开放接口附录-回调验签与成功响应最小实现示例.md](./开放接口附录-回调验签与成功响应最小实现示例.md) | 下游商户服务端回调处理 |
| [开放接口附录-NovaVexis代收pay_type_code接入说明.md](./开放接口附录-NovaVexis代收pay_type_code接入说明.md) | NovaVexis 代收产品 |
| [开放接口附录-NovaVexis代付pay_type_code接入说明.md](./开放接口附录-NovaVexis代付pay_type_code接入说明.md) | NovaVexis 代付产品 |
| [开放接口附录-CowPay代收pay_type_code接入说明.md](./开放接口附录-CowPay代收pay_type_code接入说明.md) | CowPay 代收产品 |
| [开放接口附录-CowPay代付pay_type_code接入说明.md](./开放接口附录-CowPay代付pay_type_code接入说明.md) | CowPay 代付产品 |
| [开放接口附录-Eqpay代收pay_type_code接入说明.md](./开放接口附录-Eqpay代收pay_type_code接入说明.md) | Eqpay 代收产品 |
| [开放接口附录-Eqpay代付pay_type_code接入说明.md](./开放接口附录-Eqpay代付pay_type_code接入说明.md) | Eqpay 代付产品 |
| [开放接口附录-Fzpay代收pay_type_code接入说明.md](./开放接口附录-Fzpay代收pay_type_code接入说明.md) | Fzpay 代收产品 |
| [开放接口附录-Fzpay代付pay_type_code接入说明.md](./开放接口附录-Fzpay代付pay_type_code接入说明.md) | Fzpay 代付产品 |
| [开放接口附录-Ynuopay代收pay_type_code接入说明.md](./开放接口附录-Ynuopay代收pay_type_code接入说明.md) | Ynuopay 代收产品 |
| [开放接口附录-Ynuopay代付pay_type_code接入说明.md](./开放接口附录-Ynuopay代付pay_type_code接入说明.md) | Ynuopay 代付产品 |
| [开放接口附录-XLPay代收pay_type_code接入说明.md](./开放接口附录-XLPay代收pay_type_code接入说明.md) | XLPay 代收产品 |
| [开放接口附录-XLPay代付pay_type_code接入说明.md](./开放接口附录-XLPay代付pay_type_code接入说明.md) | XLPay 代付产品 |
| [开放接口附录-TopPay代收pay_type_code接入说明.md](./开放接口附录-TopPay代收pay_type_code接入说明.md) | TopPay 代收产品 |
| [开放接口附录-TopPay代付pay_type_code接入说明.md](./开放接口附录-TopPay代付pay_type_code接入说明.md) | TopPay 代付产品 |

| [开放接口附录-gmylhxe接入说明.md](./开放接口附录-gmylhxe接入说明.md) | gmylhxe 十国代收/代付、账户类型、银行映射与订单号语义 |

## 四、下游回调通知

### 4.1 触发规则
- 订单达到终态 **`SUCCESS` 或 `FAILED`** 时，若该笔订单配置了 **`notifyUrl`**，平台会发起异步通知（代收、代付均可能推送失败态，便于商户对账与解冻业务）。
- 通知可能重试；请以 **幂等** 方式处理（建议以 `platformOrderNo` 或 `merchantOrderNo` 去重）。
- 单笔订单通知成功（商户返回约定成功应答）后，平台一般不再重复推送同一次终态（具体以平台实现为准）。
- 回调请求统一使用 `POST` + `application/json`。
- 代收通知金额字段含义：`amount` 为下单金额，`paidAmount` 为用户实际支付金额，`actualAmount` 为商户侧实际实收/可结算净额；转账类产品可能少付或多付，请优先用 `paidAmount` 做用户实付对账。
- 代收、代付通知会在有值时返回 `providerKey` 和 `providerName`，表示本单实际使用的渠道；这两个字段有值时参与回调签名。

### 4.2 回调成功判定
- HTTP 状态码必须为 `200`
- 响应体满足以下任一条件即视为成功：
  - 纯文本：`success`
  - JSON：`{"code":10000}` 或 `{"code":"10000"}`

### 4.3 回调签名规则
- 回调体中的 `sign` 生成规则，与开放接口请求/响应签名规则一致：
  1. 排除 `sign`
  2. 过滤 `null`
  3. 参数名转小写
  4. 按 ASCII 升序排序
  5. 按 `key=urlEncode(value)` 拼接
  6. 末尾追加 `&key=商户签名密钥`
  7. MD5 得到 32 位十六进制；平台下发为**默认小写**，商户验签建议**忽略大小写**比较

### 4.4 代收回调示例（成功）

回调体字段与开放接口一致（camelCase）。**成功**时 `rspCode` 为 `PAY_000`，`status` 为字符串 `SUCCESS`；**失败**终态时 `rspCode` 多为 `PAY_NOTIFY_002`，`status` 为 `FAILED`（具体文案见 `rspMsg` / `statusText`）。

费用字段与代收查询使用同一订单快照口径：

| 字段 | 类型 | 说明 |
|---|---|---|
| feeAmount | long? | 平台向商户收取的手续费（分）；Mode1 为平台技术服务费，Mode2 为交易手续费。Mode1 按订单锁定的原费率及计费基数计算，不使用退款冲正后的剩余服务费；Mode2 优先原商户手续费金额快照，缺失时按订单锁定费率及计费基数计算 |
| feeCurrency | string? | feeAmount 的 ISO 4217 币种 |
| merchantFeeRate | decimal? | 平台向商户收费的费率快照，小数表示，例如 0.009 表示 0.9% |
| merchantCostRate | decimal? | Mode1 自有上游成本费率；Mode2 等于 merchantFeeRate，不暴露平台内部上游成本 |
| merchantCostAmount | long? | 商户侧交易手续费（分），不含另收的平台技术服务费；Mode1 使用渠道成本金额快照；Mode2 等于 feeAmount |
| merchantCostCurrency | string? | merchantCostAmount 的 ISO 4217 币种，金额/币种完整时成对返回 |

- 六个字段非空（包括 0）时均输出并参与回调签名；空值不输出、不参与签名，空值不表示免费。
- Mode1 两组费用分别核算，不同币种不可直接相加；Mode2 表示同一笔费用，不能重复相加。以下为 Mode2 示例。
- 未知模式不返回 merchantCost 字段；成本金额/币种快照不足时省略金额/币种，费率可独立返回。不回读当前费率配置。
- 费用有值不单独证明已扣款，失败通知应结合 status 判断；自动通知、重试和手动通知使用相同口径。

```json
{
  "appId": "appid_demo_001",
  "rspCode": "PAY_000",
  "rspMsg": "成功",
  "platformOrderNo": "PLT20260315000001",
  "merchantOrderNo": "ORD202603150001",
  "amount": 10000,
  "paidAmount": 10000,
  "currency": "CNY",
  "providerKey": "mock_sandbox",
  "providerName": "Mock Sandbox",
  "actualAmount": 9910,
  "feeAmount": 90,
  "feeCurrency": "CNY",
  "merchantFeeRate": 0.009,
  "merchantCostRate": 0.009,
  "merchantCostAmount": 90,
  "merchantCostCurrency": "CNY",
  "status": "SUCCESS",
  "statusText": "支付成功",
  "payMethodCode": "qr",
  "subject": "购买VIP会员",
  "channelOrderNo": "UP202603150001",
  "paymentUrl": "https://cashier.example.com/pay/abc123",
  "createdTime": "2026-03-15T09:00:00",
  "updatedTime": "2026-03-15T09:02:00",
  "timestamp": "1773542405",
  "nonce": "30f1cbd18021409d",
  "apiVersion": "v1.0",
  "sign": "49c49448be8531b954984154b6333b7b"
}
```

签名前待加密串示例（字段以实际回调 JSON 为准，排除 `sign` 后参与；示例密钥为 `YOUR_SIGN_KEY`，空格编码为 `+`，示例 sign 为该串的 MD5）：

```text
actualamount=9910&amount=10000&apiversion=v1.0&appid=appid_demo_001&channelorderno=UP202603150001&createdtime=2026-03-15T09%3A00%3A00&currency=CNY&feeamount=90&feecurrency=CNY&merchantcostamount=90&merchantcostcurrency=CNY&merchantcostrate=0.009&merchantfeerate=0.009&merchantorderno=ORD202603150001&nonce=30f1cbd18021409d&paidamount=10000&paymenturl=https%3A%2F%2Fcashier.example.com%2Fpay%2Fabc123&paymethodcode=qr&platformorderno=PLT20260315000001&providerkey=mock_sandbox&providername=Mock+Sandbox&rspcode=PAY_000&rspmsg=%E6%88%90%E5%8A%9F&status=SUCCESS&statustext=%E6%94%AF%E4%BB%98%E6%88%90%E5%8A%9F&subject=%E8%B4%AD%E4%B9%B0VIP%E4%BC%9A%E5%91%98&timestamp=1773542405&updatedtime=2026-03-15T09%3A02%3A00&key=YOUR_SIGN_KEY
```

成功响应示例：

```text
success
```

### 4.5 代付回调示例（成功）

代付回调体中 **支付方式字段名为 `method`**（历史兼容），值为订单上的支付方式编码。成功时 `rspCode` 为 `PAY_000`；失败终态时 `rspCode` 多为 `PAY_NOTIFY_004`，`status` 为 `FAILED`，当前会携带 `failReason`。`failCode` 为预留字段，当前回调暂不赋值，空值不输出也不参与签名，后续商户完成兼容后再启用。

```json
{
  "appId": "appid_demo_001",
  "rspCode": "PAY_000",
  "rspMsg": "成功",
  "platformOrderNo": "PLT_OUT_20260315000001",
  "merchantOrderNo": "WD202603150001",
  "applyAmount": 50000,
  "currency": "CNY",
  "providerKey": "mock_sandbox",
  "providerName": "Mock Sandbox",
  "feeAmount": 500,
  "actualAmount": 49500,
  "status": "SUCCESS",
  "statusText": "代付成功",
  "method": "bank_card_payout",
  "payeeType": "BANK",
  "payeeName": "张三",
  "payeeAccount": "6222021234567890123",
  "payeeBankName": "中国工商银行",
  "createdTime": "2026-03-15T10:00:00",
  "settledTime": "2026-03-15T10:05:00",
  "remark": "银行卡代付",
  "timestamp": "1773542406",
  "nonce": "3c8bb214123e4ed9",
  "apiVersion": "v1.0",
  "sign": "4CB9B989CB1C77A3F4BD9A4C9425A159"
}
```

签名前待加密串示例：

```text
actualamount=49500&apiversion=v1.0&appid=appid_demo_001&applyamount=50000&createdtime=2026-03-15T10%3A00%3A00&currency=CNY&feeamount=500&merchantorderno=WD202603150001&method=bank_card_payout&nonce=3c8bb214123e4ed9&payeeaccount=6222021234567890123&payeebankname=%E4%B8%AD%E5%9B%BD%E5%B7%A5%E5%95%86%E9%93%B6%E8%A1%8C&payeename=%E5%BC%A0%E4%B8%89&payeetype=BANK&platformorderno=PLT_OUT_20260315000001&providerkey=mock_sandbox&providername=Mock%20Sandbox&remark=%E9%93%B6%E8%A1%8C%E5%8D%A1%E4%BB%A3%E4%BB%98&rspcode=PAY_000&rspmsg=%E6%88%90%E5%8A%9F&settledtime=2026-03-15T10%3A05%3A00&status=SUCCESS&statustext=%E4%BB%A3%E4%BB%98%E6%88%90%E5%8A%9F&timestamp=1773542406&key=YOUR_SIGN_KEY
```

成功响应示例：

```json
{
  "code": 10000,
  "message": "ok"
}
```

---

## 五、验签建议
- 请求前先生成签名并填入 `sign`（建议放 JSON Body）。
- 收到响应后，若存在有效 `sign`，按相同规则复算并比对；无 `sign` 或无法验签时，以 `rspCode`/`rspMsg` 为准，勿将「无法验签」一律当作攻击。
- 验签失败时不要更新业务状态，需按失败处理并记录必要上下文（勿记录密钥或完整敏感报文）。

---

**文档结束**

CloudPay 智利2原生独立渠道 `cloudpay_cl2`（待部署）的字段、标准账户类型和证件要求见 [接入说明](./开放接口附录-CloudPay智利2原生接入说明.md)。仅支持 CL/CLP，代收标准 `payTypeCode=bank` 对应上游 `56101`；商户可用性以能力查询为准。


## shijiepay 聚合付 VN/VND、PH/PHP 接入资料（待部署）

代收使用 `bank` / `qr` / `momo` / `viettel_pay` / `zalo_pay` 标准payTypeCode，由已配置路由选中8个独立上游产品；实际返回托管支付URL。见 [代收说明](开放接口附录-shijiepay代收pay_type_code接入说明.md)。

银行代付使用 `payeeType=BANK`、真实收款姓名/账号及越南平台标准payeeBankCode；见 [代付说明](开放接口附录-shijiepay代付账户类型与银行编码说明.md) 和 [越南银行标准码](vietnam-bank-codes.html)。金额为正整数分。提交mchOrderId是我方单号，代收systemOrderNo/systemOrderId是上游流水；官方代付未提供独立流水，保持为空。渠道尚待部署，当前可用性以商户能力查询为准。

菲律宾扩展：PH/PHP 代收 qr、gcash、maya、grabpay、gotyme，10个独立上游产品；代付BANK、GCASH、MAYA、GRABPAY、GOTYME对应APY001/APY002，银行传菲律宾平台标准码，钱包省略银行码。BD/PK/ID/IN本次暂不实现。
