M Merchant APIDocs
Markdown AI 提示词

Merchant OpenAPI

支付接入

用官方 SDK 接入代收与代付:baseUrl 统一走 <BASE_URL>/v1。签名、验签与双环境已内置。

POST /api/open/v1/merchant/pay/create

SDK 快速开始

先安装对应语言依赖,再复制示例并替换占位符。

安装依赖

npm install @bebebus/merchant-openapi-sdk
// Base URL 用商户后台给出的地址拼上 /v1。
import { Client, Config } from '@bebebus/merchant-openapi-sdk';

const client = new Client(new Config({
  merchantNo: '<YOUR_MERCHANT_NO>',
  apiKey: '<YOUR_API_KEY>',
  apiSecretPay: '<YOUR_API_SECRET_PAY>',
  baseUrl: '<BASE_URL>/v1',
}));

const { data } = await client.payCreate({
  out_order_no: 'order-001',
  amount: 10000,
  currency: 'PHP',
  pay_method: 'gcash',
  country: 'PH',
  notify_url: 'https://merchant.example.com/api/notify/pay',
});
console.log(data.order_no, data.pay_url);
  • Base URL:请登录商户后台「安全中心 · OpenAPI」获取(本文以 <BASE_URL> 占位,不含版本号)。版本写在功能路径中:<BASE_URL>/v1/...
  • 接口版本:v1(服务端版本 1.2.0;每次响应都带 X-Api-Version 头)
  • 导出日期:20260818

注意:本文档不包含商户真实凭据与白名单信息,请使用占位符替换后对接。

商户信息

  • 商户名称:<YOUR_MERCHANT_NAME>
  • 商户号:<YOUR_MERCHANT_NO>

官方 SDK

提供 5 种语言的官方 SDK:零第三方依赖(仅用各语言标准库),内置 HMAC-SHA256 请求签名 / 回调验签、测试与正式双环境,baseUrl 统一指向 <BASE_URL>/v1

语言 安装 / 引入 包索引 / 源码
Node.js npm install @bebebus/merchant-openapi-sdk npm
Python pip install bebebus-merchant-openapi-sdk PyPI
PHP composer require bebebus/merchant-openapi-sdk Packagist
Go go get github.com/bebebus/SDK/go pkg.go.dev
Java 源码引入(包 cloud.cniia.openapi.sdk,未发 Maven) GitHub
  • 仓库与发布说明:https://github.com/bebebus/SDK (签名算法权威说明见仓库 SIGNING.md,端点字段级请求/响应见 INTERFACES.md)。
  • 新对接请把 baseUrl 指到 <BASE_URL>/v1,并使用官方 SDK。代收/代付下单均只传 pay_method(不使用 channel_code)。

附录配置文件

可直接查看或下载各语言配置模板(占位符,填入商户后台凭据后使用)。Node.js / Java 为 JSON,PHP 为 return [...] 数组,Python 为 dict,Go 为 package 变量。

文件 查看 下载
Node.js 配置(JSON) 查看 下载
PHP 配置(数组) 查看 下载
Python 配置(dict) 查看 下载
Go 配置 查看 下载
Java 配置(JSON) 查看 下载

SDK 快速开始

下面以官方 SDK 演示代收下单。pay_method 指定支付方式;金额为实际金额 × 10000 的整数。把占位符换成商户后台的凭据与 Base URL。

Node.js

安装依赖:

npm install @bebebus/merchant-openapi-sdk
// Base URL 用商户后台给出的地址拼上 /v1。
import { Client, Config } from '@bebebus/merchant-openapi-sdk';

const client = new Client(new Config({
  merchantNo: '<YOUR_MERCHANT_NO>',
  apiKey: '<YOUR_API_KEY>',
  apiSecretPay: '<YOUR_API_SECRET_PAY>',
  baseUrl: '<BASE_URL>/v1',
}));

const { data } = await client.payCreate({
  out_order_no: 'order-001',
  amount: 10000,
  currency: 'PHP',
  pay_method: 'gcash',
  country: 'PH',
  notify_url: 'https://merchant.example.com/api/notify/pay',
});
console.log(data.order_no, data.pay_url);

Python

安装依赖:

pip install bebebus-merchant-openapi-sdk
# Base URL 用商户后台给出的地址拼上 /v1。
from openapi_sdk import Client, Config

client = Client(Config(
    merchant_no="<YOUR_MERCHANT_NO>",
    api_key="<YOUR_API_KEY>",
    api_secret_pay="<YOUR_API_SECRET_PAY>",
    base_url="<BASE_URL>/v1",
))

data = client.pay_create(
    out_order_no="order-001",
    amount=10000,
    currency="PHP",
    pay_method="gcash",
    notify_url="https://merchant.example.com/api/notify/pay",
    country="PH",
)
print(data["order_no"], data.get("pay_url"))

PHP

安装依赖:

composer require bebebus/merchant-openapi-sdk
<?php
// Base URL 用商户后台给出的地址拼上 /v1。
use Merchant\Openapi\Client;
use Merchant\Openapi\Config;

$client = new Client(new Config(
    merchantNo: '<YOUR_MERCHANT_NO>',
    apiKey: '<YOUR_API_KEY>',
    apiSecretPay: '<YOUR_API_SECRET_PAY>',
    apiSecretPayout: '<YOUR_API_SECRET_PAYOUT>',
    baseUrl: '<BASE_URL>/v1',
));

$data = $client->payCreate([
    'out_order_no' => 'order-001',
    'amount' => 10000,
    'currency' => 'PHP',
    'pay_method' => 'gcash',
    'country' => 'PH',
    'notify_url' => 'https://merchant.example.com/api/notify/pay',
]);
echo $data['order_no'];

Go

安装依赖:

go get github.com/bebebus/SDK/go
// Base URL 用商户后台给出的地址拼上 /v1。
package main

import (
	"context"
	"fmt"

	"github.com/bebebus/SDK/go"
)

