This commit is contained in:
2026-03-13 15:51:59 +08:00
parent 4db2386bbf
commit 4e91f4cede
133 changed files with 19502 additions and 37 deletions

View File

@@ -0,0 +1,931 @@
# Pay-Bridge 支付网关接入文档
| 版本 | 日期 | 说明 |
|------|------|------|
| v1.2 | 2026-02-28 | 新增商户进件接口SaaS 多商户场景)、统一下单支持 merchant_id |
| v1.1 | 2026-02-28 | 更新接入凭证申请方式 |
| v1.0 | 2026-02-28 | 初始版本 |
---
## 目录
1. [接入准备](#1-接入准备)
2. [请求规范](#2-请求规范)
3. [签名算法](#3-签名算法)
4. [统一响应格式](#4-统一响应格式)
5. [支付接口](#5-支付接口)
- 5.1 [统一下单](#51-统一下单)
- 5.2 [查询订单](#52-查询订单)
- 5.3 [关闭订单](#53-关闭订单)
- 5.4 [申请退款](#54-申请退款)
- 5.5 [查询退款](#55-查询退款)
6. [商户进件接口](#6-商户进件接口)SaaS 多商户场景)
- 6.1 [创建商户](#61-创建商户)
- 6.2 [上传证件文件](#62-上传证件文件)
- 6.3 [提交进件申请](#63-提交进件申请)
- 6.4 [查询审核状态](#64-查询审核状态)
- 6.5 [查询商户详情](#65-查询商户详情)
- 6.6 [查询商户列表](#66-查询商户列表)
7. [异步通知](#7-异步通知)
8. [订单状态说明](#8-订单状态说明)
9. [错误码对照表](#9-错误码对照表)
10. [最佳实践](#10-最佳实践)
11. [签名示例代码](#11-签名示例代码)
---
## 1. 接入准备
### 1.1 获取接入凭证
接入凭证由**平台管理员**在管理后台创建。请联系平台管理员,按以下步骤为你的系统开通接入权限:
1. 管理员登录管理后台,进入「**接入应用**」模块
2. 点击「新建应用」填写应用名称商城系统、ERP 系统)
3. 系统自动生成 `app_id``app_secret`**Secret 仅在创建时展示一次**
4. 管理员将凭证告知接入方
> **重要提示**`app_secret` 创建后无法再次查看,如遗失需由管理员在后台执行「重置密钥」操作,旧密钥立即失效。
获得的凭证如下:
| 参数 | 示例 | 说明 |
|------|------|------|
| `app_id` | `app_2602280a3f1b7c2d` | 应用唯一标识,格式为 `app_` + 日期 + 随机串 |
| `app_secret` | `A3F8C2D1E4B7F9A0...` | 64 位十六进制字符串,用于请求签名,**请妥善保管,切勿泄露或提交至代码仓库** |
### 1.2 接口基础地址
| 环境 | 地址 |
|------|------|
| 生产环境 | `https://pay.your-domain.com` |
| 沙箱环境 | `https://sandbox-pay.your-domain.com` |
---
## 2. 请求规范
### 2.1 基本要求
- 协议HTTPS
- 方法POST下单/退款/关闭、GET查询
- 编码UTF-8
- Content-Type`application/json`
### 2.2 公共请求头
所有请求必须携带以下 Header
| Header | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `X-App-Id` | string | 是 | 平台分配的 app_id |
| `X-Timestamp` | string | 是 | 当前 Unix 时间戳(秒),与服务器时间差须在 **5 分钟**以内 |
| `X-Sign` | string | 是 | 请求签名,见[签名算法](#3-签名算法) |
| `Content-Type` | string | 是 | `application/json` |
**示例:**
```http
POST /api/v1/pay/unified-order HTTP/1.1
Host: pay.your-domain.com
Content-Type: application/json
X-App-Id: app_20260101001
X-Timestamp: 1740700800
X-Sign: a3f8c2d1e4b7f9a0c5d2e8f1b4a7c3d6e9f2b5a8c1d4e7f0a3b6c9d2e5f8a1b4
```
---
## 3. 签名算法
### 3.1 算法说明
签名算法为 **HMAC-SHA256**,签名结果为 **十六进制小写字符串**
### 3.2 签名步骤
**第一步**:拼接签名原文
```
签名原文 = app_id + timestamp + requestBody
```
- `app_id`Header 中的 X-App-Id
- `timestamp`Header 中的 X-Timestamp
- `requestBody`:请求体原始 JSON 字符串GET 请求时为空字符串 `""`
**第二步**HMAC-SHA256 签名
```
sign = HMAC-SHA256(签名原文, app_secret)
```
**第三步**Hex 编码,填入 `X-Sign` Header
### 3.3 注意事项
- 请求体 JSON 中字段顺序不影响签名,但序列化后的**字节内容必须与实际发送的 body 完全一致**
- 时间戳精度为秒,不是毫秒
- GET 请求 body 为空字符串参与签名
---
## 4. 统一响应格式
所有接口均返回 JSONHTTP 状态码为 200业务错误也返回 200通过 `code` 字段区分)。
**成功响应:**
```json
{
"code": "0",
"message": "success",
"data": { ... },
"trace_id": "7f3a2b1c4d5e6f7a"
}
```
**失败响应:**
```json
{
"code": "30004",
"message": "退款金额超过可退金额",
"trace_id": "7f3a2b1c4d5e6f7a"
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `code` | string | `"0"` 为成功,其他为错误码,见[错误码表](#9-错误码对照表) |
| `message` | string | 提示信息 |
| `data` | object | 业务数据,仅成功时返回 |
| `trace_id` | string | 请求追踪 ID排查问题时提供给平台 |
---
## 5. 支付接口
### 5.1 统一下单
**接口地址**
```
POST /api/v1/pay/unified-order
```
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `merchant_order_no` | string | 是 | 商户系统订单号,同一 app_id 下唯一,最长 64 位 |
| `pay_method` | string | 是 | 支付方式,见下方枚举 |
| `amount` | int64 | 是 | 订单金额,单位**分**,最小 1 |
| `subject` | string | 是 | 商品描述,最长 256 位 |
| `notify_url` | string | 是 | 支付结果异步通知地址,须为合法 HTTPS URL |
| `expire_minutes` | int | 否 | 订单有效期(分钟),默认 30 分钟 |
| `profit_sharing_amount` | int64 | 否 | 分润金额0 表示不分润 |
| `extra` | object | 否 | 支付方式附加参数,见下方说明 |
| `merchant_id` | string | 否 | 指定收款商户 IDSaaS 多商户场景),须为本 app_id 下已进件审核通过的商户 |
**`pay_method` 枚举值**
| 值 | 说明 |
|----|------|
| `WECHAT_JSAPI` | 微信公众号支付 |
| `WECHAT_H5` | 微信 H5 支付 |
| `WECHAT_NATIVE` | 微信扫码支付 |
| `WECHAT_MINI` | 微信小程序支付 |
| `ALIPAY` | 支付宝扫码支付 |
| `QUICK_PAY` | 快捷支付 |
**`extra` 附加参数说明**
| 支付方式 | 参数 | 说明 |
|---------|------|------|
| `WECHAT_JSAPI` | `openid`(必填) | 用户在公众号的 openid |
| `WECHAT_MINI` | `openid`(必填) | 用户在小程序的 openid |
| `WECHAT_JSAPI` / `WECHAT_MINI` | `sub_appid`(可选) | 子商户公众号/小程序 AppID |
**请求示例**
```json
{
"merchant_order_no": "ORD20260228001",
"pay_method": "WECHAT_JSAPI",
"amount": 9900,
"subject": "会员充值 - 月卡",
"notify_url": "https://your-server.com/callback/pay",
"expire_minutes": 15,
"extra": {
"openid": "oxxxxxxxxxxxxxxxxxxxxxxx"
}
}
```
**成功响应 `data`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `trade_no` | string | 平台交易号,格式 `PAYyyMMddXXXXXXXX` |
| `pay_credential` | object | 支付凭证,透传给前端拉起支付,格式因支付方式不同而异 |
| `is_idempotent` | bool | `true` 表示该订单号已存在,返回的是已有订单信息 |
**响应示例**
```json
{
"code": "0",
"message": "success",
"data": {
"trade_no": "PAY26022800000001",
"pay_credential": {
"appId": "wx1234567890",
"timeStamp": "1740700800",
"nonceStr": "abc123xyz",
"package": "prepay_id=wx28...",
"signType": "RSA",
"paySign": "..."
},
"is_idempotent": false
}
}
```
> **幂等说明**:使用相同的 `merchant_order_no` 重复调用,不会重复下单,会直接返回已有订单的支付凭证,并且 `is_idempotent` 为 `true`。
---
### 5.2 查询订单
**接口地址**
```
GET /api/v1/pay/query/{trade_no}
```
**路径参数**
| 参数 | 类型 | 说明 |
|------|------|------|
| `trade_no` | string | 平台交易号(下单时返回的 `trade_no` |
**请求示例**
```http
GET /api/v1/pay/query/PAY26022800000001
```
**成功响应 `data`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `trade_no` | string | 平台交易号 |
| `merchant_order_no` | string | 商户订单号 |
| `pay_method` | string | 支付方式 |
| `amount` | int64 | 订单金额(分) |
| `status` | string | 订单状态,见[订单状态说明](#8-订单状态说明) |
| `channel_trade_no` | string | 渠道侧交易号 |
| `pay_time` | string | 支付成功时间ISO8601 格式,未支付时为 null |
| `created_at` | string | 订单创建时间ISO8601 格式 |
**响应示例**
```json
{
"code": "0",
"message": "success",
"data": {
"trade_no": "PAY26022800000001",
"merchant_order_no": "ORD20260228001",
"pay_method": "WECHAT_JSAPI",
"amount": 9900,
"status": "PAID",
"channel_trade_no": "4200002345202602280000000001",
"pay_time": "2026-02-28T10:05:00Z",
"created_at": "2026-02-28T10:00:00Z"
}
}
```
---
### 5.3 关闭订单
关闭仍在支付中的订单,已支付订单不可关闭(请使用退款接口)。
**接口地址**
```
POST /api/v1/pay/close
```
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `trade_no` | string | 是 | 平台交易号 |
**请求示例**
```json
{
"trade_no": "PAY26022800000001"
}
```
**成功响应**
```json
{
"code": "0",
"message": "success"
}
```
---
### 5.4 申请退款
**接口地址**
```
POST /api/v1/pay/refund
```
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `trade_no` | string | 是 | 平台交易号 |
| `refund_amount` | int64 | 是 | 退款金额(分),不得超过原订单金额 |
| `reason` | string | 否 | 退款原因,最长 256 位 |
| `notify_url` | string | 否 | 退款结果异步通知地址 |
**请求示例**
```json
{
"trade_no": "PAY26022800000001",
"refund_amount": 9900,
"reason": "用户申请退款",
"notify_url": "https://your-server.com/callback/refund"
}
```
**成功响应 `data`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `refund_no` | string | 平台退款单号 |
| `trade_no` | string | 关联的平台交易号 |
| `refund_amount` | int64 | 退款金额(分) |
| `status` | string | 退款状态:`PENDING` / `PROCESSING` / `SUCCESS` / `FAILED` |
| `channel_refund_no` | string | 渠道侧退款单号 |
**响应示例**
```json
{
"code": "0",
"message": "success",
"data": {
"refund_no": "REF26022800000001",
"trade_no": "PAY26022800000001",
"refund_amount": 9900,
"status": "PROCESSING",
"channel_refund_no": "50300807092026022800000000001"
}
}
```
> **注意**:退款为异步处理,状态 `PROCESSING` 表示已提交渠道,最终结果通过异步通知推送,建议同时通过查询接口轮询确认。
---
### 5.5 查询退款
**接口地址**
```
GET /api/v1/pay/refund/query/{refund_no}
```
**路径参数**
| 参数 | 类型 | 说明 |
|------|------|------|
| `refund_no` | string | 平台退款单号(申请退款时返回的 `refund_no` |
**成功响应 `data`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `refund_no` | string | 平台退款单号 |
| `trade_no` | string | 关联的平台交易号 |
| `refund_amount` | int64 | 退款金额(分) |
| `status` | string | 退款状态 |
| `channel_refund_no` | string | 渠道侧退款单号 |
| `refund_time` | string | 退款成功时间ISO8601 格式,未完成时为 null |
---
## 6. 商户进件接口
> 适用场景:你的系统是 **SaaS 平台**,平台上的客户需要先完成进件(企业入网)才能以自己名义收款。
>
> 所有进件接口与支付接口使用**相同的 HMAC 鉴权**`app_id` + `app_secret`),且数据完全按 `app_id` 隔离——你只能看到自己名下的商户。
### 典型流程
```
1. 创建商户记录(获取 merchant_id
2. 上传营业执照等证件文件(获取 file_id
3. 提交进件申请(将 file_id 填入 submit_data
4. 轮询查询审核状态,直至 APPROVED
5. 统一下单时传入 merchant_id指定该商户收款
```
---
### 6.1 创建商户
**接口地址**
```
POST /api/v1/merchant
```
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `merchant_id` | string | 是 | 你方系统的商户唯一标识,最长 32 位,由调用方自定义 |
| `merchant_name` | string | 是 | 商户名称 |
| `license_no` | string | 否 | 营业执照号 |
| `legal_person` | string | 否 | 法定代表人姓名 |
| `bank_account` | string | 否 | 结算银行账号(脱敏存储) |
**请求示例**
```json
{
"merchant_id": "tenant_0001",
"merchant_name": "示例科技有限公司",
"license_no": "91310000XXXXXXXXXX",
"legal_person": "张三",
"bank_account": "6222021234567890123"
}
```
**成功响应 `data`**
```json
{
"merchant_id": "tenant_0001"
}
```
---
### 6.2 上传证件文件
**接口地址**
```
POST /api/v1/merchant/upload-file
```
**请求格式**`multipart/form-data`
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `file` | file | 是 | 证件图片,支持 JPG / PNG / PDF |
| `file_media_type` | string | 是 | 文件类型代码,由渠道定义,如 `01`=营业执照、`02`=身份证正面 |
| `channel_code` | string | 否 | 渠道代码,默认 `HEEPAY` |
**成功响应 `data`**
```json
{
"file_id": "3000000001234567"
}
```
> 上传返回的 `file_id` 在提交进件时填入 `submit_data`,有效期以渠道规定为准(通常 48 小时内使用)。
---
### 6.3 提交进件申请
**接口地址**
```
POST /api/v1/merchant/{merchant_id}/apply
```
**路径参数**
| 参数 | 说明 |
|------|------|
| `merchant_id` | 创建商户时使用的商户 ID |
**请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `channel_code` | string | 是 | 渠道代码,如 `HEEPAY` |
| `submit_data` | object | 否 | 渠道要求的进件业务参数,内容因渠道而异,详见各渠道对接手册 |
**请求示例**
```json
{
"channel_code": "HEEPAY",
"submit_data": {
"business_license_no": "91310000XXXXXXXXXX",
"business_license_copy": "3000000001234567",
"id_card_front": "3000000001234568",
"id_card_back": "3000000001234569",
"contact_name": "张三",
"contact_phone": "138XXXXXXXX",
"bank_account_no": "6222021234567890123",
"bank_name": "中国工商银行"
}
}
```
**成功响应 `data`**
```json
{
"application_id": "APP1a2b3c4d5e6f7a8b"
}
```
---
### 6.4 查询审核状态
**接口地址**
```
GET /api/v1/merchant/{merchant_id}/audit
```
**成功响应 `data`**
| 字段 | 类型 | 说明 |
|------|------|------|
| `application_id` | string | 进件申请 ID |
| `merchant_id` | string | 商户 ID |
| `channel_code` | string | 渠道代码 |
| `audit_status` | string | 审核状态,见下方枚举 |
| `reject_reason` | string | 拒绝原因,仅 `REJECTED` 时返回 |
| `submitted_at` | string | 提交时间 |
| `audited_at` | string | 审核完成时间,未完成时为 null |
**`audit_status` 枚举值**
| 值 | 说明 |
|----|------|
| `SUBMITTING` | 提交中,正在调用渠道 |
| `REVIEWING` | 审核中,渠道人工审核 |
| `APPROVED` | 审核通过,商户可正常收款 |
| `REJECTED` | 审核拒绝,查看 `reject_reason` 修改后重新提交 |
**响应示例**
```json
{
"code": "0",
"message": "success",
"data": {
"application_id": "APP1a2b3c4d5e6f7a8b",
"merchant_id": "tenant_0001",
"channel_code": "HEEPAY",
"audit_status": "APPROVED",
"submitted_at": "2026-02-28T10:00:00Z",
"audited_at": "2026-02-28T14:30:00Z"
}
}
```
---
### 6.5 查询商户详情
**接口地址**
```
GET /api/v1/merchant/{merchant_id}
```
**成功响应 `data`**:返回完整商户对象,字段同创建时入参,额外包含:
| 字段 | 类型 | 说明 |
|------|------|------|
| `status` | string | 商户状态:`PENDING` / `ACTIVE` / `FROZEN` / `REJECTED` |
| `channel_merchant_id` | string | 渠道侧商户 ID进件审核通过后由渠道下发 |
| `created_at` | string | 创建时间 |
> 如传入的 `merchant_id` 不属于当前 `app_id`,接口返回 404。
---
### 6.6 查询商户列表
**接口地址**
```
GET /api/v1/merchant
```
**Query 参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `status` | string | 否 | 按状态过滤:`PENDING` / `ACTIVE` / `FROZEN` / `REJECTED` |
| `limit` | int | 否 | 每页数量,默认 20 |
| `offset` | int | 否 | 偏移量,默认 0 |
**响应示例**
```json
{
"code": "0",
"message": "success",
"data": {
"list": [
{
"merchant_id": "tenant_0001",
"merchant_name": "示例科技有限公司",
"status": "ACTIVE",
"created_at": "2026-02-28T10:00:00Z"
}
],
"limit": 20,
"offset": 0
}
}
```
---
### 6.7 指定商户收款(统一下单扩展)
商户进件通过后,在[统一下单](#51-统一下单)时传入 `merchant_id`,平台会将该商户的渠道收款账号注入下单参数,实现**分账到具体商户**
```json
{
"merchant_order_no": "ORD20260228002",
"pay_method": "WECHAT_JSAPI",
"amount": 9900,
"subject": "订单支付",
"notify_url": "https://your-server.com/callback/pay",
"merchant_id": "tenant_0001",
"extra": {
"openid": "oxxxxxxxxxxxxxxxxxxxxxxx"
}
}
```
> `merchant_id` 必须属于当前 `app_id`,且商户状态为 `ACTIVE`,否则返回 `30001`。
---
## 7. 异步通知
### 7.1 支付成功通知
用户支付成功后,平台将向下单时提供的 `notify_url` 发送 POST 请求。
**通知内容**
```json
{
"trade_no": "PAY26022800000001",
"merchant_order_no": "ORD20260228001",
"status": "PAID",
"amount": 9900,
"pay_method": "WECHAT_JSAPI",
"channel_trade_no": "4200002345202602280000000001",
"pay_time": "2026-02-28T10:05:00Z"
}
```
### 7.2 退款结果通知
退款处理完成后,平台将向退款时提供的 `notify_url` 发送 POST 请求。
**通知内容**
```json
{
"refund_no": "REF26022800000001",
"trade_no": "PAY26022800000001",
"merchant_order_no": "ORD20260228001",
"refund_amount": 9900,
"status": "SUCCESS",
"refund_time": "2026-02-28T10:30:00Z"
}
```
### 7.3 通知应答规则
**接收通知后,你的服务器必须在 10 秒内响应以下内容:**
```
HTTP 200
Body: success
```
返回任何其他内容,或超时未响应,平台将认为通知失败并重试。
### 7.4 重试策略
| 第 N 次 | 延迟 |
|--------|------|
| 1 | 立即 |
| 2 | 15 秒后 |
| 3 | 30 秒后 |
| 4 | 1 分钟后 |
| 5 | 5 分钟后 |
| 6 | 30 分钟后 |
| 7 | 1 小时后 |
| 8 | 6 小时后 |
| 9 | 12 小时后 |
超过 9 次仍失败将停止重试,请通过**查询接口**主动同步最终状态。
### 7.5 防重处理
通知可能因网络原因重复发送,请以 `trade_no` 为唯一键做幂等处理,避免重复发货或重复入账。
---
## 8. 订单状态说明
### 8.1 交易订单状态
| 状态 | 说明 |
|------|------|
| `CREATING` | 创建中,正在调用渠道下单 |
| `PAYING` | 待支付,等待用户付款 |
| `PAID` | 支付成功 |
| `CLOSED` | 已关闭 |
| `FAILED` | 支付失败 |
| `CREATE_FAILED` | 下单失败,渠道返回错误 |
| `REFUNDED` | 已全额退款 |
### 8.2 退款状态
| 状态 | 说明 |
|------|------|
| `PENDING` | 待处理 |
| `PROCESSING` | 处理中,已提交渠道 |
| `SUCCESS` | 退款成功 |
| `FAILED` | 退款失败,可联系平台处理 |
---
## 9. 错误码对照表
| 错误码 | HTTP 状态码 | 说明 | 处理建议 |
|--------|------------|------|---------|
| `0` | 200 | 成功 | — |
| `10001` | 400 | 参数校验失败 | 检查请求参数格式和必填项 |
| `10002` | 400 | 缺少必填参数 | 补充缺少的参数 |
| `10003` | 400 | 不支持的支付方式 | 检查 pay_method 是否正确 |
| `10004` | 400 | 金额非法 | 金额须为正整数(分) |
| `20001` | 401 | 签名验证失败 | 检查签名算法和 app_secret |
| `20002` | 401 | 应用不存在或已禁用 | 联系平台确认 app_id 状态 |
| `30001` | 422 | 订单不存在 | 检查 trade_no 是否正确 |
| `30002` | 422 | 订单已支付 | 勿重复支付 |
| `30003` | 422 | 订单已关闭 | 需重新下单 |
| `30004` | 422 | 退款金额超过可退金额 | 检查退款金额 |
| `30009` | 422 | 订单未支付,无法退款 | 确认订单已支付后再退款 |
| `30010` | 422 | 退款单不存在 | 检查 refund_no 是否正确 |
| `40001` | 502 | 渠道下单失败 | 稍后重试,仍失败请联系平台 |
| `40002` | 502 | 渠道退款失败 | 稍后重试,仍失败请联系平台 |
| `40003` | 502 | 渠道调用超时 | 稍后重试 |
| `50099` | 500 | 系统内部错误 | 记录 trace_id 联系平台排查 |
---
## 10. 最佳实践
### 10.1 下单流程建议
```
1. 用户确认支付
2. 你的服务端调用【统一下单】接口
3. 返回 pay_credential 给前端
4. 前端调用微信/支付宝 SDK 拉起支付
5. 接收异步通知 → 更新订单状态 → 返回 "success"
6. (兜底)若通知未收到,定时调用【查询订单】接口轮询
```
### 10.2 安全注意事项
- `app_secret` 只在服务端使用,**禁止出现在前端代码或 App 客户端中**
- 异步通知的 IP 建议加入白名单(联系平台获取出口 IP 段)
- 通知接收后务必**先返回 `success`,再处理业务逻辑**,避免超时导致重复通知
### 10.3 金额单位
所有金额字段均以**分**为单位,整数类型:
- 1 元 = `100`
- 9.9 元 = `990`
- 99.99 元 = `9999`
### 10.4 时区
所有时间字段均为 **UTC 时间**ISO8601 格式,例如 `2026-02-28T10:05:00Z`
---
## 11. 签名示例代码
### Go
```go
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"strconv"
"time"
)
func sign(appID, appSecret, body string) (timestamp, sign string) {
ts := strconv.FormatInt(time.Now().Unix(), 10)
raw := appID + ts + body
mac := hmac.New(sha256.New, []byte(appSecret))
mac.Write([]byte(raw))
return ts, hex.EncodeToString(mac.Sum(nil))
}
```
### Python
```python
import hmac
import hashlib
import time
def sign(app_id: str, app_secret: str, body: str) -> tuple[str, str]:
timestamp = str(int(time.time()))
raw = app_id + timestamp + body
signature = hmac.new(
app_secret.encode("utf-8"),
raw.encode("utf-8"),
hashlib.sha256
).hexdigest()
return timestamp, signature
```
### Java
```java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
public static String[] sign(String appId, String appSecret, String body) throws Exception {
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String raw = appId + timestamp + body;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] bytes = mac.doFinal(raw.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : bytes) sb.append(String.format("%02x", b));
return new String[]{timestamp, sb.toString()};
}
```
### PHP
```php
function sign(string $appId, string $appSecret, string $body): array {
$timestamp = (string)time();
$raw = $appId . $timestamp . $body;
$signature = hash_hmac('sha256', $raw, $appSecret);
return [$timestamp, $signature];
}
```
---
如有问题请联系平台技术支持,并提供接口返回的 `trace_id`

344
docs/approach-design.md Normal file
View File

@@ -0,0 +1,344 @@
# pay-bridge Approach Design
| 字段 | 内容 |
|-----|------|
| 文档版本 | v1.0 |
| 创建日期 | 2026-02-27 |
| 状态 | 草稿 |
---
## 1. 整体架构分层
pay-bridge 采用四层架构自上而下分别为API 接入层、业务逻辑层、渠道适配层、基础设施层。
```
┌──────────────────────────────────────────────────────────────┐
│ 下游业务系统 │
│ (电商 / SaaS / 多商户平台) │
└────────────────────────┬─────────────────────────────────────┘
│ REST/JSON over HTTPS
┌────────────────────────▼─────────────────────────────────────┐
│ Layer 1: API 接入层 │
│ • 鉴权中间件appId + appSecret 签名验证) │
│ • 请求路由Gin Router
│ • 参数校验binding/validator
│ • 限流中间件Redis Token Bucket
│ • 统一响应格式封装 / 错误码映射 │
├──────────────────────────────────────────────────────────────┤
│ Layer 2: 业务逻辑层 │
│ • 交易服务(统一下单、查询、退款、关单) │
│ • 通知服务(接收上游回调、通知下游、重试调度) │
│ • 分润服务(分账计算、分润触发、退款回退) │
│ • 服务费服务(费率计算、自动扣收) │
│ • 收款匹配服务(入账通知接收、三维度匹配引擎) │
│ • 对账服务(账单拉取、逐笔比对、差异报告) │
│ • 商户进件服务(进件提交、审核状态跟踪) │
│ • 微信通知服务(模板消息推送、绑定管理) │
│ • 订单编码服务(按 app_id 隔离的序列号生成) │
├──────────────────────────────────────────────────────────────┤
│ Layer 3: 渠道适配层 │
│ • 渠道适配器接口(统一 interface 定义) │
│ • 汇元支付适配器RSA/MD5 签名、RSA+3DES 加解密) │
│ • 渠道工厂(根据 channel_code 动态路由到对应适配器) │
│ • 渠道配置仓储(密钥、证书的加密读取) │
├──────────────────────────────────────────────────────────────┤
│ Layer 4: 基础设施层 │
│ • MySQL 8.0(交易持久化、配置存储) │
│ • Redis幂等 Key 缓存、分布式锁、延迟队列) │
│ • 定时任务调度器cron 对账、状态补偿) │
│ • 结构化日志zerolog / zap
└──────────────────────────────────────────────────────────────┘
│ 渠道私有协议
┌────────────────────────▼─────────────────────────────────────┐
│ 上游支付渠道 │
│ 汇元支付 │ (预留微信直连) │ (预留支付宝直连) │
└──────────────────────────────────────────────────────────────┘
```
**分层理由**
- API 接入层与业务逻辑层分离,使鉴权、限流、协议转换等横切关注点集中处理,业务层保持纯粹。
- 渠道适配层独立为一层,而非嵌入业务层,使新增渠道无需改动任何业务代码,只新增一个适配器实现。
- 基础设施层统一封装,方便后续将 Redis 替换为其他实现,或扩展消息队列。
---
## 2. 核心模块划分
| 模块 | 职责 | 关键依赖 |
|-----|-----|--------|
| 交易核心Trade | 统一下单、查询、关单,维护订单状态机 | MySQL、Redis幂等、渠道适配层 |
| 退款Refund | 退款请求、退款状态跟踪、退款查询 | MySQL、渠道适配层 |
| 异步通知Notify | 接收上游回调验签、更新状态、通知下游、重试调度 | Redis 延迟队列、MySQL |
| 分润ProfitSharing | 分润配置读取、分账调用、退款回退分润 | 渠道适配层、MySQL |
| 服务费ServiceFee | 费率配置读取、服务费计算、分账划转 | 渠道适配层、MySQL |
| 收款匹配PaymentMatch | 接收固定账户入账通知、三维度匹配引擎 | MySQL、通知模块 |
| 对账Reconciliation | T+1 账单拉取、逐笔比对、差异入库 | 渠道适配层、MySQL |
| 商户进件Merchant | 进件提交、审核跟踪、状态异常检测 | 渠道适配层、MySQL |
| 微信通知WechatNotify | 微信绑定管理、模板消息推送 | 微信公众号 API、MySQL |
| 订单编码Sequence | 按 app_id 隔离的订单号生成 | MySQL悲观锁序列或 Redis原子自增 |
| 渠道适配Channel | 统一 interface、汇元适配器实现、渠道工厂 | 无外部依赖(纯逻辑) |
| 应用鉴权Auth | appId + appSecret 签名校验、应用信息缓存 | MySQL、Redis |
---
## 3. 中间件选型及理由
### 3.1 MySQL 8.0
**理由**:交易数据要求强一致性和 ACID 事务金融场景不接受数据丢失。MySQL 在团队熟悉度、生态(如 gorm、成本自建方面综合最优。单表千万级订单通过分区表或归档策略应对不需要引入分布式数据库的复杂性。
选 MySQL 而非 PostgreSQLPRD 明确列出 MySQL 8.0团队已有运维经验MySQL 在国内支付系统中更为普遍,社区案例更多。
### 3.2 Redis
Redis 在本系统中承担三个独立职责,每个职责对应不同的数据结构:
| 职责 | 数据结构 | 说明 |
|-----|---------|-----|
| 幂等 Key 缓存 | StringSET NX EX | 下单去重、回调幂等TTL 与订单超时一致 |
| 分布式锁 | StringRedlock 语义) | 防止并发退款、分润重复触发 |
| 异步通知延迟队列 | Sorted Setscore 为下次重试时间戳) | 实现指数退避重试,无需引入重量级 MQ |
**为什么不引入 RabbitMQ 或 Kafka**MVP 阶段通知 QPS 较低(< 500Redis Sorted Set 延迟队列已足够;引入独立 MQ 会增加运维复杂度和故障点。PRD 也明确将 Redis Stream 或 RabbitMQ 列为备选Redis Sorted Set 是更轻量的起点,后续可迁移。
### 3.3 Gin 框架
**理由**Go 生态最成熟的 HTTP 框架,性能优异(零 gc 路由),中间件生态完善,团队学习成本低。符合 PRD 的 P95 < 200ms 要求。
### 3.4 GORM v2
**理由**:提供类型安全的 ORM减少 SQL 拼接错误支持软删除、Hook 钩子方便审计日志Migration 能力支持版本化数据库变更。对于金融场景中需要精确控制的批量 SQL支持原生 SQL 直接执行。
---
## 4. 模块间交互方式
pay-bridge 采用**同进程函数调用**而非微服务拆分,理由是 MVP 阶段团队规模和交易量均不需要微服务的复杂性,单体部署运维更简单,且 Go 的并发模型goroutine天然支持高并发。
模块间交互规则:
1. **同步调用链**请求主路径API Handler → Service → Repository → DB。Service 层不互相直接调用,通过 interface 注入解耦。
2. **事件驱动**(异步后处理):支付成功后,通知服务、分润服务、服务费服务通过 Go channel 或直接异步 goroutine 触发,不阻塞主请求链路。
3. **重试队列**(延迟执行):通知重试写入 Redis Sorted Set独立的 goroutine 定时扫描到期任务并执行。
4. **定时任务**:对账、商户状态检测等 cron 任务由独立 goroutine 调度,与 HTTP 服务共进程但相互隔离。
```
HTTP Request
API Handler
│ 同步
Trade Service ──── Repository ──── MySQL
│ 异步goroutine
├──► Notify Service ──► Redis Sorted Set延迟重试
├──► ProfitSharing Service ──► Channel Adapter ──► 汇元分账 API
└──► ServiceFee Service ──► Channel Adapter ──► 汇元分账 API
```
---
## 5. 渠道适配器框架设计思路
渠道适配器是整个系统可扩展性的核心。设计原则:**对外暴露统一接口,对内封装渠道差异**。
### 5.1 统一接口抽象
定义 `PaymentChannel` interface所有渠道适配器必须实现此接口
```go
type PaymentChannel interface {
// Code 返回渠道编码
Code() string
// CreateOrder 下单,返回支付凭证
CreateOrder(ctx context.Context, req *CreateOrderRequest) (*CreateOrderResponse, error)
// QueryOrder 查询订单状态
QueryOrder(ctx context.Context, req *QueryOrderRequest) (*QueryOrderResponse, error)
// CloseOrder 关闭订单
CloseOrder(ctx context.Context, req *CloseOrderRequest) (*CloseOrderResponse, error)
// Refund 发起退款
Refund(ctx context.Context, req *RefundRequest) (*RefundResponse, error)
// QueryRefund 查询退款状态
QueryRefund(ctx context.Context, req *QueryRefundRequest) (*QueryRefundResponse, error)
// VerifyNotify 验证上游回调签名,返回解析后的通知数据
VerifyNotify(ctx context.Context, rawBody []byte, headers map[string]string) (*NotifyData, error)
// ProfitSharing 分账(渠道不支持时返回 ErrNotSupported
ProfitSharing(ctx context.Context, req *ProfitSharingRequest) (*ProfitSharingResponse, error)
// RollbackProfitSharing 回退分账
RollbackProfitSharing(ctx context.Context, req *RollbackSharingRequest) (*RollbackSharingResponse, error)
// DownloadBill 下载对账账单
DownloadBill(ctx context.Context, req *DownloadBillRequest) (*BillData, error)
// MerchantApply 商户进件
MerchantApply(ctx context.Context, req *MerchantApplyRequest) (*MerchantApplyResponse, error)
// QueryMerchantStatus 查询商户审核状态
QueryMerchantStatus(ctx context.Context, channelMerchantID string) (*MerchantStatusResponse, error)
}
```
### 5.2 渠道工厂与注册Registry 模式)
采用注册表Registry模式避免 switch-case 的硬编码,实现插件化设计:
```go
var registry = map[string]ChannelFactory{}
func Register(channelCode string, factory ChannelFactory) {
registry[channelCode] = factory
}
func GetChannel(channelCode string, config *ChannelConfig) (PaymentChannel, error) {
factory, ok := registry[channelCode]
if !ok {
return nil, ErrChannelNotFound
}
return factory(config), nil
}
```
每个渠道适配器包在 `init()` 中调用 `Register()` 完成自注册。新增渠道只需:新建包、实现 interface、调用 Register主程序 `import _ "pay-bridge/internal/channel/newchannel"` 即可接入,无需修改任何现有代码。
### 5.3 汇元适配器特殊处理
汇元支付HePay采用 RSA/MD5 双签名和 RSA+3DES 双层加密,适配器内部封装:
- **签名层**:根据渠道配置决定使用 RSA 还是 MD5对外透明。
- **加密层**:请求体使用 3DES 加密,密钥使用 RSA 公钥加密后随请求发送;响应体同样解密处理。
- **重试安全**:所有加解密操作幂等,同一请求多次加密结果不同但均有效。
---
## 6. 异步通知 + 重试机制方案
### 6.1 整体流程
```
上游回调 → 验签 → 更新交易状态DB 事务)→ 写入通知任务 → 立即第一次推送
推送成功 → 标记完成
推送失败 → 写入 Redis Sorted Set
score = now + 重试间隔
Poller goroutine 定时扫描
到期任务 → 执行推送
成功 → 删除任务
失败 → 更新 score下次重试时间
超过 8 次 → 标记「通知异常」
```
### 6.2 重试间隔设计
共 9 次推送机会(第 1 次立即,后续 8 次重试),重试间隔:
| 第 N 次推送 | 距上次等待时长 | 累计等待时间 |
|-----------|------------|-----------|
| 1 | 立即 | 0 |
| 2 | 15s | 15s |
| 3 | 30s | 45s |
| 4 | 1m | 1m45s |
| 5 | 5m | 6m45s |
| 6 | 30m | 36m45s |
| 7 | 1h | 1h36m45s |
| 8 | 6h | 7h36m45s |
| 9最终 | 12h | 19h36m45s |
重试策略参考微信支付官方规范,前期快速重试应对网络抖动,后期拉长间隔避免无效轰炸,最终兜底是下游主动查询。
### 6.3 幂等保障
通知发送前检查 `notify_log` 中的发送记录,避免 Poller 并发触发重复推送。同一通知任务加 Redis 分布式锁lock key = `notify_lock:{trade_no}`),保证同一时刻只有一个 goroutine 执行推送。
---
## 7. 幂等方案
系统在三个层面保障幂等,形成防重复操作的纵深防御:
### 7.1 下单幂等(防重复创建订单)
- **第一层 - Redis SET NX**:下单时以 `idempotent:{app_id}:{merchant_order_no}` 为 keySET NX EXTTL = 订单超时时间 + 缓冲)。命中则直接返回已有凭证,不进入后续流程。
- **第二层 - DB 唯一索引**`trade_order` 表在 `(app_id, merchant_order_no)` 上建唯一索引,作为 Redis 失效或缓存穿透时的兜底防护。
- **处理逻辑**:若幂等 key 已存在,直接查询并返回已有订单的支付凭证,不重新调用渠道。
### 7.2 回调幂等(防重复处理上游通知)
- 上游回调到达后,先以 `(channel_trade_no, status)` 查询 DB如已处理则直接返回成功。
- 更新 `trade_order.status` 使用**乐观锁**`WHERE status = 'PAYING' AND trade_no = ?`),确保状态只正向流转,并发更新时只有一个成功,其余幂等返回。
### 7.3 分润 / 服务费幂等(防重复分账)
- `profit_sharing_order``service_fee_log``trade_no` 上建唯一索引(同一笔交易只触发一次分账)。
- 调用渠道分账 API 前,以 `sharing_lock:{trade_no}` 加 Redis **分布式锁**TTL = 30s防止并发触发。
---
## 8. 关键技术决策点
### 8.1 单体还是微服务
**决策:单体**。理由团队规模小MVP 阶段交易量 < 500 QPS单体的运维复杂度远低于微服务Go 的 goroutine 模型天然支持高并发,单体完全能满足性能目标。架构上通过分层和 interface 保持模块边界清晰,未来有需要时可以沿模块边界拆分为微服务。
### 8.2 消息队列选型
**决策Redis Sorted Set 作为延迟队列**。理由:避免引入独立 MQ 组件RabbitMQ、Kafka增加运维负担Redis 已是必选基础设施Sorted Set 的 score 天然表达「下次执行时间」,实现简单可靠。当 QPS 超过 5000 或需要多消费者时再迁移到专业 MQ。
### 8.3 订单号策略
**决策:数据库序列(行级锁 + 自增)**,不用 UUID不用雪花 ID。理由UUID 无序,频繁插入导致 B+ 树碎片化;雪花 ID 依赖机器 ID 配置,多实例部署时配置复杂;数据库序列在 MySQL 层保证 app_id 维度的唯一递增,实现最简单,天然满足 PRD 中「不同应用独立编码序列」的要求。生成格式:`{prefix}{yyMMdd}{8位序号}`,例如 `PAY26022700000001`
### 8.4 密钥存储
**决策数据库加密存储AES-256-GCM 加密**。私钥、appSecret 等敏感字段以加密后的 Base64 字符串存入 MySQL加密密钥由环境变量注入不写入代码或配置文件。读取时在渠道配置仓储层解密上层服务不感知加密细节。
### 8.5 对账执行机制
**决策:进程内 cron + 数据库任务锁**。使用 `robfig/cron` 在进程内调度,多实例部署时通过 Redis SETNX 确保同一时刻只有一个实例执行对账,避免重复。不引入外部调度平台(如 XXL-Job保持轻量。
### 8.6 数据隔离粒度
**决策:以 app_id 为核心隔离维度**。订单、分润配置、服务费配置、订单编码序列均以 app_id 隔离。不同 app 的数据物理上在同一张表(通过 app_id 字段区分),通过数据库索引和应用层鉴权确保 A 应用无法访问 B 应用的数据。MVP 阶段不做分库分表,当单 app 订单量超过 5000 万后再考虑分表。
### 8.7 固定账户收款匹配策略
**决策:规则引擎(优先级匹配)而非 ML 模型**。三维度匹配(备注解析 > 金额精确匹配 > 付款方名称相似度)通过确定性规则实现,可解释、可审计、易排查。备注解析采用正则提取订单号,名称比较采用精确相等(不用模糊匹配),避免误匹配导致的资金风险。匹配降级策略:备注匹配优先,失败时降级为金额匹配,多候选时用名称缩小范围,无法确定时标记待人工确认。
---
## 9. 部署架构
```
┌─────────────────┐
│ Nginx / LB │
└────────┬────────┘
┌───────────────┼───────────────┐
│ │ │
┌─────────▼──────┐ ┌──────▼───────┐ ┌────▼──────────┐
│ pay-bridge │ │ pay-bridge │ │ pay-bridge │
│ instance 1 │ │ instance 2 │ │ instance 3 │
└────────┬───────┘ └──────┬───────┘ └────┬──────────┘
│ │ │
┌────────▼────────────────▼──────────────▼──────────┐
│ MySQL 8.0(主从复制) │
│ RedisSentinel / Cluster 模式) │
└───────────────────────────────────────────────────┘
```
**水平扩展能力保障**
- 无本地状态:所有实例状态通过 Redis 和 MySQL 共享,任意实例可处理任意请求。
- 幂等在 Redis/DB 层:多实例并发下单、重复回调均由 Redis SET NX 和 DB 唯一索引保障。
- 分布式锁在 Redis 层:分润、服务费分账操作通过 Redis 锁防止并发执行。
- 定时任务去重cron 任务通过 Redis SETNX 保证多实例中只有一个实例执行。
**高可用方案**
- MySQL 主从复制:写操作走主库,读操作可走从库(按需);主库故障时手动或自动切换。
- Redis Sentinel3 节点 Sentinel 监控,主节点故障自动切换,客户端感知切换。
- Nginx 负载均衡upstream 配置健康检查,实例故障自动摘除。
- 日志聚合:结构化 JSON 日志接入 ELK/Loki多实例日志统一查询。

View File

@@ -0,0 +1,330 @@
# 001 - 汇元企业入网申请 API
**接口名称:** `customer.enter.enterprise.apply`
**更新时间:** 2025-11-28
**状态:** 已实现
---
## 调用地址
| 环境 | 地址 |
|------|------|
| 生产 | `https://openapi.heepay.com/v1/customer/gateway` |
| 沙箱 | `http://openapi.heepaydev.com/v1/customer/gateway` |
> 注意:进件网关地址与支付网关不同,对应 `config.yaml` 中的 `channels.heepay.merchant_url`。
---
## 接口说明
企业商户入网申请。所有 `*_img` 字段均需先调用**文件上传接口**(接口 002获取 `file_id` 后传入。
---
## 请求业务参数biz_content
### 顶层字段
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `base_info` | 基础信息 | 是 | Object | 见下方 |
| `settlement_info` | 结算信息 | 是 | Object | 见下方 |
| `addition_info` | 补充信息 | 否 | Object | 见下方 |
| `subject_info` | 主体信息 | 是 | Object | 见下方 |
| `identity_info` | 法人信息 | 是 | Object | 见下方 |
| `contact_info` | 业务联系人信息 | 是 | Object | 见下方 |
| `ubo_infos` | 受益所有人信息 | 条件必填 | Object[] | 受益人非法人时必传 |
| `business_info` | 业务信息 | 是 | Object | 见下方 |
---
### base_info 基础信息
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `request_no` | 商户入网申请流水号 | 是 | String(64) | 商户自定义,全局唯一 |
| `alias_name` | 商户简称 | 是 | String(20) | 支付宝/微信支付页显示该名称 |
| `mcc` | 经营类目编码 | 是 | String(4) | 参照【经营类目编码】列表 |
| `service_phone` | 客服电话 | 是 | String | 客服电话 |
| `email` | 商户邮箱 | 是 | String(128) | 首次入网默认作为登录账号和联系人邮箱 |
| `notify_url` | 通知地址 | 否 | String(256) | 汇元主动通知的 http/https 回调地址 |
---
### settlement_info 结算信息
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `settle_type` | 结算类型 | 是 | String | `ACCOUNT`=结算到汇付宝账户,`BANK_CARD`=结算到银行卡 |
| `account_type` | 账户类型 | 是 | String | `PUBLIC`=对公,`PRIVATE`=对私;公司只支持对公,小微只支持对私 |
| `account_no` | 银行卡号 | 是 | String(35) | 银行卡号 |
| `account_name` | 开户名称 | 是 | String(32) | 开户名称 |
| `account_branch_no` | 开户支行联行号 | 是 | String(64) | 开户支行联行号 |
| `open_account_img` | 银行开户许可照 | 条件必填 | String(64) | 对公账号必传,传 `file_id` |
| `bank_name` | 银行名称 | 是 | String | 参照【银行列表】 |
| `region_code` | 银行卡省市区县编码 | 是 | String(6) | 参照省市编码列表 |
---
### addition_info 补充信息(选填)
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `open_merch_video` | 开户意愿视频 | 否 | String | 传 `file_id` |
| `sharing_protocol_img` | 分账协议 | 否 | String | 传 `file_id` |
| `business_developer` | 业务开发者(拓展商户的业务员) | 否 | String(20) | 业务员姓名 |
---
### subject_info 主体信息
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `name` | 商户名称 | 是 | String(50) | 须与营业执照名称一致 |
| `cert_no` | 营业执照号 | 是 | String(32) | 营业执照号 |
| `region_code` | 营业执照区划编码 | 是 | String(32) | 传区县编码(通过行政区划查询接口获取) |
| `address` | 营业执照注册地址 | 是 | String(250) | 营业执照注册地址 |
| `cert_img` | 营业执照图片 | 是 | String | 传 `file_id` |
| `cert_expire` | 营业执照有效期 | 是 | String | 格式:`yyyy-MM-dd/yyyy-MM-dd`,长期有效传 `yyyy-MM-dd/forever` |
---
### identity_info 法人信息
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `name` | 姓名 | 是 | String(18) | 法人姓名 |
| `mobile` | 手机号 | 是 | String(11) | 法人手机号 |
| `cert_type` | 证件类型 | 是 | String | `ID_CARD`=大陆身份证,`HK_CARD`=港通行证,`MC_CARD`=澳通行证,`TW_CARD`=台通行证,`PASSPORT`=外籍护照 |
| `cert_no` | 证件号 | 是 | String(32) | 证件号码 |
| `nation` | 国籍类型 | 是 | Int | 参照【国家编码】列表 |
| `cert_front_img` | 证件正面照(人像面) | 是 | String | 传 `file_id` |
| `cert_back_img` | 证件反面照(非人像面) | 是 | String | 传 `file_id` |
| `cert_expire` | 证件有效期 | 是 | String | 格式:`yyyy-MM-dd/yyyy-MM-dd`,长期有效传 `yyyy-MM-dd/forever` |
| `belong_ubo` | 受益人是否是法人 | 是 | Bool | `true`=是,`false`=否;为 false 时 `ubo_infos` 必传 |
---
### contact_info 业务联系人信息
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `name` | 姓名 | 是 | String(32) | 业务联系人姓名 |
| `mobile` | 手机号 | 是 | String(11) | 业务联系人手机号 |
| `cert_type` | 证件类型 | 是 | String | 同 `identity_info.cert_type` 枚举值 |
| `cert_no` | 证件号 | 是 | String(18) | 证件号码 |
| `nation` | 国籍类型 | 是 | Int | 参照【国家编码】列表 |
| `cert_expire` | 证件有效期 | 是 | String | 格式:`yyyy-MM-dd/yyyy-MM-dd`,长期有效传 `yyyy-MM-dd/forever` |
| `cert_front_img` | 证件正面照(人像面) | 是 | String(255) | 传 `file_id` |
| `cert_back_img` | 证件反面照(非人像面) | 是 | String(255) | 传 `file_id` |
---
### ubo_infos 受益所有人信息(受益人非法人时必传,数组)
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `name` | 证件姓名 | 是 | String(64) | 受益所有人证件姓名 |
| `cert_type` | 证件类型 | 是 | String | 同 `identity_info.cert_type` 枚举值 |
| `cert_no` | 证件号码 | 是 | String(32) | 证件号码 |
| `nation` | 国籍类型 | 是 | Int | 参照【国家编码】列表 |
| `cert_expire` | 证件有效期 | 是 | String | 格式:`yyyy-MM-dd/yyyy-MM-dd`,长期有效传 `yyyy-MM-dd/forever` |
| `cert_address` | 证件地址 | 是 | String(255) | 受益所有人证件地址 |
| `rate` | 持股比例 | 是 | String | 以 % 为单位,传 1-100 的数字,如 `10` 表示占股 10% |
---
### business_info 业务信息
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `business_open_info` | 业务开通详情 | 是 | Object | 见下方 |
#### business_open_info
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `business_platform` | 业务平台 | 是 | String | `HEEPAY`=汇付宝,`HEELIFE`=汇生活 |
| `heepay_info` | 汇付宝信息 | 条件必填 | Object | `business_platform=HEEPAY` 时传入 |
| `heelife_info` | 汇生活信息 | 条件必填 | Object | `business_platform=HEELIFE` 时传入 |
#### heepay_info 汇付宝信息
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `operate_type` | 操作类型 | 是 | String | `OPEN_ORDINARY_MERCH`=开通普通户收单账户,`OPEN_BALANCE`=开通子户余额账户,`OPEN_MERCH`=开通子户收单账户,`APPEND_OPEN_PRODUCT`=补充开通产品;小微商户不支持 `OPEN_ORDINARY_MERCH` |
| `scene_info` | 场景信息 | 条件必填 | Object | 收单账户必传 |
| `heepay_ordinary` | 普通商户必须信息 | 条件必填 | Object | `operate_type=OPEN_ORDINARY_MERCH` 时必传 |
| `product_info` | 产品费率信息 | 条件必填 | Object | `operate_type=OPEN_MERCH``APPEND_OPEN_PRODUCT` 时必传 |
| `wechat_config` | 微信配置 | 否 | Object | 见下方 |
| `wechat_enter` | 微信进件参数 | 否 | Object | 需要指定微信进件参数时传入 |
| `alipay_enter` | 支付宝进件参数 | 否 | Object | 需要指定支付宝进件参数时传入 |
#### scene_info 场景信息(收单账户必传)
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `shop_brand_img` | 商户品牌标识图片 | 是 | String | 企业传公司大楼照,个体/小微传门头照,传 `file_id` |
| `customer_service_img` | 客户服务照 | 是 | String | 企业传公司前台照,个体/小微传收银台照,传 `file_id` |
| `work_env_img` | 商户经营照 | 是 | String | 企业传内部办公场所照,个体/小微传店铺经营照,传 `file_id` |
#### heepay_ordinary 普通商户必须信息operate_type=OPEN_ORDINARY_MERCH 时必传)
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `app_type` | 应用类型 | 是 | String | `PC``APP``WAP``WECHAT_MINI`=微信小程序,`ALIPAY_MINI`=支付宝小程序,`WECHAT_PUBLIC_PLATFORM`=微信公众号,`QUICK_PASS`=云闪付,`OTHER`=其他线上场景 |
| `app_name` | 应用名称 | 是 | String | 应用名称 |
| `app_url` | 应用网址 | 条件必填 | String | `app_type` 为 PC/APP/WAP/WECHAT_MINI 时必填 |
| `app_download_url` | 应用下载地址 | 条件必填 | String | `app_type` 为 PC/APP/WAP/WECHAT_MINI 时必填 |
| `mini_app_id` | 小程序 APPID | 条件必填 | String | `app_type` 为 WECHAT_MINI/ALIPAY_MINI 时必填 |
| `app_status` | 应用状态 | 是 | String | `OFFLINE`=未上线,`ONLINE`=已上线公开,`ONLINE_SPECIAL`=已上线特定IP/用户开放 |
| `icp_url` | ICP 备案网址 | 条件必填 | String | `app_type` 为 PC/WAP 时必填 |
| `business_types` | 业务种类 | 是 | Object[] | 支持多个,见下方 `business_types` 结构 |
| `business_note` | 业务场景说明 | 是 | String | 业务场景说明 |
`business_types` 单条结构:
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `business_type` | 业务种类 | 是 | String | 见下方枚举值 |
`business_type` 枚举值:
| 枚举值 | 说明 |
|--------|------|
| `PURCHASE_VIRTUAL_GOODS` | 虚拟商品购买 |
| `PREPAID_ACCOUNT_CHARGE` | 预付费类账户充值 |
| `MATERIAL_CONSUMPTION` | 实物消费 |
| `AVIATION_BUSINESS_TRAVEL_EXPENSES` | 航空商旅消费 |
| `L_C_CONSUMPTION` | 生活及商业消费服务 |
| `OTHER_MERCH_CONSUMPTION` | 其他商户消费 |
| `PAYMENT_PUBLIC_UTILITIES` | 公共事业缴费 |
| `E_MEDICAL_PAYMENT` | 教育医疗缴费 |
| `GOVERNMENT_PAYMENT` | 政府服务缴费 |
| `PUBLIC_WELFARE_DONATION` | 公益捐款 |
| `OTHER_PUBLIC_SERVICES` | 其他公共服务 |
| `OTHER_FINANCIAL_PAYMENTS` | 其他金融付款 |
| `FUND_PURCHASE` | 基金购买 |
| `INSURANCE_PURCHASE` | 保险选购 |
| `WEALTH_MANAGE` | 投资理财 |
| `CREDIT_REPAYMENT` | 信贷偿还 |
| `CREDIT_CARD_REPAYMENTS` | 信用卡还款转出 |
| `RECHARGE_PAYMENT_ACCOUNT` | 支付账户充值 |
| `BANK_ACCOUNT_TRANSFER_OUT` | 银行账户转账转出 |
| `OTHER_ACCOUNT_CHARGE` | 其他账户充值 |
| `SERVICE_TYPE` | 服务类 |
| `SYSTEM_TYPE` | 系统类 |
| `MANAGE_TYPE` | 管理类 |
| `BID_BOND_PAYMENT` | 招投标保证金支付 |
| `OVERSEAS_SHOPPING` | 境外商品购买 |
| `business_img` | 经营服务图片 | 条件必填 | String | `app_type` 为 APP/WECHAT_MINI 时必填,传 `file_id` |
| `ext_a_img` ~ `ext_e_img` | 附件 1-5 | 否 | String | 传 `file_id` |
#### product_info 产品费率信息operate_type=OPEN_MERCH 或 APPEND_OPEN_PRODUCT 时必传)
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `reference_merch_id` | 标杆商户编码 | 条件必填 | Long | 与 `rate_infos` 二选一 |
| `rate_infos` | 费率列表 | 条件必填 | Object[] | 与 `reference_merch_id` 二选一 |
`rate_infos` 单条结构:
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `rate_code` | 支付场景编码 | 是 | String | 参照【支付场景】列表 |
| `rate_type` | 费率类型 | 是 | String(32) | `SINGLE_PERCENT`=单笔百分比,`SINGLE_FIXED`=单笔固定值 |
| `rate` | 费率值 | 是 | String(5) | 费率值 |
#### wechat_config 微信配置(选填)
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `app_ids` | appId 列表 | 否 | Object[] | appId 列表 |
| `pay_urls` | 支付授权目录列表 | 否 | Object[] | 支付授权目录列表 |
#### wechat_enter 微信进件参数(选填)
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `channel_code` | 进件渠道号 | 是 | String | 进件渠道号 |
#### alipay_enter 支付宝进件参数(选填)
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `channel_code` | 进件渠道号 | 是 | String | 进件渠道号 |
#### heelife_info 汇生活信息business_platform=HEELIFE 时传入)
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `operate_type` | 操作类型 | 是 | String | 指明业务类型(具体枚举值待补充) |
---
## 响应业务参数
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `request_no` | 商户申请流水号 | 是 | String | 后续查询(接口 003和修改接口 004时使用 |
---
## 业务错误码
| 错误码 | 说明 | 处理建议 |
|--------|------|---------|
| `invalid_parameter_email_existed` | 汇元已存在此邮箱 | 更换邮箱 |
| `invalid_parameter_email_except` | 邮箱校验异常 | 检查参数 |
| `invalid_parameter_enterprise_type_ex` | 企业用户只支持对公账户 | 检查 `account_type` |
| `invalid_parameter_micro_type_ex` | 小微用户只支持对私账户 | 检查 `account_type` |
| `invalid_parameter_ubo_must_not_empty` | 受益人不能为空 | 传入 `ubo_infos` |
| `invalid_parameter_rate_must_not_empty` | 开通收单账户费率信息不能为空 | 检查 `product_info` |
| `invalid_parameter_common_must_not_empty` | 开通普通户必须信息不能为空 | 检查 `heepay_ordinary` |
| `invalid_parameter_mark_merch_not_existed` | 标杆商户未配置 | 联系汇元配置 |
| `business_fail_customer_has_passed` | 商户已入驻完毕 | 确认 `request_no` 是否已用过 |
| `business_fail_customer_waiting` | 入驻申请处理中 | 等待审核结果 |
| `business_fail_save_his_work_record_fail` | 迁移创建历史入驻工单失败 | 重试 |
| `business_fail_delete_his_work_record_fail` | 迁移删除历史入驻工单失败 | 重试 |
| `business_fail_save_work_record_fail` | 保存入驻记录失败 | 重试 |
| `unknown_exception` | 系统未知问题 | 参考返回描述 |
| `unknown_error_gateway` | 网关系统不可用 | 稍后重试 |
| `invalid_auth` | 授权权限不足 | 检查签名/权限 |
| `missing_parameter` | 缺少参数 | 补充必填参数 |
| `invalid_parameter` | 无效参数 | 检查参数格式 |
| `invalid_request` | 无效请求 | 参考返回详细信息 |
| `biz_failure` | 业务错误 | 参照具体错误提示 |
| `service_not_exists` | 服务不存在 | 确认服务是否开通 |
| `service_time_out` | 系统繁忙 | 稍后重试 |
| `channel_error` | 通道系统异常 | 用相同参数重新调用 |
---
## 实现要点
1. **网关地址**:使用 `channels.heepay.merchant_url`(进件网关),而非支付网关
2. **图片先传后用**:所有 `*_img` 字段均为 `file_id`,依赖接口 002文件上传
3. **受益人条件必填**`identity_info.belong_ubo=false` 时,`ubo_infos` 数组必传
4. **operate_type 决定必填子结构**
- `OPEN_MERCH` / `APPEND_OPEN_PRODUCT``product_info` 必传
- `OPEN_ORDINARY_MERCH``heepay_ordinary` 必传
- 收单账户 → `scene_info` 必传
5. **费率二选一**`product_info``reference_merch_id``rate_infos` 二选一
6. **返回 request_no**:作为查询(接口 003和修改接口 004的入参需持久化存储
---
## 待补充
- [ ] `heelife_info.operate_type` 枚举值(暂不支持汇生活,低优先级)
- [ ] `wechat_config.app_ids``pay_urls` 单条结构字段
- [ ] 省市区县编码(建议用行政区划查询接口在线获取,无需维护静态列表)
## 附录文档
- MCC 经营类目编码 → `appendix-mcc-codes.md`
- 银行列表 → `appendix-bank-codes.md`
- 国家编码 → `appendix-nation-codes.md`
- 支付场景编码 → `appendix-payment-scene-codes.md`

View File

@@ -0,0 +1,135 @@
# 002 - 汇元商户文件上传 API
**接口名称:** `customer.file.upload`
**更新时间:** 2025-11-28
**状态:** 已实现
---
## 调用地址
| 环境 | 地址 |
|------|------|
| 生产 | `https://openapi.heepay.com/v1/customer/gateway` |
| 沙箱 | `http://openapi.heepaydev.com/v1/customer/gateway` |
与入网接口共用同一进件网关(`channels.heepay.merchant_url`)。
---
## 接口说明
上传图片/视频/文件,返回 `file_id`供入网接口001中所有 `*_img` 字段使用。**必须先上传文件获取 `file_id`,再调用入网接口。**
---
## 请求业务参数biz_content
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `file_content` | 文件内容 | 是 | ByteData | 文件二进制内容Base64 编码后传入) |
| `file_sign` | 文件内容签名 | 是 | String | 文件内容的 MD5 值,用于校验文件完整性 |
| `file_media_type` | 文件类型 | 是 | String | 参照【文件类型编码】列表(待补充) |
---
## 响应业务参数
| 字段 | 名称 | 必填 | 类型 | 说明 |
|------|------|------|------|------|
| `file_id` | 文件 ID | 否 | String | 上传成功后返回,传入入网接口的 `*_img` 字段 |
---
## 支持的文件格式
| 类型 | 格式 |
|------|------|
| 图片 | `png` / `bmp` / `gif` / `jpg` / `jpeg` |
| 视频 | `mp4` / `flv` / `avi` / `rm` / `rmvb` / `wav` |
| 文件 | `zip` / `rar` / `pdf` |
---
## 业务错误码
| 错误码 | 说明 | 处理建议 |
|--------|------|---------|
| `invalid_parameter_file_type_not_correct` | 文件类型不正确 | 检查格式是否在支持列表内 |
| `invalid_parameter_file_size_too_big` | 文件过大 | 压缩后重新上传 |
| `invalid_parameter_file_sign_can_not_null` | 文件签名不能为空 | 传入 `file_sign`MD5 |
| `invalid_parameter_file_sign_err` | 文件签名异常 | 确认文件是否损坏,重新计算 MD5 |
| `invalid_parameter_file_has_err` | file 有误,疑似被修改 | 检查文件完整性 |
| `invalid_parameter_file_need_ext` | 文件名需带扩展名 | 上传时文件名需包含扩展名 |
| `unknown_exception` | 系统未知问题 | 参考返回描述 |
| `unknown_error_gateway` | 网关系统不可用 | 稍后重试 |
| `invalid_auth` | 授权权限不足 | 检查签名/权限 |
| `missing_parameter` | 缺少参数 | 补充必填参数 |
| `invalid_parameter` | 无效参数 | 检查参数格式 |
| `invalid_request` | 无效请求 | 参考返回详细信息 |
| `biz_failure` | 业务错误 | 参照具体错误提示 |
| `service_not_exists` | 服务不存在 | 确认服务是否开通 |
| `service_time_out` | 系统繁忙 | 稍后重试 |
| `channel_error` | 通道系统异常 | 用相同参数重新调用 |
---
## 实现要点
1. **`file_content` 编码方式**ByteData 类型,实现时需将文件二进制内容 Base64 编码后放入 `biz_content` JSON 字符串中
2. **`file_sign` 计算**:对原始文件二进制内容计算 MD5得到 32 位小写十六进制字符串
3. **文件名带扩展名**:请求中需要携带文件名(含扩展名),具体字段名待联调确认
4. **调用顺序**:文件上传 → 获取 `file_id` → 入网申请001`file_id` 需持久化存储备用
5. **复用性**:同一文件可上传一次,`file_id` 在多个字段中复用(如法人正反面同一人时)
---
## 文件类型编码file_media_type
| 文件名称 | 类型值 |
|---------|--------|
| 营业执照 | `01` |
| 开户许可证/开户证明照 | `02` |
| 门头照 | `03` |
| 店内场景照 | `04` |
| 收银台照 | `05` |
| 法人身份证正面照 | `06` |
| 法人身份证反面照 | `07` |
| 联系人身份证正面照 | `08` |
| 联系人身份证反面照 | `09` |
| 公司大楼照 | `10` |
| 公司前台照 | `11` |
| 结算银行卡正面照 | `12` |
| 结算银行卡反面照 | `13` |
| 结算人手持银行卡正面照 | `14` |
| 经营者身份证正面照 | `15` |
| 经营者身份证反面照 | `16` |
| 经营者手持身份证正面照 | `17` |
| 经营者手持银行卡正面照 | `18` |
| 其它图片1 | `19` |
| 其它图片2 | `20` |
| 开户意愿视频 | `50` |
| 分账协议 | `52` |
> 对照入网接口001字段与文件类型的映射关系
>
> | 入网字段 | file_media_type |
> |---------|----------------|
> | `subject_info.cert_img`(营业执照) | `01` |
> | `settlement_info.open_account_img`(开户许可证) | `02` |
> | `scene_info.shop_brand_img`(门头照/公司大楼照) | `03` 或 `10` |
> | `scene_info.customer_service_img`(收银台照/公司前台照) | `05` 或 `11` |
> | `scene_info.work_env_img`(店内场景照) | `04` |
> | `identity_info.cert_front_img`(法人证件正面) | `06` |
> | `identity_info.cert_back_img`(法人证件反面) | `07` |
> | `contact_info.cert_front_img`(联系人证件正面) | `08` |
> | `contact_info.cert_back_img`(联系人证件反面) | `09` |
> | `addition_info.open_merch_video`(开户意愿视频) | `50` |
> | `addition_info.sharing_protocol_img`(分账协议) | `52` |
---
## 待补充
- [ ] 文件大小限制(图片/视频各自上限)
- [ ] 文件名字段名称确认(`file_name`

View File

@@ -0,0 +1,270 @@
# 附录 - 银行列表
使用场景商户入网接口001`settlement_info.bank_name` 字段传入。
> **注意**:请按以下银行名称严格匹配传入。若找不到具体支行名称,按大行名称传入即可。
> 例如:「中国建设银行股份有限公司宿迁宿豫支行」→ 传入「建设银行」
---
## 结算银行列表(入网使用)
| 编码 | 银行名称 |
|------|---------|
| 1 | 工商银行 |
| 2 | 建设银行 |
| 3 | 农业银行 |
| 4 | 邮政储蓄银行 |
| 5 | 中国银行 |
| 6 | 交通银行 |
| 7 | 招商银行 |
| 8 | 光大银行 |
| 9 | 浦发银行 |
| 10 | 华夏银行 |
| 11 | 广东发展银行 |
| 12 | 中信银行 |
| 13 | 兴业银行 |
| 14 | 民生银行 |
| 15 | 杭州银行 |
| 16 | 上海银行 |
| 17 | 宁波银行 |
| 18 | 平安银行 |
| 19 | 东亚银行 |
| 20 | 上海农村商业银行 |
| 21 | 南京银行 |
| 22 | 广州银行 |
| 23 | 渤海银行 |
| 24 | 大连银行 |
| 25 | 徽商银行 |
| 26 | 江苏银行 |
| 27 | 齐鲁银行 |
| 28 | 渣打银行 |
| 29 | 深圳农村商业银行 |
| 30 | 温州银行 |
| 31 | 厦门银行 |
| 32 | 浙商银行 |
| 33 | 北京银行 |
| 34 | 哈尔滨银行 |
| 35 | 湖北银行 |
| 36 | 潍坊银行 |
| 37 | 贵阳银行 |
| 38 | 浙江泰隆商业银行 |
| 39 | 济宁银行 |
| 40 | 台州银行 |
| 41 | 汉口银行 |
| 42 | 安徽省农村信用社联合社 |
| 43 | 郑州银行 |
| 44 | 中原银行 |
| 45 | 宜宾商业银行 |
| 46 | 莱商银行 |
| 47 | 日照银行 |
| 48 | 常熟农商银行 |
| 49 | 北京农商银行 |
| 50 | 福建省农村信用社联合社 |
| 51 | 齐商银行 |
| 52 | 云南省农村信用社联合社 |
| 53 | 山东省农村信用社联合社 |
| 54 | 广东华兴银行 |
| 55 | 江西银行 |
| 56 | 东营银行 |
| 57 | 浙江稠州商业银行 |
| 58 | 重庆农村商业银行 |
| 59 | 晋城银行 |
| 60 | 秦农银行 |
| 61 | 长安银行 |
| 62 | 成都银行 |
| 63 | 恒丰银行 |
| 64 | 承德银行 |
| 65 | 绍兴银行 |
| 66 | 广东南粤银行 |
| 67 | 青岛银行 |
| 68 | 江苏长江商行 |
| 69 | 包商银行 |
| 70 | 富滇银行 |
| 71 | 自贡市商业银行 |
| 72 | 湖北农信 |
| 73 | 浙江农信 |
| 74 | 葫芦岛银行 |
| 75 | 昆仑银行 |
| 76 | 苏州银行 |
| 77 | 湖州银行 |
| 78 | 泉州银行 |
| 79 | 广州农村商业银行 |
| 81 | 太仓农村商业银行 |
| 82 | 烟台银行 |
| 83 | 上饶银行 |
| 84 | 绵阳市商业银行 |
| 85 | 德州银行 |
| 86 | 广西农村信用社 |
| 87 | 柳州银行 |
| 88 | 新韩银行中国 |
| 89 | 长沙银行 |
| 90 | 黄河农村商业银行 |
| 91 | 鞍山银行 |
| 92 | 龙江银行 |
| 93 | 河北银行 |
| 94 | 内蒙古银行 |
| 95 | 吉林农村信用社 |
| 96 | 浙江三门银座村镇银行 |
| 97 | 东莞银行 |
| 98 | 泰安银行 |
| 99 | 桂林银行股份有限公司 |
| 100 | 昆山农村商业银行 |
| 101 | 攀枝花市商业银行 |
| 102 | 西安银行 |
| 103 | 营口银行 |
| 104 | 江苏省农村信用社联合社 |
| 105 | 顺德农村商业银行 |
| 106 | 张家港农村商业银行 |
| 107 | 重庆黔江银座村镇银行 |
| 108 | 临商银行 |
| 109 | 洛阳银行 |
| 110 | 邢台银行 |
| 111 | 韩亚银行 |
| 112 | 广西北部湾银行 |
| 113 | 张家口市商业银行 |
| 114 | 珠海华润银行 |
| 115 | 天津银行 |
| 116 | 阜新银行 |
| 117 | 吴江农村商业银行 |
| 118 | 友利银行 |
| 119 | 北京顺义银座村镇银行 |
| 120 | 晋商银行 |
| 121 | 赣州银行 |
| 122 | 鄞州银行 |
| 123 | 兰州银行 |
| 124 | 锦州银行 |
| 125 | 邯郸市商业银行 |
| 126 | 深圳福田银座村镇银行 |
| 127 | 东莞农村商业银行 |
| 128 | 乌鲁木齐市商业银行 |
| 129 | 浙江景宁银座村镇银行 |
| 130 | 威海市商业银行 |
| 131 | 海南农村商业银行股份有限公司 |
| 132 | 商丘银行 |
| 133 | 鄂尔多斯银行 |
| 134 | 江西赣州银座村镇银行 |
| 135 | 天津农商银行 |
| 136 | 重庆银行 |
| 137 | 宁夏银行 |
| 138 | 浙江民泰商业银行 |
| 140 | 长城华西银行 |
| 141 | 廊坊银行 |
| 142 | 沧州银行 |
| 143 | 福建海峡银行 |
| 144 | 嘉兴银行 |
| 145 | 吉林银行 |
| 146 | 青海银行 |
| 147 | 重庆渝北银座村镇银行 |
| 148 | 枣庄银行 |
| 149 | 武汉农村商业银行 |
| 150 | 重庆三峡银行 |
| 151 | 南洋商业银行 |
| 152 | 恒生银行 |
| 153 | 集友银行 |
| 154 | 大众银行 |
| 155 | 永亨银行 |
| 156 | 上海商业银行 |
| 157 | 永隆银行 |
| 158 | 中信嘉华银行 |
| 159 | 华南商业银行 |
| 161 | 保定银行 |
| 162 | 上海华瑞银行 |
| 163 | 九江银行 |
| 164 | 江西省农村信用社 |
| 165 | 广东省农村信用社联合社 |
| 166 | 河南省农村信用社 |
| 167 | 辽宁省农村信用社 |
| 168 | 黑龙江省农村信用社 |
| 169 | 湖南省农村信用社 |
| 170 | 河北省农村信用社 |
| 171 | 甘肃省农村信用社 |
| 172 | 山西省农村信用社 |
| 173 | 陕西省农村信用社 |
| 174 | 贵州省农村信用社 |
| 175 | 内蒙古自治区农村信用社 |
| 176 | 新疆自治区农村信用社 |
| 177 | 四川省农村信用社 |
| 178 | 成都农商银行 |
| 179 | 长沙农商银行 |
| 180 | 三亚农商银行 |
| 221 | 国家开发银行 |
| 224 | 汇丰银行 |
| 239 | 网商银行 |
| 246 | 武汉众邦银行 |
| 310 | 中国农业发展银行 |
| 432 | 深圳前海微众银行股份有限公司 |
| 473 | 北京中关村银行股份有限公司 |
| 480 | 吉林亿联银行股份有限公司 |
| 483 | 四川新网银行股份有限公司 |
| 492 | 重庆富民银行股份有限公司 |
| 546 | 四川银行股份有限公司 |
| 584 | 江苏苏商银行股份有限公司 |
| 695 | 山西银行股份有限公司 |
| 720 | 花旗银行(中国)有限公司 |
| 777 | 摩根大通银行(中国)有限公司 |
| 948 | 宁波东海银行股份有限公司 |
> 完整列表共 800+ 条,上方仅列出主要银行。如需完整列表请查阅汇元客户中心银行列表 Excel对接群 @客服督导获取),该列表更新更及时。
---
## 网银支持银行列表
用于网银支付场景的银行编码(与结算银行编码体系不同)。
| 编码 | 银行名称 |
|------|---------|
| 001 | 中国工商银行 |
| 003 | 中国建设银行 |
| 005 | 中国农业银行 |
| 006 | 交通银行 |
| 008 | 广东发展银行 |
| 009 | 中信银行 |
| 010 | 中国光大银行 |
| 011 | 兴业银行 |
| 012 | 平安银行 |
| 013 | 中国民生银行 |
| 014 | 华夏银行 |
| 020 | 中国邮政储蓄银行 |
| 022 | 上海银行 |
| 024 | 宁波银行 |
| 029 | 北京农商银行 |
| 035 | 渤海银行 |
| 044 | 浙商银行 |
| 045 | 北京银行 |
### 企业网银
| 编码 | 银行名称 |
|------|---------|
| 030 | 农业银行(企业银行) |
| 046 | 中信银行(企业银行) |
| 047 | 招商银行(企业银行) |
| 048 | 中国建设银行(企业银行) |
| 049 | 上海浦东发展银行(企业银行) |
| 050 | 中国银行(企业银行) |
| 051 | 广发银行(企业银行) |
| 052 | 北京银行(企业银行) |
| 053 | 中国邮政储蓄银行(企业银行) |
| 054 | 中国工商银行(企业银行) |
| 055 | 中国民生银行(企业银行) |
| 056 | 中国光大银行(企业银行) |
| 057 | 上海银行(企业银行) |
| 058 | 平安银行(企业银行) |
| 059 | 宁波银行(企业银行) |
| 060 | 华夏(企业银行) |
| 061 | 浙商银行(企业银行) |
| 062 | 交通银行(企业银行) |
| 063 | 柳州银行(企业银行) |
| 066 | 桂林银行(企业银行) |
| 068 | 杭州银行(企业银行) |
| 071 | 齐鲁银行(企业银行) |
---
## 注意事项
1. **两套编码体系相互独立**:结算银行列表(数字编码 1-950+)用于入网 `bank_name` 字段网银支持列表3位字符编码 001-071用于网银支付场景勿混用
2. **结算银行传名称**`settlement_info.bank_name` 传银行名称字符串,不传编码
3. **编码存在跳号**:如结算列表中无 80、139、160 等编号,属正常现象

View File

@@ -0,0 +1,179 @@
# 附录 - MCC 经营类目编码
使用场景商户入网接口001`base_info.mcc` 字段传入。
> 小微商户:使用企业或个体户对应行业的编码即可。
## 企业 - 线上业务
适用于游戏、网络虚拟、电商团购、财经资讯、众筹、电信运营商、机票、共享服务、网购平台、O2O 平台、信用还款等。
| 行业细分 | 编码 |
|---------|------|
| 线上商超 | 1000 |
| 在线教育培训机构 | 1001 |
| 人才中介机构/招聘/猎头 | 1002 |
| 职业社交/婚介/交友 | 1003 |
| 机票/机票代理 | 1004 |
| 在线图书/视频/音乐 | 1005 |
| 门户/资讯/论坛 | 1006 |
| 网络直播 | 1008 |
| 软件/建站/技术开发 | 1009 |
| 网络推广/网络广告 | 1010 |
| 综合生活服务平台 | 1011 |
| 电信运营商 | 1012 |
| 宽带收费 | 1013 |
| 信用还款 | 1014 |
| 其他 | 1015 |
## 企业 - 保险
适用于保险公司、保险代理公司。
| 行业细分 | 编码 |
|---------|------|
| 保险业务 | 1016 |
## 企业 - 线下实体
适用于餐饮、零售批发、交通出行、生活娱乐服务、民营医疗机构、缴费、加油、物流快递等。
| 行业细分 | 编码 |
|---------|------|
| 餐饮 | 1017 |
| 超市 | 1018 |
| 便利店 | 1019 |
| 百货 | 1020 |
| 食品生鲜 | 1021 |
| 数码电器/电脑办公 | 1022 |
| 家具建材/家居厨具 | 1023 |
| 服饰箱包 | 1024 |
| 运动户外 | 1025 |
| 美妆个护 | 1026 |
| 母婴用品/儿童玩具 | 1027 |
| 图书音像/文具乐器 | 1028 |
| 黄金珠宝 | 1029 |
| 钟表眼镜 | 1030 |
| 宠物/宠物用品 | 1031 |
| 礼品鲜花/农资绿植 | 1032 |
| 物流/快递 | 1033 |
| 咨询/法律咨询/金融咨询等 | 1034 |
| 婚庆/摄影 | 1035 |
| 装饰/设计 | 1036 |
| 家政/维修服务 | 1037 |
| 广告/会展/活动策划 | 1038 |
| 房地产 | 1039 |
| 丧仪殡葬服务 | 1040 |
| 宠物医院 | 1041 |
| 娱乐票务 | 1042 |
| 运动健身场馆 | 1043 |
| 俱乐部/休闲会所 | 1044 |
| 院线影城 | 1045 |
| 演出赛事 | 1046 |
| 美发/美容/美甲店 | 1047 |
| 酒吧 | 1048 |
| 租车 | 1049 |
| 加油 | 1050 |
| 船舶/海运服务 | 1051 |
| 铁路客运 | 1052 |
| 旅行社 | 1053 |
| 汽车用品 | 1054 |
| 汽车美容/维修保养 | 1055 |
| 停车缴费 | 1056 |
| 旅馆/酒店/度假区 | 1057 |
| 景区 | 1058 |
| 宗教 | 1059 |
| 教育/培训/考试缴费/学费 | 1060 |
| 诊所/卫生站/卫生服务中心 | 1061 |
| 私立/民营医院/诊所 | 1062 |
| 有线电视缴费 | 1063 |
| 话费通讯 | 1064 |
| 拍卖/典当 | 1065 |
| 其他 | 1066 |
## 企业 - 民办教育
| 行业细分 | 编码 |
|---------|------|
| 民办大学及学院 | 1067 |
| 民办中小幼 | 1068 |
## 企业 - 民生缴费 / 交通
适用于水电煤暖气民生缴费、交通罚款、公交/高速。
| 行业细分 | 编码 |
|---------|------|
| 高速收费 | 1069 |
| 城市公共交通 | 1070 |
| 公共事业(水、电、燃气、供暖) | 1071 |
| 游戏 | 1073 |
## 个体户 - 线上业务
适用于电商团购、电信运营商/宽带收费、机票/机票代理。
| 行业细分 | 编码 |
|---------|------|
| 机票/机票代理 | 1074 |
| 线上商超 | 1075 |
| 综合生活服务平台 | 1076 |
## 个体户 - 线下实体
适用于餐饮、零售批发、交通出行、生活娱乐服务、民营医疗机构、缴费等。
| 行业细分 | 编码 |
|---------|------|
| 餐饮 | 1077 |
| 超市 | 1078 |
| 便利店 | 1079 |
| 百货 | 1080 |
| 食品生鲜 | 1081 |
| 数码电器/电脑办公 | 1082 |
| 家具建材/家居厨具 | 1083 |
| 服饰箱包 | 1084 |
| 运动户外 | 1085 |
| 美妆个护 | 1086 |
| 母婴用品/儿童玩具 | 1087 |
| 图书音像/文具乐器 | 1088 |
| 黄金珠宝 | 1089 |
| 钟表 | 1090 |
| 宠物/宠物用品 | 1091 |
| 礼品鲜花/农资绿植 | 1092 |
| 眼镜 | 1093 |
| 物流/快递 | 1094 |
| 咨询/法律咨询/金融咨询等 | 1095 |
| 婚庆/摄影 | 1096 |
| 装饰/设计 | 1097 |
| 家政/维修服务 | 1098 |
| 广告/会展/活动策划 | 1099 |
| 丧仪殡葬服务 | 1100 |
| 宠物医院 | 1101 |
| 娱乐票务 | 1102 |
| 运动健身场馆 | 1103 |
| 俱乐部/休闲会所 | 1104 |
| 院线影城 | 1105 |
| 演出赛事 | 1106 |
| 美发/美容/美甲店 | 1107 |
| 酒吧 | 1108 |
| 租车 | 1109 |
| 加油 | 1110 |
| 船舶/海运服务 | 1111 |
| 汽车用品 | 1112 |
| 汽车美容/维修保养 | 1113 |
| 停车缴费 | 1114 |
| 旅馆/酒店/度假区 | 1115 |
| 景区 | 1116 |
| 教育/培训/考试缴费/学费 | 1117 |
| 保健器械/医疗器械/非处方药品 | 1118 |
| 诊所/卫生站/卫生服务中心 | 1119 |
| 私立/民营医院/诊所 | 1120 |
| 有线电视缴费 | 1121 |
| 话费通讯 | 1122 |
| 拍卖/典当 | 1123 |
| 其他 | 1124 |
## 小微商户
使用企业或个体户对应行业编码1000-1124均可。

View File

@@ -0,0 +1,145 @@
# 附录 - 国家编码
使用场景商户入网接口001以下字段传入
- `identity_info.nation`(法人国籍)
- `contact_info.nation`(业务联系人国籍)
- `ubo_infos[].nation`(受益所有人国籍)
| 编码 | 国家/地区名称 |
|------|-------------|
| 1 | 中国大陆 |
| 2 | 中国香港 |
| 3 | 中国澳门 |
| 4 | 中国台湾地区 |
| 5 | 马来西亚 |
| 6 | 新加坡 |
| 7 | 日本 |
| 8 | 韩国 |
| 9 | 美国 |
| 10 | 加拿大 |
| 11 | 澳大利亚 |
| 12 | 新西兰 |
| 13 | 阿尔巴尼亚 |
| 14 | 阿根廷 |
| 15 | 阿联酋 |
| 16 | 阿曼 |
| 17 | 阿塞拜疆 |
| 18 | 爱尔兰 |
| 19 | 埃及 |
| 20 | 爱沙尼亚 |
| 21 | 安哥拉 |
| 22 | 奥地利 |
| 23 | 巴布亚新几内亚 |
| 24 | 巴哈马 |
| 25 | 巴勒斯坦 |
| 26 | 巴林 |
| 27 | 巴拿马 |
| 28 | 巴西 |
| 29 | 白俄罗斯 |
| 30 | 保加利亚 |
| 31 | 贝宁 |
| 32 | 比利时 |
| 33 | 秘鲁 |
| 34 | 波兰 |
| 35 | 玻利维亚 |
| 36 | 伯利兹 |
| 37 | 布基纳法索 |
| 38 | 赤道几内亚 |
| 39 | 丹麦 |
| 40 | 德国 |
| 41 | 多哥 |
| 42 | 俄罗斯 |
| 43 | 法国 |
| 44 | 菲律宾 |
| 45 | 芬兰 |
| 46 | 佛得角 |
| 47 | 冈比亚 |
| 48 | 格林纳达 |
| 49 | 格鲁吉亚 |
| 50 | 哥伦比亚 |
| 51 | 哥斯达黎加 |
| 52 | 圭亚那 |
| 53 | 荷兰 |
| 54 | 洪都拉斯 |
| 55 | 吉布提 |
| 56 | 吉尔吉斯斯坦 |
| 57 | 几内亚 |
| 58 | 几内亚比绍 |
| 59 | 加蓬 |
| 60 | 柬埔寨 |
| 61 | 津巴布韦 |
| 62 | 喀麦隆 |
| 63 | 卡塔尔 |
| 64 | 开曼群岛 |
| 65 | 克罗地亚 |
| 66 | 科摩罗 |
| 67 | 科威特 |
| 68 | 肯尼亚 |
| 69 | 拉脱维亚 |
| 70 | 莱索托 |
| 71 | 立陶宛 |
| 72 | 卢森堡 |
| 73 | 卢旺达 |
| 74 | 罗马尼亚 |
| 75 | 马达加斯加 |
| 76 | 马尔代夫 |
| 77 | 马拉维 |
| 78 | 马里 |
| 79 | 毛里求斯 |
| 80 | 毛里塔尼亚 |
| 81 | 蒙古 |
| 82 | 摩尔多瓦 |
| 83 | 摩洛哥 |
| 84 | 莫桑比克 |
| 85 | 墨西哥 |
| 86 | 纳米比亚 |
| 87 | 南非 |
| 88 | 尼加拉瓜 |
| 89 | 尼日尔 |
| 90 | 尼日利亚 |
| 91 | 挪威 |
| 92 | 葡萄牙 |
| 93 | 瑞典 |
| 94 | 瑞士 |
| 95 | 萨尔瓦多 |
| 96 | 塞尔维亚 |
| 97 | 塞拉利昂 |
| 98 | 塞内加尔 |
| 99 | 塞浦路斯 |
| 100 | 塞舌尔 |
| 101 | 沙特阿拉伯 |
| 102 | 斯里兰卡 |
| 103 | 斯洛伐克 |
| 104 | 斯洛文尼亚 |
| 105 | 斯威士兰 |
| 106 | 苏里南 |
| 107 | 塔吉克斯坦 |
| 108 | 泰国 |
| 109 | 坦桑尼亚 |
| 110 | 特立尼达和多巴哥 |
| 111 | 土耳其 |
| 112 | 土库曼斯坦 |
| 113 | 突尼斯 |
| 114 | 危地马拉 |
| 115 | 委内瑞拉 |
| 116 | 文莱 |
| 117 | 乌干达 |
| 118 | 乌克兰 |
| 119 | 乌拉圭 |
| 120 | 乌兹别克斯坦 |
| 121 | 西班牙 |
| 122 | 希腊 |
| 123 | 匈牙利 |
| 124 | 牙买加 |
| 125 | 也门 |
| 126 | 意大利 |
| 127 | 以色列 |
| 128 | 印度 |
| 129 | 印度尼西亚 |
| 130 | 英国 |
| 131 | 英属维尔京群岛 |
| 132 | 约旦 |
| 133 | 越南 |
| 134 | 赞比亚 |
| 135 | 乍得 |
| 136 | 智利 |

View File

@@ -0,0 +1,175 @@
# 附录 - 支付场景编码
使用场景商户入网接口001`business_info.business_open_info.heepay_info.product_info.rate_infos[].rate_code` 字段传入。
---
## 支付场景列表
### 账户类
| 支付场景名称 | 编码 |
|------------|------|
| 个人账户余额 | `PERSON_BALANCE_PAY` |
| 商家余额支付 | `MERCH_BALANCE_PAY` |
| 商家余额代收 | `MERCH_BALANCE_RECEIVE` |
| 个人卡包支付 | `PERSON_CARD_PAY` |
| 商家卡包支付 | `MERCH_CARD_PAY` |
### 银联控件支付
| 支付场景名称 | 编码 |
|------------|------|
| 手机 Wap 借记卡 | `UNIPAY_WAP_DEBIT` |
| 手机 Wap 贷记卡 | `UNIPAY_WAP_CREDIT` |
### 网银支付B2C
| 支付场景名称 | 编码 |
|------------|------|
| 网银支付 | `BANK_ONLINE_B2C` |
| 网银借记卡 | `BANK_ONLINE_DEBIT` |
| 网银贷记卡 | `BANK_ONLINE_CREDIT` |
| 网银支付(通用) | `BANK_ONLINE` |
### 网银支付B2B 企业银行)
| 支付场景名称 | 编码 |
|------------|------|
| 网银支付 B2B通用 | `BANK_ONLINE_B2B` |
| 平安企业银行 | `BANK_ONLINE_SPABANK` |
| 浦发企业银行 | `BANK_ONLINE_SPDB` |
| 建设企业银行 | `BANK_ONLINE_CCB` |
| 农业企业银行 | `BANK_ONLINE_ABC` |
| 邮储企业银行 | `BANK_ONLINE_PSBC` |
| 中行企业银行 | `BANK_ONLINE_BOC` |
| 招商企业银行 | `BANK_ONLINE_CMB` |
| 广发企业银行 | `BANK_ONLINE_GDB` |
| 中信企业银行 | `BANK_ONLINE_CITIC` |
| 民生企业银行 | `BANK_ONLINE_CMBC` |
| 交通企业银行 | `BANK_ONLINE_COMM` |
| 杭州企业银行 | `BANK_ONLINE_HZCB` |
| 宁波企业银行 | `BANK_ONLINE_NBBANK` |
| 光大企业银行 | `BANK_ONLINE_CEB` |
| 北京企业银行 | `BANK_ONLINE_BJBANK` |
| 工商企业银行 | `BANK_ONLINE_ICBC` |
### 支付宝支付
| 支付场景名称 | 编码 |
|------------|------|
| 支付宝条码支付 | `ALI_BARCODE` |
| 支付宝扫码支付 | `ALI_QRCODE` |
| 支付宝 H5 支付 | `ALI_H5` |
| 支付宝公众号 | `ALI_JSAPI` |
| 支付宝小程序 | `ALI_MINI` |
### 微信支付
| 支付场景名称 | 编码 |
|------------|------|
| 微信公众号支付 | `WX_JSAPI` |
| 微信原生扫码支付 | `WX_QRCODE` |
| 微信 APP 支付 | `WX_APP` |
| 微信刷卡支付 | `WX_BARCODE` |
| 微信 H5 支付 | `WX_H5` |
| 微信小程序支付 | `WX_MINI` |
### 快捷支付
| 支付场景名称 | 编码 |
|------------|------|
| 老快捷支付 | `QUICK_PAY_OLD` |
| 新快捷-借(通用) | `QUICK_PAY_DEBIT` |
| 新快捷-贷(通用) | `QUICK_PAY_CREDIT` |
| 新快捷-上海银行-借 | `QUICK_SH_DEBIT` |
| 新快捷-上海银行-贷 | `QUICK_SH_CREDIT` |
| 新快捷-华夏银行-借 | `QUICK_HX_DEBIT` |
| 新快捷-平安银行-借 | `QUICK_PA_DEBIT` |
| 新快捷-浦发银行-借 | `QUICK_PF_DEBIT` |
| 新快捷-建设银行-借 | `QUICK_CCB_DEBIT` |
| 新快捷-建设银行-贷 | `QUICK_CCB_CREDIT` |
| 新快捷-中信银行-借 | `QUICK_CITIC_DEBIT` |
| 新快捷-中信银行-贷 | `QUICK_CITIC_CREDIT` |
| 新快捷-工商银行-借 | `QUICK_ICBC_DEBIT` |
| 新快捷-工商银行-贷 | `QUICK_ICBC_CREDIT` |
| 新快捷-光大银行-借 | `QUICK_GD_DEBIT` |
| 新快捷-光大银行-贷 | `QUICK_GD_CREDIT` |
| 新快捷-民生银行-借 | `QUICK_MS_DEBIT` |
| 新快捷-民生银行-贷 | `QUICK_MS_CREDIT` |
| 新快捷-中国银行-借 | `QUICK_BOC_DEBIT` |
| 新快捷-中国银行-贷 | `QUICK_BOC_CREDIT` |
| 新快捷-邮政银行-借 | `QUICK_PSB_DEBIT` |
| 新快捷-邮政储蓄银行-借 | `QUICK_PS_SB_DEBIT` |
| 新快捷-农业银行-借 | `QUICK_AB_DEBIT` |
| 新快捷-交通银行-借 | `QUICK_BC_DEBIT` |
| 新快捷-交通银行-贷 | `QUICK_BC_CREDIT` |
| 新快捷-浙商银行-借 | `QUICK_ZSB_DEBIT` |
| 新快捷-渤海银行-借 | `QUICK_BANK_BH_DEBIT` |
| 新快捷-恒丰银行-借 | `QUICK_HFBANK_DEBIT` |
| 新快捷-广东发展银行-借 | `QUICK_GDB_DEBIT` |
| 新快捷-苏州银行-借 | `QUICK_SUZHOUBANK_DEBIT` |
| 新快捷-鄞州银行-借 | `QUICK_BEEBANK_DEBIT` |
| 新快捷-贵州银行-借 | `QUICK_GUIZHOUBANK_DEBIT` |
| 新快捷-上海农村商业银行-借 | `QUICK_SRCB_DEBIT` |
| 新快捷-北京农商银行-借 | `QUICK_BJRCBANK_DEBIT` |
| 新快捷-天津农商银行-借 | `QUICK_TRCBANK_DEBIT` |
| 新快捷-成都农商银行-借 | `QUICK_CDRCBANK_DEBIT` |
| 新快捷-深圳农村商业银行-借 | `QUICK_SZNCSYBANK_DEBIT` |
| 新快捷-重庆农村商业银行-借 | `QUICK_RCB_CQ_DEBIT` |
| 新快捷-武汉农村商业银行-借 | `QUICK_WHRCBANK_DEBIT` |
| 新快捷-广东南海农村商业银行-借 | `QUICK_RCB_GD_SOUTH_SEA_DEBIT` |
| 新快捷-四川省农村信用社-借 | `QUICK_RCC_SC_DEBIT` |
| 新快捷-河南省农村信用社-借 | `QUICK_RCC_HN_DEBIT` |
| 新快捷-广西农村信用社-借 | `QUICK_RCC_GX_DEBIT` |
| 新快捷-甘肃省农村信用社-借 | `QUICK_RCC_GXS_DEBIT` |
| 新快捷-山西省农村信用社-借 | `QUICK_RCC_SX_DEBIT` |
| 新快捷-陕西省农村信用社-借 | `QUICK_SXNXSBANK_DEBIT` |
| 新快捷-河北省农村信用社-借 | `QUICK_HEBNXBANK_DEBIT` |
| 新快捷-内蒙古自治区农村信用社-借 | `QUICK_NMGNXSBANK_DEBIT` |
| 新快捷-青海省农村信用社联合社-借 | `QUICK_QINGHAIRCBANK_DEBIT` |
| 新快捷-黑龙江省农村信用社-借 | `QUICK_HLJRCCBANK_DEBIT` |
| 新快捷-辽宁省农村信用社-借 | `QUICK_LNRCCBANK_DEBIT` |
| 新快捷-云南省农村信用社联合社-借 | `QUICK_RCC_YN_DEBIT` |
| 新快捷-湖南省农村信用社-借 | `QUICK_RCC_HUNS_DEBIT` |
| 新快捷-海南省农村信用社-借 | `QUICK_RCC_HNS_DEBIT` |
| 新快捷-安徽省农村信用社联合社-借 | `QUICK_RCC_AH_DEBIT` |
| 新快捷-吉林农村信用社-借 | `QUICK_RCC_JL_DEBIT` |
### 银联扫码支付
| 支付场景名称 | 编码 |
|------------|------|
| 银行卡扫码支付小额-借 | `BANK_QRCODE_SMALL_DEBIT` |
| 银行卡扫码支付小额-贷 | `BANK_QRCODE_SMALL_CREDIT` |
| 银行卡扫码支付大额-借 | `BANK_QRCODE_LARGE_DEBIT` |
| 银行卡扫码支付大额-贷 | `BANK_QRCODE_LARGE_CREDIT` |
### 银联全渠道
| 支付场景名称 | 编码 |
|------------|------|
| 银联全渠道 APP-借 | `UNIPAY_APP_DEBIT` |
| 银联全渠道 APP-贷 | `UNIPAY_APP_CREDIT` |
| 银联全渠道 H5-借 | `UNIPAY_H5_DEBIT` |
| 银联全渠道 H5-贷 | `UNIPAY_H5_CREDIT` |
---
## 费率参数示例
`rate_infos` 方式(标准结构):
```json
{
"product_info": {
"rate_infos": [
{ "rate_code": "WX_JSAPI", "rate_type": "SINGLE_PERCENT", "rate": "0.006" },
{ "rate_code": "WX_QRCODE", "rate_type": "SINGLE_PERCENT", "rate": "0.006" },
{ "rate_code": "WX_MINI", "rate_type": "SINGLE_PERCENT", "rate": "0.006" }
]
}
}
```
> 注意:文档中也出现了另一种简写格式 `"rate": {"WX_JSAPI": 0.006, ...}`,以实际联调结果为准,建议优先使用标准 `rate_infos` 数组结构。

1140
docs/tech-design.md Normal file

File diff suppressed because it is too large Load Diff