func main() {
	client := openapi.NewClient(openapi.Config{
		MerchantNo: "<YOUR_MERCHANT_NO>",
		APIKey:     "<YOUR_API_KEY>",
		SecretPay:  "<YOUR_API_SECRET_PAY>",
		BaseURL:    "<BASE_URL>/v1",
	})
	resp, err := client.PayCreate(context.Background(), map[string]any{
		"out_order_no": "order-001",
		"amount":       10000,
		"currency":     "PHP",
		"pay_method":   "gcash",
		"country":      "PH",
		"notify_url":   "https://merchant.example.com/api/notify/pay",
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(resp.Data["order_no"], resp.Data["pay_url"])
}

Java

安装依赖:

# 未发 Maven。把官方仓库 java/src/main/java/cloud/cniia/openapi/sdk 加入工程编译源
javac --release 17 -encoding UTF-8 -d out $(find src/main/java -name '*.java')
// Base URL 用商户后台给出的地址拼上 /v1。
import cloud.cniia.openapi.sdk.Client;
import cloud.cniia.openapi.sdk.Config;
import java.util.LinkedHashMap;
import java.util.Map;

Config config = Config.builder()
        .merchantNo("<YOUR_MERCHANT_NO>")
        .apiKey("<YOUR_API_KEY>")
        .apiSecretPay("<YOUR_API_SECRET_PAY>")
        .baseUrl("<BASE_URL>/v1")
        .build();
Client client = new Client(config);

Map<String, Object> params = new LinkedHashMap<>();
params.put("out_order_no", "order-001");
params.put("amount", 10000L);
params.put("currency", "PHP");
params.put("pay_method", "gcash");
params.put("country", "PH");
params.put("notify_url", "https://merchant.example.com/api/notify/pay");
Map<String, Object> data = client.payCreate(params).dataAsMap();
System.out.println(data.get("order_no") + " " + data.get("pay_url"));

代收:创建订单(pay/create)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/pay/create
  • 用途:创建代收订单,返回接口订单号与支付链接/二维码内容。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign、out_order_no、amount、currency、pay_method、notify_url
  • 可选字段:nonce、country、return_url、subject、remark、client_ip、extra
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(从商户后台获取)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
out_order_no string 商户订单号(同一商户全局唯一;重复提交一律拒绝,不返回原单)
amount int 订单金额(= 实际金额 × 10000 的整数,例如 1.2345 传 12345)。必须是 JSON 数字正整数,不接受字符串(如 "12345")或小数;非法返回 code=100001(HTTP 200,message 为具体字段校验错误信息)。
currency string 币种(如 PHP/USDT;用于校验与路由)
pay_method string 支付方式(从支付方式字典中选择,如 gcash/maya;加密货币使用链名如 trc20/erc20)
country string|null 国家 ISO 码(如 PH;法币必填,加密货币可省略)
notify_url string 回调地址(订单进入终态后,接口会向该地址发送结果)
return_url string|null 前端回跳地址(支付完成后跳回商户页面;是否跳转取决于支付方式/场景)
subject string|null 订单标题(可用于展示或对账说明)
remark string|null 备注(可用于商户自定义说明/对账)
client_ip string|null 终端用户 IP(可用于风控;不传则接口无法获取该信息)
extra object|null 扩展字段(顶层字段,参与签名;object 会按稳定 JSON 序列化)。⚠️ 强烈建议携带下单用户个人信息 extra.customer(见下方"扩展信息与渠道要求"说明)
extra.customer object 下单用户信息(选填)。未提供时,接口不会仅因缺少该字段返回 300405;但部分支付方式要求 name/phone,缺失可能导致订单失败,建议提供。提供后接口会校验格式并转换字段(整名 name 会拆分为 first/last):可填 name 整名(或 first_name+last_name)、email、phone
sign string 签名(按文档规则计算;pay 接口使用 api_secret_pay)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "out_order_no": "202501010001",
  "amount": 10000,
  "currency": "PHP",
  "pay_method": "gcash",
  "country": "PH",
  "notify_url": "https://merchant.example.com/api/notify/pay",
  "return_url": "https://merchant.example.com/pay/result",
  "subject": "订单标题(可选)",
  "remark": "备注(可选)",
  "client_ip": "1.2.3.4",
  "extra": {
    "user_id": "u123456",
    "customer": {
      "first_name": "San",
      "last_name": "Zhang",
      "email": "[email protected]",
      "phone": "13800000000"
    }
  }
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
order_no string 接口订单号(用于后续查询与对账)
out_order_no string 商户订单号(原样回传,便于商户侧关联业务订单)
amount int 订单金额(= 实际金额 × 10000 的整数,例如 12345 表示 1.2345)
currency string 币种(原样回传请求币种,如 PHP/USDT)
pay_url string|null 支付链接(下单成功 code=0 时,pay_url/qrcode_content/pay_params 至少一项非空;本字段可能为空,此时用其余字段唤起支付)
qrcode_content string|null 二维码内容(下单成功 code=0 时,pay_url/qrcode_content/pay_params 至少一项非空;本字段可能为空)
pay_params string|null 支付原生串(可选):部分支付方式返回 App 原生唤端参数;pay_url 为空而本字段非空时,请用它在客户端唤起支付
expire_at string|null 过期时间(ISO8601;可空)。超时未支付不再单独表示为 expired 状态,对外统一归一为 pending(处理中),请以查单结果为准。
status string 订单状态:pending(处理中)/success(成功)/failed(失败)。仅 success/failed 为终态;超时未支付不再单独返回 expired,统一归一为 pending。

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "order_no": "P20250101000001",
    "out_order_no": "202501010001",
    "amount": 10000,
    "currency": "PHP",
    "pay_url": "https://pay.example.com/h5/P20250101000001",
    "qrcode_content": "https://pay.example.com/h5/P20250101000001",
    "pay_params": null,
    "expire_at": "2025-01-01T12:30:00Z",
    "status": "pending"
  }
}

补充说明

  • 金额 = 实际金额 × 10000 的整数,例如 1.2345 传 12345,以整数传输避免浮点误差。
  • 同一商户的 out_order_no 重复提交一律拒绝(无论参数是否相同,均不返回原单):请求超时/结果未知时先用 pay/query 查单确认,需要重下则更换新 out_order_no。
  • 【用户信息(强烈建议必传)】部分支付方式要求终端用户姓名/手机(email 可能选填),缺失可能导致订单失败。请使用通用字段提供:姓名——extra.customer.name 整名(也可显式 extra.customer.first_name+last_name);邮箱——extra.customer.email(或 extra.email);手机——extra.customer.phone(或 extra.phone)。提供后接口会统一校验并转换字段,商户无需为不同支付方式分别适配。
  • 【支付原生串】pay_url 为空而 pay_params 非空时(部分支付方式仅返回原生唤端参数),请在客户端用 pay_params 唤起支付。

常见错误

  • 100101 请求过期
  • 100102 IP 不在白名单
  • 100104 签名错误
  • 100105 IP 在黑名单
  • 100000 创建订单失败(订单未被受理,已实时置 failed)
  • 300101 商户订单号已存在,请查单或更换 out_order_no
  • 300404 当前条件下无可用支付方式
  • 100001 参数校验失败(如 notify_url 指向内网/非法协议)
  • 300402 支付方式配置不可用
  • 300403 费率未配置

代收:查询订单(pay/query)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/pay/query
  • 用途:按接口订单号或商户订单号查询代收订单状态。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign、order_no/out_order_no(二选一)
  • 可选字段:nonce
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(从商户后台获取)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
order_no string|null 接口订单号(与 out_order_no 二选一,至少提供一个)
out_order_no string|null 商户订单号(与 order_no 二选一,至少提供一个)
sign string 签名(按文档规则计算;pay 接口使用 api_secret_pay)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "out_order_no": "202501010001",
  "order_no": null
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
order_no string 接口订单号
out_order_no string 商户订单号
amount int 下单参考金额(= 实际金额 × 10000 的整数);仅参考,入账以 actual_amount 为准
actual_amount int|null 用户实际支付金额(代收入账与对账的主依据,请优先使用;未知时为 null)
fee_amount int|null 手续费(按实付重算;未知时为 null)
net_amount int|null 净入账额 = 实付 − 手续费(未知时为 null)
currency string 币种
status string 订单状态:pending(处理中)/success(成功)/failed(失败)。仅 success/failed 为终态;超时未支付不再单独返回 expired,统一归一为 pending。
channel_order_no null 始终返回 null。订单查询和业务关联请使用 order_no 或 out_order_no。
paid_at string|null 支付成功时间(ISO8601;未成功时可能为空)
notify_status string 回调发送状态:pending/success/failed(不等同于支付结果)

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "order_no": "P20250101000001",
    "out_order_no": "202501010001",
    "amount": 10000,
    "actual_amount": 9500,
    "fee_amount": 500,
    "net_amount": 9000,
    "currency": "USDT",
    "status": "success",
    "channel_order_no": null,
    "paid_at": "2025-01-01T12:15:00Z",
    "notify_status": "success"
  }
}

补充说明

  • order_no/out_order_no 至少提供一个。
  • status 终态为 success/failed;pending 表示处理中(含超时未支付,已统一归一为 pending)。
  • 代收仅在订单成功(success)时回调商户;失败/超时等非成功状态不回调,商户应通过本查单接口获知最终结果。

常见错误

  • 100104 签名错误
  • 300301 订单不存在

代付:创建订单(payout/create)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/payout/create
  • 用途:创建代付订单并冻结余额(创建成功不代表最终出款成功)。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign、out_payout_no、amount、currency、pay_method、notify_url、account_no
  • 可选字段:nonce、country、account_name、bank_name、bank_code、remark、client_ip、extra
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(从商户后台获取)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
out_payout_no string 商户代付单号(同一商户全局唯一;重复提交一律拒绝,不返回原单)
amount int 代付金额(= 实际金额 × 10000 的整数,例如 1.2345 传 12345)。必须是 JSON 数字正整数,不接受字符串(如 "12345")或小数;非法返回 code=100001(HTTP 200,message 为具体字段校验错误信息)。
currency string 币种(如 PHP/USDT;用于校验与路由)
pay_method string 支付方式(从支付方式字典中选择,如 gcash/maya;加密货币使用链名如 trc20/erc20)。代付不使用 channel_code/分组编码。
country string|null 国家 ISO 码(如 PH;法币必填,加密货币可省略)
notify_url string 回调地址(代付订单进入终态后,接口会向该地址发送结果)
account_name string|null 收款人姓名/账户名(按通道类型解释;链上地址类可空)
account_no string 收款账号/地址(按通道类型解释;例如银行卡号/链上地址)
bank_name string|null 银行/链名称(按通道类型解释;可空)
bank_code string|null 银行编码(对应「查询可用银行」接口返回的 code;无银行选择时可省略;如同时传 bank_name,以 bank_code 解析结果优先)
remark string|null 备注(可用于商户自定义说明/对账)
client_ip string|null 终端用户 IP(可用于风控)
extra object|null 扩展字段(参与签名;object 会按稳定 JSON 序列化)。⚠️ 强烈建议携带下单用户个人信息 extra.customer(见下方"扩展信息与渠道要求"说明)
extra.customer object 下单用户信息(选填)。未提供时,接口不会仅因缺少该字段返回 300405;但部分支付方式要求 name/phone,缺失可能导致订单失败,建议提供。提供后接口会校验格式并转换字段(整名 name 会拆分为 first/last):可填 name 整名(或 first_name+last_name)、email、phone
sign string 签名(按文档规则计算;payout 接口使用 api_secret_payout)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "out_payout_no": "WD202501010001",
  "amount": 5000,
  "currency": "PHP",
  "pay_method": "gcash",
  "country": "PH",
  "notify_url": "https://merchant.example.com/api/notify/payout",
  "account_name": "张三(可选)",
  "account_no": "09171234567",
  "bank_name": "可选:银行卡代付时填银行名(gcash 等钱包类可省略)",
  "client_ip": "1.2.3.4",
  "remark": "商户提现(可选)",
  "extra": {
    "user_id": "u123456",
    "customer": {
      "first_name": "San",
      "last_name": "Zhang",
      "email": "[email protected]",
      "phone": "13800000000"
    }
  }
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
payout_no string 接口代付单号(用于后续查询与对账)
out_payout_no string 商户代付单号(原样回传,便于商户侧关联业务)
amount int 代付金额(= 实际金额 × 10000 的整数,例如 12345 表示 1.2345)
currency string 币种(原样回传请求币种,如 PHP/USDT)
status string 订单状态:创建时为 pending(处理中,代付一律先进入处理流程);success(成功)/failed(失败)为终态。
review_status string|null 出款审批状态(启用商户出款审批时):pending(审批中)/approved(通过)/rejected(驳回);无需审批时为 null。
fee_amount int|null 手续费(可空)
freeze_amount int|null 冻结金额(可空;建议口径 amount + fee_amount)

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "payout_no": "W20250101000001",
    "out_payout_no": "WD202501010001",
    "amount": 5000,
    "currency": "PHP",
    "status": "pending",
    "review_status": "pending",
    "fee_amount": 20,
    "freeze_amount": 5020
  }
}

补充说明

  • 创建成功表示"已受理并冻结余额"。代付通常需要审核/下发等流程,最终结果以异步通知与查询为准。
  • 同一商户的 out_payout_no 全局唯一;重复提交一律拒绝(无论参数是否相同,均不返回原单):结果未知时先用 payout/query 查单确认,需要重下则更换新单号。
  • 【用户信息(强烈建议必传)】部分支付方式要求终端用户姓名/手机(email 可能选填),缺失可能导致订单失败。请使用通用字段提供:代付可使用 account_name(收款人/账户名),或使用 extra.customer.name 整名(也可显式 extra.customer.first_name+last_name);邮箱——extra.customer.email(或 extra.email);手机——extra.customer.phone(或 extra.phone)。提供后接口会统一校验并转换字段,商户无需为不同支付方式分别适配。
  • 【银行类代付】pay_method 为银行类时 bank_code 必传,取值用「查询可用银行(payout/banks/query)」接口返回的 code;编码非法返回 300407。

常见错误

  • 100104 签名错误
  • 300201 商户代付单号已存在,请查单或更换 out_payout_no
  • 300501 余额不足
  • 300404 当前条件下无可用支付方式
  • 300403 费率未配置
  • 300401 支付方式不可用/不存在
  • 100001 参数校验失败(如 notify_url 指向内网/非法协议)
  • 300402 支付方式配置不可用
  • 300406 缺少必要下单参数(如 bank_code)
  • 300407 银行编码非法

代付:查询订单(payout/query)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/payout/query
  • 用途:按接口代付单号或商户代付单号查询代付订单状态。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign、payout_no/out_payout_no(二选一)
  • 可选字段:nonce
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(从商户后台获取)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
payout_no string|null 接口代付单号(与 out_payout_no 二选一,至少提供一个)
out_payout_no string|null 商户代付单号(与 payout_no 二选一,至少提供一个)
sign string 签名(按文档规则计算;payout 接口使用 api_secret_payout)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "payout_no": null,
  "out_payout_no": "WD202501010001"
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
payout_no string 接口代付单号
out_payout_no string 商户代付单号
amount int 代付金额(= 实际金额 × 10000 的整数,例如 12345 表示 1.2345)
currency string 币种
status string 订单状态:pending(处理中)/success(成功)/failed(失败),仅 success/failed 为终态。
sub_state string|null 处理中子态(归一化):accepted 已受理 / reviewing 审核中 / processing 出款处理中 / verifying 出款结果核实中(非终态,请继续等待回调或轮询);终态时为 null
channel_order_no null 始终返回 null。订单查询和业务关联请使用 payout_no 或 out_payout_no。
finished_at string|null 完成时间(ISO8601;未终态时可能为空)
failed_reason string|null 失败原因:仅 failed 时返回;经平台策略确认安全的业务失败返回上游业务原文,其余返回通用文案
notify_status string 回调发送状态:pending/success/failed(不等同于代付结果)

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "payout_no": "W20250101000001",
    "out_payout_no": "WD202501010001",
    "amount": 5000,
    "currency": "USDT",
    "status": "success",
    "sub_state": null,
    "channel_order_no": null,
    "finished_at": "2025-01-01T13:00:00Z",
    "failed_reason": null,
    "notify_status": "success"
  }
}

补充说明

  • payout_no/out_payout_no 至少提供一个。
  • status 终态为 success/failed;pending 表示处理中(请继续等待回调或轮询查单)。
  • sub_state 是处理中状态的归一化细分(verifying 表示出款结果核实中,仍是非终态);sub_state 仅用于展示/排查,业务判断以 status 终态(success/failed)为准。

常见错误

  • 100104 签名错误
  • 300301 订单不存在

代付:查询可用银行(payout/banks/query)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/payout/banks/query
  • 用途:按国家 + 币种 + 支付能力查询当前可用的银行列表(银行类代付下单 bank_code 的合法取值)。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign、pay_method、country、currency
  • 可选字段:nonce
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(从商户后台获取)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
pay_method string 支付能力(与 payout/create 中表示支付分组的 pay_method 含义不同;查询可用银行时通常固定传 bank)
country string 国家 ISO 码(如 PH)
currency string 币种(如 PHP)
sign string 签名(按文档规则计算;payout 接口使用 api_secret_payout)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "pay_method": "gcash",
  "country": "PH",
  "currency": "PHP"
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
banks array 可用银行列表 [{code,name}];code 即代付下单 bank_code 的合法取值。

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "banks": [
      {
        "code": "BDO",
        "name": "BDO Unibank"
      },
      {
        "code": "BPI",
        "name": "Bank of the Philippine Islands"
      },
      {
        "code": "GCASH",
        "name": "GCash"
      },
      {
        "code": "MAYA",
        "name": "Maya"
      }
    ]
  }
}

补充说明

  • 可用银行列表可能动态变化,建议下单前实时查询(或做短期缓存)。
  • 查询银行列表时支付能力通常固定为 pay_method=bank;返回的 banks 可能含电子钱包(如 GCASH/MAYA)作为代付目的地,bank_code 可传其 code。

常见错误

  • 100104 签名错误

代付:查询付款凭证(payout/proof/query)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/payout/proof/query
  • 用途:查询已成功代付订单的付款凭证地址(并非所有支付方式/币种都提供凭证)。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign、payout_no/out_payout_no(二选一)
  • 可选字段:nonce
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(从商户后台获取)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
payout_no string|null 接口代付单号(与 out_payout_no 二选一,至少提供一个)
out_payout_no string|null 商户代付单号(与 payout_no 二选一,至少提供一个)
sign string 签名(按文档规则计算;payout 接口使用 api_secret_payout)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "payout_no": null,
  "out_payout_no": "WD202501010001"
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
payout_no string 接口代付单号
out_payout_no string 商户代付单号
proof_url string 付款凭证地址(有访问时效,见 expires_in;请即取即用,勿持久化该 URL)
expires_in int|null 凭证地址有效期(秒,由渠道决定,如 1800=30 分钟;null 表示渠道未声明)
queried_at string|null 接口返回的查询时间(可空;格式可能不是 ISO8601)

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "payout_no": "W20250101000001",
    "out_payout_no": "WD202501010001",
    "proof_url": "https://proof.example.com/xxx.pdf",
    "expires_in": 1800,
    "queried_at": "2025-01-01 13:00:00"
  }
}

补充说明

  • 仅出款成功(status=success)的订单可查凭证;处理中/失败订单返回 300409。
  • 【测试密钥不支持】用测试环境密钥(env=test)调用本接口一律返回 300408:测试代付不提供付款凭证(不查订单、不回源上游)。
  • 并非所有渠道/币种都提供凭证;部分渠道仅支持查询近几天内的订单(超窗返回 300409)。
  • 凭证 URL 有访问时效(expires_in 秒),请下载转存而非保存 URL。

常见错误

  • 100104 签名错误
  • 300301 订单不存在
  • 300408 渠道不支持凭证查询 / 测试密钥不支持凭证
  • 300409 凭证暂不可用

代付:查询付款收据图片(payout/receipt/query)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/payout/receipt/query
  • 用途:查询/生成代付订单的付款收据图片(PNG)。仅 status=success 的代付单可生成;render-once 落盘复用。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign、payout_no/out_payout_no(二选一)
  • 可选字段:nonce、lang、inline
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(从商户后台获取)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
payout_no string|null 接口代付单号(与 out_payout_no 二选一,至少提供一个)
out_payout_no string|null 商户代付单号(与 payout_no 二选一,至少提供一个)
lang string|null 收据语言(可选,枚举:en / zh-CN / zh-TW;不传时按订单国家自动派生)
inline int|null 传 1 时直接返回 base64 图片数据(image_base64 + mime);不传或传 0 时返回带时效签名的下载链接(receipt_url)
sign string 签名(按文档规则计算;payout 接口使用 api_secret_payout)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "payout_no": null,
  "out_payout_no": "WD202501010001",
  "lang": "zh-CN",
  "inline": 0
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
payout_no string 接口代付单号
out_payout_no string 商户代付单号
lang string 收据实际使用的语言(en / zh-CN / zh-TW)
receipt_url string|null 收据图片下载地址(站点根相对路径,如 /api/open/v1/payout/receipt/file?token=…)。请用域名 origin 解析,例如 new URL(receipt_url, 'https://example.com');不要拼到已含 /api/open/v1 的 Base URL 后面。GET 即可下载;仅 inline=0 或未传时返回;链接带时效,请即取即用。
expires_in int|null 下载链接有效期(秒,如 3600=1 小时;null 表示未声明有效期);仅 inline=0 或未传时有意义
mime string|null 图片 MIME 类型(如 image/png);仅 inline=1 时返回
image_base64 string|null 收据图片 Base64 编码数据(不含 data URI 前缀);仅 inline=1 时返回

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "payout_no": "W20250101000001",
    "out_payout_no": "WD202501010001",
    "lang": "zh-CN",
    "receipt_url": "/api/open/v1/payout/receipt/file?token=eyJhbGciOiJIUzI1NiJ9...",
    "expires_in": 3600
  }
}

补充说明

  • 仅出款成功(status=success)的代付单可生成收据;非 success 状态返回 300410。
  • 【测试密钥不支持】用测试环境密钥(env=test)调用本接口一律返回 300410:测试代付不提供收据(不查订单、不生成图片、不签发下载令牌)。
  • render-once:首次生成后图片落盘复用,相同参数重复查询直接返回缓存结果。
  • lang 不传时接口按订单国家自动选择语言(如 PH → en);显式指定可覆盖。
  • inline=1 时响应体直接含 Base64 图片(image_base64 + mime),适合服务端即时处理;inline=0(默认)时返回带时效签名的 receipt_url 下载链接,适合前端跳转/嵌入。
  • 下载链接有时效(expires_in 秒),请勿持久化 URL;需长期保存请下载图片转存至自有存储。
  • receipt_url 是站点根相对路径,请用域名 origin 解析,不要拼到 OpenAPI Base URL 后面。

常见错误

  • 100104 签名错误
  • 300301 订单不存在
  • 300410 代付收据暂不可用(订单非 success / 测试密钥不支持收据)
  • 300411 收据生成失败

通用:查询可用支付方式(pay-methods/query)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/pay-methods/query
  • 用途:查询可用支付方式字典(下单 pay_method/country 的合法取值)。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign
  • 可选字段:nonce、country
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(从商户后台获取)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
country string|null 国家 ISO 码(如 PH;不传返回全部)
sign string 签名(按文档规则计算;本接口使用 api_secret_pay)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "country": "PH"
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
methods array 支付方式列表 [{pay_method,name,country,currency}];pay_method 即下单接口的合法取值

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "methods": [
      {
        "pay_method": "gcash",
        "name": "GCash",
        "country": "PH",
        "currency": "PHP"
      },
      {
        "pay_method": "maya",
        "name": "Maya",
        "country": "PH",
        "currency": "PHP"
      }
    ]
  }
}

补充说明

  • 返回的是当前可用支付方式字典;某支付方式当前是否可下单以创建订单接口的实际返回为准(无可用支付方式时报 300404)。

常见错误

  • 100104 签名错误

通用:查询账户余额(balance/query)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/balance/query
  • 用途:查询商户交易账户各币种的可用/冻结余额。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign
  • 可选字段:nonce、currency
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(从商户后台获取)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
currency string|null 币种(如 PHP;不传返回全部币种)
sign string 签名(按文档规则计算;本接口使用 api_secret_pay)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "currency": "PHP"
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
balances array 余额列表 [{currency,available,frozen}];金额 = 实际金额 × 10000 的整数

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "balances": [
      {
        "currency": "PHP",
        "available": 12345600,
        "frozen": 50000
      }
    ]
  }
}

补充说明

  • available 为可用余额,frozen 为冻结金额(含在途代付冻结);均为最小单位整数。

常见错误

  • 100104 签名错误

通用:服务版本(GET /version)

  • 方法:GET
  • 接口:<BASE_URL>/v1/version
  • 用途:查询服务端 OpenAPI 版本(无需鉴权);所有 /api/open/ 响应均带 X-Api-Version 头。

请求说明

  • Content-Type:application/json
  • 必填字段:无
  • 可选字段:无

请求示例

{}

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
major string 大版本(路径前缀,如 v1)
version string 语义化版本(major.minor.patch)
base_path string OpenAPI 路径前缀

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "major": "v1",
    "version": "1.2.0",
    "base_path": "/api/open/v1"
  }
}

补充说明

  • 无需鉴权;用于探活与版本灰度排查。

代付:下载付款回单文件(GET /payout/receipt/file)

  • 方法:GET
  • 接口:<BASE_URL>/v1/payout/receipt/file
  • 用途:下载代付付款回单图片(二进制 PNG)。本端点不直接调用,而是由「查询付款收据图片(payout/receipt/query)」返回的 receipt_url 派生;receipt_url 是站点根相对路径,请用域名 origin 解析后 GET,不要拼到 OpenAPI Base URL 后面。

请求说明

  • Content-Type:application/json
  • 必填字段:token
  • 可选字段:无
字段 类型 必填 说明
token string 下载令牌(query 参数)。由 payout/receipt/query(inline=0/未传时返回的 receipt_url)签发,内含代付单号/商户/语言/有效期,带时效;请勿自行构造或长期持久化。

请求示例

{}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。

返回示例

{}

补充说明

  • 本端点返回的是二进制图片Content-Type: image/pngcontent-disposition: inline),而非 {code,message,data} JSON 信封;下载成功直接得到 PNG 字节流。
  • 调用方式:先用「查询付款收据图片(payout/receipt/query)」(inline=0 或不传)拿到 receipt_url(形如 /api/open/v1/payout/receipt/file?token=…)。它是站点根相对路径,请用域名 origin 解析(new URL(receipt_url, 'https://example.com')),不要拼到已含 /api/open/v1 的 Base URL 后面。
  • 官方 SDK 不封装本端点:receipt_url 是带时效签名的下载链接,请用任意 HTTP 客户端自行 GET(无需再签名/验签);链接过期(token 失效)会返回 100001,重新调用 payout/receipt/query 取新链接即可。
  • 鉴权方式与其它接口不同:本端点不走 merchant_no/api_key/sign 鉴权,仅凭 query 中的 token 鉴权(HMAC 签发),故无需也不应附带签名字段。

常见错误

  • 100001 token 非法或已过期(重新调用 payout/receipt/query 取新链接)
  • 300410 代付收据暂不可用(订单非 success)

测试沙箱:手动完成代收测试单(pay/test/complete)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/pay/test/complete
  • 用途:【仅测试密钥】把一笔测试代收单手动推到终态(success/failed),用于无真实支付流程的对接联调;正式密钥调用被拒。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign、out_order_no/order_no(二选一)、result
  • 可选字段:nonce、actual_amount
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(必须为测试环境的密钥;正式密钥调用会被拒)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
out_order_no string|null 商户订单号(与 order_no 二选一,至少提供一个)
order_no string|null 接口订单号(与 out_order_no 二选一,至少提供一个)
result string 期望终态:success(成功)或 failed(失败)
actual_amount int|null 用户实付金额(= 实际金额 × 10000 的整数,可选;仅 result=success 时生效,不传则按订单 amount;result=failed 时忽略)
sign string 签名(按文档规则计算;本接口使用 api_secret_pay 测试密钥)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "out_order_no": "202501010001",
  "order_no": null,
  "result": "success",
  "actual_amount": 10000
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
ok bool 是否处理成功(恒为 true,失败由 code 表达)
order_no string 接口订单号
status string 推送后的订单终态:success/failed

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "ok": true,
    "order_no": "P20250101000001",
    "status": "success"
  }
}

补充说明

  • 【仅测试密钥】只有测试环境密钥(env=test)可调用;正式密钥调用返回 100001(仅测试密钥可调用测试完成端点)。
  • 仅可作用于测试订单:用测试密钥创建的订单与正式订单物理隔离(独立测试存储),走 mock、不动真钱、不计统计。对非测试订单、不存在的单或已终态的单调用,返回 100001(订单不存在 / 非测试订单不可手动完成 / 订单已是终态)。
  • 置为 success 后会照常入队并投递商户回调(沙箱「回调照发」),可用于联调回调验签与入账逻辑;推送结果同样可经 pay/query 查询。

常见错误

  • 100104 签名错误
  • 100001 仅测试密钥可调用 / 订单不存在 / 非测试订单 / 订单已是终态(message 为具体原因)

测试沙箱:手动完成代付测试单(payout/test/complete)

  • 方法:POST
  • 接口:<BASE_URL>/v1/merchant/payout/test/complete
  • 用途:【仅测试密钥】把一笔测试代付单手动推到终态(success/failed),用于无真实支付流程的对接联调;正式密钥调用被拒。

请求说明

  • Content-Type:application/json
  • 必填字段:merchant_no、api_key、timestamp、sign、out_payout_no/payout_no(二选一)、result
  • 可选字段:nonce
字段 类型 必填 说明
merchant_no string 商户号(从商户后台获取)
api_key string API Key(必须为测试环境的密钥;正式密钥调用会被拒)
timestamp int Unix 时间戳(秒),用于过期校验(建议 ±300 秒窗口)
nonce string|null 防重放随机串;不使用时建议省略或传 null(不要传空字符串)
out_payout_no string|null 商户代付单号(与 payout_no 二选一,至少提供一个)
payout_no string|null 接口代付单号(与 out_payout_no 二选一,至少提供一个)
result string 期望终态:success(成功)或 failed(失败)
sign string 签名(按文档规则计算;本接口使用 api_secret_payout 测试密钥)

请求示例

{
  "merchant_no": "<YOUR_MERCHANT_NO>",
  "api_key": "<YOUR_API_KEY>",
  "timestamp": 1736073600,
  "nonce": "random-xyz",
  "sign": "<SIGN>",
  "out_payout_no": "WD202501010001",
  "payout_no": null,
  "result": "success"
}

签名说明:sign 需对"请求 JSON 顶层除 sign 以外的所有字段"参与计算;object/array 字段会按稳定 JSON 序列化。

返回字段与示例

  • 统一返回结构:{ code, message, data };业务失败通常仍为 HTTP 200。
字段 类型 必填 说明
ok bool 是否处理成功(恒为 true,失败由 code 表达)
payout_no string 接口代付单号
status string 推送后的代付终态:success/failed

返回示例

{
  "code": 0,
  "message": "ok",
  "data": {
    "ok": true,
    "payout_no": "W20250101000001",
    "status": "success"
  }
}

补充说明

  • 【仅测试密钥】只有测试环境密钥(env=test)可调用;正式密钥调用返回 100001(仅测试密钥可调用测试完成端点)。代付测试完成无 actual_amount 参数(代付按下单金额)。
  • 仅可作用于测试订单:测试订单与正式订单物理隔离(独立测试存储),不动真实资金(创建时的冻结亦不在此解冻),不进入真实支付流程、不计统计。对非测试订单、不存在的单或已终态的单调用,返回 100001(订单不存在 / 非测试订单不可手动完成 / 订单已是终态)。
  • 代付终态(success/failed)均会照常入队并投递商户回调(沙箱「回调照发」),可用于联调代付回调验签;推送结果同样可经 payout/query 查询。

常见错误

  • 100104 签名错误
  • 100001 仅测试密钥可调用 / 订单不存在 / 非测试订单 / 订单已是终态(message 为具体原因)

签名与通用字段

通用字段(建议放在 JSON 请求体中):merchant_noapi_keytimestampnonce(可选)、sign。 基础算法:HMAC-SHA256。把所有参与签名字段(不含 sign)按字段名 ASCII 升序排序,拼成 key=value 并用 & 连接,末尾追加 &secret=... 得到 canonical body,对其做 HMAC-SHA256,结果转 16 进制小写作为 sign。签名基串即 canonical body 本身(body-only,无 method+路径绑定前缀)。 时间戳窗口为 ±300 秒(请求时间与服务端相差超过此范围返回 100101)。防重放:传 nonce 时按 nonce 去重,不传时按「签名指纹」兜底去重;两类去重记录均保留 600 秒(覆盖时间窗内报文的全部有效期),即同一 nonce / 同一已签名请求在 600 秒内不可重复(重复返回 100103)。建议为每个请求生成全局唯一 nonce(如 UUID),并保证其在至少 600 秒内不重复。

提示:以上签名规则已由「官方 SDK」内置实现,对接时直接调用 SDK 即可,无需手写签名与稳定序列化。

金额口径

所有金额统一约定为 金额 = 实际金额 × 10000 的整数(最小记账单位 0.0001),例如 1.234512345,以整数传输避免浮点误差。该口径适用于全部请求、响应与回调的金额字段,且不区分币种(请勿按「元」理解)。

测试密钥沙箱

测试环境密钥(env=test)可用于对接联调:用测试密钥发起的代收/代付下单为测试订单,与正式订单物理隔离(独立测试存储),走 mock 短路、不进入真实支付流程、不动真实资金、不计入统计与对账,但回调照发(可联调回调验签与入账逻辑)。测试代付不提供付款凭证/收据payout/proof/query 返回 300408、payout/receipt/query 返回 300410)。 测试单不会进入真实支付流程,因此提供两个手动完成端点让你自行把测试单推到终态:POST /merchant/pay/test/complete(代收,用 api_secret_pay,可选 actual_amount)与 POST /merchant/payout/test/complete(代付,用 api_secret_payout),resultsuccess/failed,详见上方对应端点说明。

注意:手动完成端点仅测试密钥(env=test)可调用,正式密钥调用一律被拒(返回 100001,message 为「仅测试密钥可调用测试完成端点」);且只能作用于测试订单——对正式单、不存在的单或已终态的单调用,同样返回 100001正式(env=prod)密钥无此沙箱行为:正式单不可手动完成。

回调说明

订单进入终态后,接口会按创建订单时提供的 notify_urlPOST application/json 方式发送支付/代付结果。 回调同样携带签名字段,请商户侧按对应业务(pay/payout)使用各自密钥验签。

代收回调时机:代收仅在订单成功(status=success)时回调商户;失败/超时等非成功状态不回调,商户应通过查单接口(pay/query)获知最终结果。 (代付不受此限制:代付在终态 success/failed 均会回调。)

成功应答规则:商户处理成功后,必须返回 HTTP 200 且响应体为 successok(大小写不敏感); 也接受 JSON 格式:{"success":true} / {"code":0} / {"message":"success"} / {"message":"ok"}。 未按此返回(即使 HTTP 200 但 body 为其他内容,如空响应、HTML 错误页等)本次回调视为失败, 将按策略重试,连续失败达阈值会触发告警。

代收回调字段

字段 类型 必填 说明
merchant_no string 商户号
order_no string 接口订单号
out_order_no string 商户订单号
amount int 下单参考金额(= 实际金额 × 10000 的整数);仅参考,入账以 actual_amount 为准
actual_amount int|null 用户实际支付金额(代收入账与对账的主依据,请优先使用;未知时为 null)
fee_amount int|null 手续费(按实付重算;未知时为 null)
net_amount int|null 净入账额 = 实付 − 手续费(未知时为 null)
currency string 币种
status string 归一状态;代收仅在成功时回调,故此处恒为 success
channel_order_no null 始终返回 null;请使用 order_no 或 out_order_no 关联订单。该字段为 null,不参与签名。
paid_at string|null 支付成功时间(ISO8601;未成功时可能为空)
sign string 签名(代收回调用 api_secret_pay 计算)

代付回调字段

字段 类型 必填 说明
merchant_no string 商户号
payout_no string 接口代付单号
out_payout_no string 商户代付单号
amount int 代付金额(= 实际金额 × 10000 的整数)
currency string 币种
status string 归一状态:success/failed(代付终态均回调)
fee_amount int|null 手续费(未知时为 null)
channel_order_no null 始终返回 null;请使用 payout_no 或 out_payout_no 关联订单。该字段为 null,不参与签名。
finished_at string|null 完成时间(ISO8601)
failed_reason string|null 失败原因:经平台策略确认安全的业务失败可返回上游业务原文,其余返回通用文案;非失败状态为 null
sign string 签名(代付回调用 api_secret_payout 计算)

注意:代付回调体不包含 notify_statusnotify_status 只在查单响应中返回,不会出现在回调体中。

退款回调字段

字段 类型 必填 说明
merchant_no string 商户号
order_no string|null 来源代收单的接口订单号(被退款的原代收单;极端情况下可能为 null)
out_order_no string|null 来源代收单的商户订单号(被退款的原代收单;极端情况下可能为 null)
source_channel_order_no null 始终返回 null;退款回调不提供原代收单的其他订单编号。该字段为 null,不参与签名。
refund_no string 接口退款单号
out_refund_no string 商户退款单号
amount int 退款金额(= 实际金额 × 10000 的整数)
currency string 币种
status string 归一状态:success/failed(退款终态均回调,与代付终态集合一致)
channel_order_no null 始终返回 null;退款订单关联请使用 refund_no 或 out_refund_no。该字段为 null,不参与签名。
finished_at string|null 完成时间(ISO8601)
failed_reason string|null 失败原因(对外脱敏的通用文案;失败时返回,其余为 null)
sign string 签名(退款回调用 api_secret_pay 计算,与代收共用密钥)

退款回调说明:退款回调体api_secret_pay 验签(与代收共用密钥,商户无需额外维护退款回调密钥);验签算法与代收/代付回调一致(见下文「回调签名验证」)。channel_order_no / source_channel_order_no 始终为 null不参与签名refund_no / out_refund_no 为退款单号,order_no / out_order_no 关联被退款的原代收单。

回调签名验证

回调验签算法与请求签名完全一致(见「签名与通用字段」一节):

  1. 取回调 JSON 顶层「除 sign 外、且值非 null」的所有字段;
  2. 按字段名 ASCII(码点)升序排序,拼成 key=value& 连接;
  3. 末尾追加 &secret=<对应密钥>,对该 raw string 做 HMAC-SHA256,输出 16 进制小写;
  4. 与回调体的 sign 比对(建议用常量时间比较,如 crypto.timingSafeEqual,防时序攻击)。

密钥选择:代收回调用 api_secret_pay,代付回调用 api_secret_payoutchannel_order_no 等值为 null 的字段不参与签名(与请求签名「跳过 null」一致)。

安全红线(务必遵守):① 先验签通过、再处理业务与入账,严禁未验签即按回调内容改单;② 入账 / 对账金额以 actual_amount(用户实付)与 net_amount(净入账 = 实付 − 手续费)为准,切勿使用 amount(仅为下单参考额);③ 回调可能因重试重复投递,请按 out_order_no / out_payout_no 幂等处理,重复通知不可重复入账;④ 回调来源 IP 不固定请勿用 IP 白名单限制回调来源——验签是唯一可信校验

重试 / 超时 / 安全

  • 超时:回调服务等待商户应答 8000ms,无应答即判本次失败。
  • 重试:最多 6 次(含首次),退避间隔依次约 1分钟 / 2分钟 / 5分钟 / 10分钟 / 30分钟 / 60分钟(超过取最后一档);达上限仍失败则该回调任务置 failed,商户可用查单接口兜底获取终态。
  • 不跟随重定向:回调服务对 notify_url 不跟随 30x 重定向。
  • SSRF 防护notify_url 指向内网 / 环回 / 链路本地地址会被拦截,直接判失败且不重试(地址不会自行变化);下单时此类 notify_url 亦会返回 100001

字段口径与对外约定

  • 回调金额同请求口径:= 实际金额 × 10000 的整数。
  • status 为接口统一状态值:代收恒为 success;代付为 success/failed

代收 vs 代付差异

  • 触发时机:代收仅在 success 时触发回调;代付在终态 success/failed 触发。
  • 字段差异:代收特有 actual_amount / net_amount / paid_at;代付特有 finished_at / failed_reason

IP 黑白名单说明

  • 默认不启用白名单(允许所有来源 IP 访问 OpenAPI)。
  • 当启用策略后,命中黑名单直接拒绝;存在白名单时必须命中白名单才允许访问。
  • 导出文档不包含商户真实白名单配置,请在商户后台自行查看。

错误码总表

所有业务错误统一返回 HTTP 200 + 信封 { code, message, data }不使用 HTTP 4xx/5xx 表达业务失败(传输层 4xx/5xx 仅代表网络/网关异常,应排查链路或重试)。各端点「常见错误」只列高频项,完整错误码以本表为准;鉴权类错误(100xxx)对所有需鉴权端点通用。

错误码下载 Node.js 错误码 PHP 错误码 Python 错误码 Go 错误码 Java 错误码

错误码 含义 HTTP 可重试 说明 / 排查
100000 通用业务失败 / 鉴权失败统一码 200 视情况 订单未被受理时已实时置 failed,勿用同 out_order_no 重试;鉴权阶段统一为「认证失败」话术
100001 参数校验失败 200 message 为具体字段校验错误信息(英文,如 "amount" must be a number);amount 必须为 JSON 整数,字符串/小数均返回此码。修正参数后重发
100101 请求过期 200 timestamp 超出 ±300 秒窗口;校准本地时间后重试
100102 IP 不在白名单(message 含商户号与请求 IP) 200 在商户后台把来源 IP 加入白名单后重试;正式密钥与测试密钥共用同一白名单
100103 重放 / 重复请求 200 nonce 或签名指纹在 300 秒内重复;换新 nonce(或改参数)后重试
100104 签名错误 200 核对密钥与签名算法(pay 用 api_secret_pay、payout 用 api_secret_payout)
100105 IP 在黑名单 200 从黑名单移除来源 IP 后重试
100106 鉴权失败次数过多(限流) 200 同 merchant_no + 来源 IP 在 60 秒内鉴权失败达 60 次触发;等待约 60 秒再试
200002 服务账户已禁用 200 联系服务商处理
210002 商户已禁用 200 联系服务商处理
300101 商户订单号已存在 200 同一商户 out_order_no 重复提交一律拒绝(无论参数是否相同,不返回原单);请先查单或更换新单号
300201 商户代付单号已存在 200 同一商户 out_payout_no 重复提交一律拒绝(无论参数是否相同,不返回原单);请先查单或更换新单号
300301 订单不存在 200 核对订单号(order_no / out_order_no / payout_no / out_payout_no)
300304 建单暂不可用(订单未创建,可用同一外部单号重试) 503 insert-first 并发冲突重试耗尽或风控版本分片缺失,均在 INSERT 之前 fail-closed;HTTP 503。请用同一 out_order_no / out_payout_no 稍后重试,勿换单号以免双单
300401 支付方式不可用 / 不存在 200 支付方式不可用或不存在
300402 支付方式配置不可用 200 当前请求未匹配到有效配置;修改参数或稍后重试
300403 费率未配置 200 联系服务商配置费率后重试
300404 当前条件下无可用支付方式 200 country + currency + pay_method 未匹配到启用分组;核对参数或联系运营开通
300405 缺少必要附加信息(extra.customer) 200 请按 data.missing_fields 补齐 extra.customer 中的字段
300406 缺少必要下单参数(如 bank_code) 200 补齐该路由必填字段后重试
300407 银行编码非法 200 用「查询可用银行」(payout/banks/query) 返回的 code
300408 当前支付方式不支持代付凭证查询 200 当前支付方式不支持凭证查询
300409 代付凭证暂不可用 200 订单未成功 / 凭证暂未生成 / 超出查询窗口;确认成功且在窗口内再试
300410 代付收据暂不可用(订单非 success) 200 等订单出款成功后再试
300411 收据生成失败 200 渲染异常;稍后重试
300501 余额不足 200 商户可用余额 < 冻结额(amount + fee);充值后重试

频率限制与轮询建议

  • 限流仅作用于鉴权失败:同一 merchant_no + 来源 IP 在 60 秒内鉴权失败累计达 60 次后,后续请求被拒并返回 100106,窗口滚动恢复(约 60 秒)。成功鉴权的正常业务请求无 QPS 硬上限
  • 不要无退避地重试鉴权失败(签名错误、时间偏移等),否则极易触发 100106;先修正原因再请求。
  • 查单轮询建议:终态优先依赖回调;未收到回调时再轮询查单,并使用指数退避(例如首次延迟 3~5 秒,随后 5s → 15s → 30s → 60s 递增,直至终态或合理上限)。避免对未终态订单高频空轮询。

对接须知

  • 入账金额以 actual_amount 为准:代收按用户实付金额入账与对账,请以回调 / 查单中的 actual_amount(实付)与 net_amount(净入账 = 实付 − 手续费)为准;amount 仅为下单参考额,不可作为入账依据。
  • 金额上下限:各 pay_method 的金额上下限会实时校验,不预先公布固定值;超限下单会返回相应错误码(如 300402 / 300404)。请勿在客户端硬编码金额区间。
  • 订单有效期:代收订单 expire_at 以创建订单接口返回值为准,不要硬编码固定时长;超时未支付统一为 pending,请以查单结果为准。
  • 回调来源:回调出口 IP 不固定,请勿用 IP 白名单限制回调来源,以验签作为唯一可信校验(见「回调签名验证」与上方安全红线)。

附录:国家 ISO 编码

下单字段 country 使用 ISO 3166-1 alpha-2。下表为平台国家字典标准项;某国家当前是否可下单以 pay-methods/query 为准。加密货币可不传 country

数据下载 Node.js 数据 PHP 数据 Python 数据 Go 数据 Java 数据

ISO 码 国家 常用币种
PH 菲律宾 PHP
ID 印度尼西亚 IDR
IN 印度 INR
BD 孟加拉国 BDT
VN 越南 VND
TH 泰国 THB
MM 缅甸 MMK
MY 马来西亚 MYR
BR 巴西 BRL
MX 墨西哥 MXN
CN 中国 CNY

附录:币种

下单字段 currency 使用 ISO 4217USDT 为平台加密货币例外)。金额均为实际金额 × 10000 的整数。某币种当前是否可下单以分组/支付方式查询为准。

数据下载 Node.js 数据 PHP 数据 Python 数据 Go 数据 Java 数据

币种 名称 类型
PHP 菲律宾比索 法币
IDR 印尼盾 法币
INR 印度卢比 法币
BDT 孟加拉塔卡 法币
VND 越南盾 法币
THB 泰铢 法币
MMK 缅元 法币
MYR 马来西亚林吉特 法币
BRL 巴西雷亚尔 法币
MXN 墨西哥比索 法币
CNY 人民币 法币
USDT 泰达币 加密货币

版本与兼容策略

  • 大版本写在功能路径中:<BASE_URL>/v1/...。代收/代付均只在 v1。
  • v1 仅做向后兼容的演进(新增可选字段、修复缺陷),不会改变已有字段含义或收紧已有校验。
  • 若有破坏性变更,会新增 /v2 路径并保留 /v1 一段时间,商户可平滑迁移。
  • 可调用 GET <BASE_URL>/version 查询当前服务端版本(无需鉴权)。

行为说明

  • 代收对外 status 不再返回 expired:超时未支付统一归一为 pending(处理中),请以查单结果为准。
  • 代收仅在订单成功(success)时回调商户;失败/超时等非成功状态不回调,商户应通过查单接口获知最终结果(代付不受此限制)。