支付接口文档
HTTP · POST/GET · UTF-8 · MD5 签名
1. 协议规则
传输方式:采用HTTP传输(生产环境建议HTTPS)
提交方式:采用POST/GET方式提交
字符编码:UTF-8
签名算法:MD5
1.1 参数规范
交易金额:默认为人民币交易,单位为分,参数值不能带小数。
1.2 安全规范
参数名=参数值,再按整条字典序排好,用 & 连接得到字符串 stringA。
签名规则
- 除
sign外,所有非空参数一律参与签名,没有例外;参数值为空的不参与(空字符串、null 都算空); - 参数名区分大小写(照抄别改),但排序时不区分——例如
Token排在subject之后; - 参数值里不能出现
&号——回调地址若带多个查询参数会被整笔拒绝; - 验签时报文里的
sign不参与,用它和你算出来的值比对; - 失败应答(
retCode=FAIL)可能带也可能不带sign,判断成败一律看retCode; - 返回报文里的
payParams是 JSON 对象,验签时先把它的键按字典序重排、去掉空格再序列化,用这个字符串参与;其余字段按原样; - 我们可能新增返回字段,验签要能容纳新字段,不要写死字段列表。
&key=私钥,做 MD5,结果转大写得到的就是 sign。
如请求支付系统参数如下(假设商户私钥 key 为 abc123456789):
{
"mchId": "20001222",
"productId": "9168",
"mchOrderNo": "P20260828001",
"amount": "100",
"subject": "测试商品",
"body": "测试商品描述",
"notifyUrl": "https://merchant.example.com/notify"
}amount=100&body=测试商品描述&mchId=20001222&mchOrderNo=P20260828001¬ifyUrl=https://merchant.example.com/notify&productId=9168&subject=测试商品amount=100&body=测试商品描述&mchId=20001222&mchOrderNo=P20260828001¬ifyUrl=https://merchant.example.com/notify&productId=9168&subject=测试商品&key=abc12345678994884A0F25E72BC0EB5EC0ED4F547F0C最终请求支付系统时,在上述业务参数之外再带上 sign=94884A0F25E72BC0EB5EC0ED4F547F0C。
商户登录商户系统后,通过安全中心查看或修改私钥key。
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
public class PaySign {
/** 同一个方法也可用于验证返回报文与回调通知:把收到的报文原样传进来即可。 */
public static String sign(Map<String, Object> params, String key) throws Exception {
List<String> parts = new ArrayList<>();
for (Map.Entry<String, Object> e : params.entrySet()) {
String v = val(e.getValue());
if (v.isEmpty() || "sign".equals(e.getKey())) continue;
parts.add(e.getKey() + "=" + v);
}
Collections.sort(parts, String.CASE_INSENSITIVE_ORDER);
String s = String.join("&", parts) + "&key=" + key;
byte[] d = MessageDigest.getInstance("MD5").digest(s.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : d) sb.append(String.format("%02X", b));
return sb.toString();
}
/** 嵌套对象(如下单返回报文里的 payParams,其值均为字符串):键按字典序、紧凑序列化 */
@SuppressWarnings("unchecked")
private static String val(Object o) {
if (o == null) return "";
if (!(o instanceof Map)) return o.toString();
StringBuilder sb = new StringBuilder("{");
Map<String, Object> m = new TreeMap<>((Map<String, Object>) o);
for (Map.Entry<String, Object> e : m.entrySet()) {
if (sb.length() > 1) sb.append(',');
sb.append('"').append(esc(e.getKey())).append("\":\"")
.append(esc(String.valueOf(e.getValue()))).append('"');
}
return sb.append('}').toString();
}
private static String esc(String s) {
return s.replace("\\", "\\\\").replace("\"", "\\\"");
}
public static void main(String[] args) throws Exception {
Map<String, Object> p = new LinkedHashMap<>();
p.put("mchId", "20001222");
p.put("productId", "9168");
p.put("mchOrderNo", "P20260828001");
p.put("amount", "100");
p.put("subject", "测试商品");
p.put("body", "测试商品描述");
p.put("notifyUrl", "https://merchant.example.com/notify");
System.out.println(sign(p, "abc123456789"));
// 应输出 94884A0F25E72BC0EB5EC0ED4F547F0C
}
}<?php
// 嵌套对象(如下单返回报文里的 payParams):键按字典序、紧凑序列化,与平台一致
function payVal($v): string {
if (is_array($v)) {
ksort($v);
return json_encode($v, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
return (string)$v;
}
// 同一个函数也可用于验证返回报文与回调通知:把收到的报文原样传进来即可
function paySign(array $params, string $key): string {
$parts = [];
foreach ($params as $k => $v) {
if ($k === 'sign' || $v === null) continue;
$s = payVal($v);
if ($s === '') continue;
$parts[] = $k . '=' . $s;
}
usort($parts, 'strcasecmp');
return strtoupper(md5(implode('&', $parts) . '&key=' . $key));
}
$p = [
'mchId' => '20001222',
'productId' => '9168',
'mchOrderNo' => 'P20260828001',
'amount' => '100',
'subject' => '测试商品',
'body' => '测试商品描述',
'notifyUrl' => 'https://merchant.example.com/notify',
];
echo paySign($p, 'abc123456789');
// 应输出 94884A0F25E72BC0EB5EC0ED4F547F0Cimport hashlib
import json
def _val(v):
# 嵌套对象(如下单返回报文里的 payParams):键按字典序、紧凑序列化,与平台一致
if isinstance(v, dict):
return json.dumps(v, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
return str(v)
def pay_sign(params: dict, key: str) -> str:
"""同一个函数也可用于验证返回报文与回调通知:把收到的报文原样传进来即可。"""
parts = [f"{k}={_val(v)}" for k, v in params.items()
if k != "sign" and v is not None and _val(v) != ""]
parts.sort(key=str.lower)
s = "&".join(parts) + "&key=" + key
return hashlib.md5(s.encode("utf-8")).hexdigest().upper()
p = {
"mchId": "20001222",
"productId": "9168",
"mchOrderNo": "P20260828001",
"amount": "100",
"subject": "测试商品",
"body": "测试商品描述",
"notifyUrl": "https://merchant.example.com/notify",
}
print(pay_sign(p, "abc123456789"))
# 应输出 94884A0F25E72BC0EB5EC0ED4F547F0Cconst crypto = require('crypto');
// 嵌套对象(如下单返回报文里的 payParams):键按字典序、紧凑序列化,与平台一致
const val = v => (v !== null && typeof v === 'object')
? JSON.stringify(v, Object.keys(v).sort())
: String(v);
// 同一个函数也可用于验证返回报文与回调通知:把收到的报文原样传进来即可
function paySign(params, key) {
const parts = Object.entries(params)
.filter(([k, v]) => k !== 'sign' && v !== null && v !== undefined && val(v) !== '')
.map(([k, v]) => `${k}=${val(v)}`);
parts.sort((a, b) => {
const x = a.toLowerCase(), y = b.toLowerCase();
return x < y ? -1 : x > y ? 1 : 0;
});
const s = parts.join('&') + '&key=' + key;
return crypto.createHash('md5').update(s, 'utf8').digest('hex').toUpperCase();
}
const p = {
mchId: '20001222',
productId: '9168',
mchOrderNo: 'P20260828001',
amount: '100',
subject: '测试商品',
body: '测试商品描述',
notifyUrl: 'https://merchant.example.com/notify',
};
console.log(paySign(p, 'abc123456789'));
// 应输出 94884A0F25E72BC0EB5EC0ED4F547F0C// 用法:Body 选 x-www-form-urlencoded,业务参数逐个填好,sign 那格填 {{sign}}
// 把下面这段贴进 Pre-request Script,每次 Send 会自动算好签名
const KEY = '你的商户私钥';
const parts = [];
pm.request.body.urlencoded.each(p => {
if (p.disabled || p.key === 'sign') return;
const v = pm.variables.replaceIn(String(p.value == null ? '' : p.value));
if (v !== '') parts.push(p.key + '=' + v);
});
parts.sort((a, b) => {
const x = a.toLowerCase(), y = b.toLowerCase();
return x < y ? -1 : x > y ? 1 : 0;
});
pm.variables.set('sign',
CryptoJS.MD5(parts.join('&') + '&key=' + KEY).toString().toUpperCase());2. 统一下单
业务通过统一下单接口可以发起任意三方支付渠道的支付订单。业务系统不必关心该如何调用三方支付,统一下单接口会根据业务系统传入的支付产品ID(productId),选择对应的支付渠道,发起下单请求,然后响应给业务系统支付请求所需参数。
| 字段名 | 变量名 | 必填 | 签名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|---|
| 商户ID | mchId | 必填 | 参与 | long | 20001222 | 分配的商户号 |
| 支付产品ID | productId | 必填 | 参与 | int | 9168 | 支付产品ID |
| 商户订单号 | mchOrderNo | 必填 | 参与 | String(60) | 20160427210604000490 | 每次提交不可重复;商户生成的订单号。最长 60 位,且只允许字母、数字、下划线 _ 、连字符 -,含其它字符(如 / : 空格 中文)将被拒绝 |
| 支付金额 | amount | 必填 | 参与 | int | 100 | 支付金额,单位分 |
| 客户端IP | clientIp | 可选 | 参与 | String | 210.73.10.148 | 客户端IP地址 |
| 设备 | device | 可选 | 参与 | String(64) | ios10.3.1 | 客户端设备 |
| 支付结果前端跳转URL | returnUrl | 可选 | 参与 | String(128) | https://merchant.example.com/return.htm (商户填写自己的支付完成同步跳转地址) | 支付结果同步跳转URL |
| 支付结果后台回调URL | notifyUrl | 必填 | 参与 | String(128) | https://merchant.example.com/notify.htm (商户填写自己的异步回调地址) | 支付结果异步通知URL |
| 商品主题 | subject | 必填 | 参与 | String(64) | 测试商品1 | 商品主题 |
| 商品描述信息 | body | 必填 | 参与 | String(256) | 聚合测试商品描述 | 商品描述信息 |
| 扩展参数1 | param1 | 可选 | 参与 | String(64) | 支付中心回调时会原样返回 | |
| 客户姓名 | param2 | 可选 | 参与 | String(64) | 卡转卡通道必传 | |
| 附加参数 | extra | 可选 | 参与 | String(512) | abcd | 额外参数,预留参数 |
| 币种 | currency | 可选 | 参与 | String(3) | cny | 不传默认 cny,仅支持人民币 |
| 请求时间 | reqTime | 可选 | 参与 | String(14) | 20260829171032 | 格式 yyyyMMddHHmmss,格式错会拒单 |
| 签名 | sign | 必填 | 不参与 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 签名值,详见签名算法 |
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 返回状态码 | retCode | 必填 | String(16) | SUCCESS | SUCCESS 或 FAIL。标识本次请求是否成功 |
| 返回信息 | retMsg | 可选 | String(128) | 签名失败 | 返回信息。如非空则为错误原因,例如:签名失败、参数格式校验错误 |
以下字段在retCode为SUCCESS的时候有返回
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 签名 | sign | 必填 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 签名值,详见签名算法 |
| 支付订单号 | payOrderId | 可选 | String(60) | 20160427210604000490 | 当前版本不返回,请以商户订单号 mchOrderNo 关联订单 |
| 支付引导方式 | payMethod | 必填 | String(16) | formJump | formJump=跳转支付,cardInfo=返卡支付,见下方说明 |
| 支付跳转地址 | payUrl | 可选 | String | https://pay.example.com/xxx | payMethod=formJump 时必有;cardInfo 模式不返回 |
| 支付参数 | payParams | 必填 | JSONObject | {"payMethod":"formJump","payUrl":"支付Url"} | 内容随 payMethod 而变,见下方说明 |
同步返回模式说明(payMethod)
下单成功(retCode=SUCCESS)时,返回报文中的 payMethod 字段标识本次支付引导方式,商户系统必须按 payMethod 分支处理,共两种:
1. payMethod="formJump"(跳转支付):返回 payUrl(支付跳转地址,必有)、payJumpUrl(可能为空)、payParams(内含 payMethod、payUrl,兼容用途)。商户引导付款用户浏览器跳转到 payUrl 完成支付。
2. payMethod="cardInfo"(返卡支付):返回 payParams 对象,含 accountName(收款户名)、accountNo(收款卡号)、bankName(收款银行),此模式不返回 payUrl。商户将收款卡信息展示给付款用户,由用户按下单金额转账;卡信息每笔订单可能不同,请勿缓存复用。
具体走哪种模式由平台侧通道配置决定,商户无需传任何参数,但需同时实现以上两种分支。同步返回仅表示下单受理成功,支付结果以异步回调通知和查单接口为准。
curl -X POST 'https://接口域名/api/pay/create_order' \
--data-urlencode 'mchId=20001222' \
--data-urlencode 'productId=9168' \
--data-urlencode 'mchOrderNo=PAY202608290012345678' \
--data-urlencode 'amount=150000' \
--data-urlencode 'subject=测试商品' \
--data-urlencode 'body=测试商品描述' \
--data-urlencode 'notifyUrl=https://merchant.example.com/notify' \
--data-urlencode 'returnUrl=https://merchant.example.com/return' \
--data-urlencode 'extra=OD20260829001' \
--data-urlencode 'param2=张三' \
--data-urlencode 'sign=79D49ECB98EBA457D0319E3CE5B71E20'{
"retCode": "SUCCESS",
"payMethod": "formJump",
"payUrl": "https://pay.example.com/gateway/6f2a1c",
"payParams": {
"payMethod": "formJump",
"payUrl": "https://pay.example.com/gateway/6f2a1c"
},
"sign": "39BEA0B26EA5D3C9066B2DBBF9CBE77E"
}{
"retCode": "SUCCESS",
"payMethod": "cardInfo",
"payParams": {
"accountName": "张三",
"accountNo": "6222020200098541458",
"bankName": "招商银行深圳分行"
},
"sign": "AAEC7509A9CC4BF1DB65D3C7B795C484"
}{
"retCode": "FAIL",
"retMsg": "签名失败"
}3. 查询支付订单
业务系统通过查询支付订单接口获取最新的支付订单状态,并根据状态结果进一步处理业务逻辑。
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户ID | mchId | 必填 | String(30) | 20001222 | 支付中心分配的商户号 |
| 支付订单号 | payOrderId | 二选一 | String(60) | 20160427210604000490 | 与 mchOrderNo 二选一。传了本字段就只按它查,mchOrderNo 会被忽略;下单接口不返回本字段,建议只传 mchOrderNo |
| 商户订单号 | mchOrderNo | 二选一 | String(60) | 20160427210604000490 | 商户生成的订单号,与 payOrderId 二选一 |
| 是否执行回调 | executeNotify | 可选 | Boolean | true | 为 true 时,若订单已支付成功,支付中心会再向商户补发一次回调;订单未成功时不会有任何回调 |
| 签名 | sign | 必填 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 签名值,详见签名算法 |
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 返回状态码 | retCode | 必填 | String(16) | SUCCESS | SUCCESS 或 FAIL。标识本次请求是否成功 |
| 返回信息 | retMsg | 可选 | String(128) | 签名失败 | 返回信息。如非空则为错误原因,例如:签名失败、参数格式校验错误 |
以下字段在retCode为SUCCESS的时候有返回
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户ID | mchId | 必填 | String(30) | 20001222 | 支付中心分配的商户号 |
| 支付产品ID | productId | 必填 | String | 9168 | 支付产品ID |
| 支付订单号 | payOrderId | 必填 | String(60) | 20160427210604000490 | 支付订单号(与 mchOrderNo 相同) |
| 商户订单号 | mchOrderNo | 必填 | String(60) | 20160427210604000490 | 商户生成的订单号 |
| 支付金额 | amount | 必填 | String | 100 | 支付金额,单位分 |
| 币种 | currency | 必填 | String(3) | cny | 货币代码,人民币:cny |
| 状态 | status | 必填 | String | 0 1 2 3 4 -1 -2 | 0 订单生成 1 支付中 2 支付成功 3 业务完成(成功已回调) 4 已冲正 -1 支付失败 -2 订单已关闭 |
| 渠道用户ID | channelUser | 可选 | String(64) | 渠道侧支付时使用的用户ID | |
| 渠道订单号 | channelOrderNo | 可选 | String(64) | wx20170910211043fb206e92260071822007 | 对应的第三方支付订单号 |
| 渠道数据包 | channelAttach | 可选 | String | 上游透传的附加数据,多数通道为空 | |
| 支付成功时间 | paySuccTime | 可选 | String | 1787894094262 | 支付成功时间,13 位毫秒时间戳 |
| 签名 | sign | 必填 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 签名值,详见签名算法 |
curl -X POST 'https://接口域名/api/pay/query_order' \
--data-urlencode 'mchId=20001222' \
--data-urlencode 'mchOrderNo=PAY202608290012345678' \
--data-urlencode 'sign=C566E282BEB8D6555BCE7856DCA759DF'{
"retCode": "SUCCESS",
"mchId": "20001222",
"productId": "9168",
"payOrderId": "PAY202608290012345678",
"mchOrderNo": "PAY202608290012345678",
"amount": "150000",
"currency": "cny",
"status": "3",
"channelOrderNo": "wx20260828211043fb206e92260071822007",
"paySuccTime": "1787894094262",
"sign": "79054F5536F4CD872B687CAA0A625398"
}4. 支付结果通知
支付成功后,我方平台将支付结果通知给 notifyUrl。
- 发送:
POST请求,参数放在请求体里,类型application/x-www-form-urlencoded(格式与 URL 查询串一样,参数值经 UTF-8 编码)。空值字段也会带上(写成「字段名=」),但空值不参与签名。 - 返回:验签通过后,响应体只回
success这 7 个字符。必须整串相等——回 JSON、或内容里夹着 success,都算失败。 - 失败:按 1、2、3、4、5 分钟的间隔重发,最多再发 5 次。
- ⚠ 这个地址不能自带
?:平台会在你的地址后面再拼一个?,两个问号会让我方第一个参数的字段名粘进你自己的参数值里,验签必然失败。
| 字段名 | 变量名 | 必填 | 签名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|---|
| 支付订单号 | payOrderId | 必填 | 参与 | String(60) | 20160427210604000490 | 支付订单号(与 mchOrderNo 相同) |
| 商户ID | mchId | 必填 | 参与 | String(30) | 20001222 | 支付中心分配的商户号 |
| 支付产品ID | productId | 必填 | 参与 | int | 9168 | 支付产品ID |
| 商户订单号 | mchOrderNo | 必填 | 参与 | String(60) | 20160427210604000490 | 商户生成的订单号 |
| 支付金额 | amount | 必填 | 参与 | int | 100 | 支付金额,单位分 |
| 实际支付金额 | income | 必填 | 参与 | int | 100 | 实际支付金额,单位分 |
| 状态 | status | 必填 | 参与 | int | 2 | 2 或 3 都表示支付成功(补发的通知会是 3)。只有支付成功才发通知,其它状态请用查单接口 |
| 渠道订单号 | channelOrderNo | 可选 | 参与 | String(64) | wx2016081611532915ae15beab0167893571 | 三方支付渠道订单号 |
| 渠道数据包 | channelAttach | 可选 | 参与 | String | 上游透传的附加数据,多数通道为空 | |
| 扩展参数1 | param1 | 可选 | 参与 | String(64) | 支付中心回调时会原样返回 | |
| 客户姓名 | param2 | 可选 | 参与 | String(64) | 支付中心回调时会原样返回 | |
| 支付成功时间 | paySuccTime | 必填 | 参与 | long | 1787894094262 | 精确到毫秒 |
| 通知类型 | backType | 必填 | 参与 | int | 2 | 2 notifyUrl通知 |
| 签名 | sign | 必填 | 不参与 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 签名值,详见签名算法 |
curl -X POST 'https://merchant.example.com/notify' \
--data-urlencode 'payOrderId=PAY202608290012345678' \
--data-urlencode 'mchId=20001222' \
--data-urlencode 'productId=9168' \
--data-urlencode 'mchOrderNo=PAY202608290012345678' \
--data-urlencode 'amount=150000' \
--data-urlencode 'income=150000' \
--data-urlencode 'status=2' \
--data-urlencode 'channelOrderNo=wx20260828211043fb206e92260071822007' \
--data-urlencode 'paySuccTime=1787894094262' \
--data-urlencode 'backType=2' \
--data-urlencode 'sign=A9AB733008917D3F9999CFC208A00FF1'success5. 查询商户余额
业务系统查询余额。
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户ID | mchId | 必填 | String(30) | 20001222 | 支付中心分配的商户号 |
| 签名 | sign | 必填 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 签名值,详见签名算法 |
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 返回状态码 | retCode | 必填 | String(16) | SUCCESS | SUCCESS 或 FAIL。标识本次请求是否成功 |
| 返回信息 | retMsg | 可选 | String(128) | 签名失败 | 返回信息。如非空则为错误原因,例如:签名失败、参数格式校验错误 |
| 错误码 | errCode | 可选 | String(8) | 0010 | 仅在失败时返回,值固定是 0010 |
| 错误描述 | errDes | 可选 | String(128) | 参数错误 | 仅在 retCode 为 FAIL 时返回 |
以下字段在retCode为SUCCESS的时候有返回
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户ID | mchId | 必填 | long | 20001222 | 支付中心分配的商户号 |
| 总余额 | balance | 必填 | long | 1000 | 总余额,单位分 |
| 可用余额 | availableBalance | 必填 | long | 1000 | 可用余额,单位分 |
| 签名 | sign | 必填 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 签名值,详见签名算法 |
curl -X POST 'https://接口域名/api/account/mch_balance' \
--data-urlencode 'mchId=20001222' \
--data-urlencode 'sign=3A6A04A7E57518BA9DDC9FA25B05A998'{
"retCode": "SUCCESS",
"mchId": 20001222,
"balance": 1000,
"availableBalance": 1000,
"sign": "7ED9464396D17426045FB8A3903CF0A9"
}代付接口文档
HTTP · POST/GET · UTF-8 · MD5 签名 · 需 IP 白名单
1. 协议规则
传输方式:采用HTTP传输(生产环境建议HTTPS)
提交方式:采用POST/GET方式提交
字符编码:UTF-8
签名算法:MD5
IP 白名单:代付接口需先向运营申请把发起请求的服务器出口 IP 加入白名单,否则会被拒绝。
参数规范与签名算法与支付接口完全相同(同一套签名实现),请直接看 支付接口 · 1.2 安全规范:金额单位为分不带小数;签名为「参数名=参数值」整条排序后拼私钥取 MD5 大写。
2. 申请代付
商户通过代付接口发起代付申请,支付系统收到请求后同步返回申请结果,申请成功并不代表代付成功。
商户有两种方式确定代付结果:
1)发起代付时传递代付结果回调地址,支付系统处理代付确定结果后会向该地址发起通知请求。
2)商户系统客户主动发起代付查询,以查询到的最终结果确定代付是否成功。
注意:商户访问该接口需要申请IP白名单。
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户ID | mchId | 必填 | long | 20001222 | 分配的商户号 |
| 代付产品ID | productId | 必填 | int | 9188 | 代付产品ID |
| 商户订单号 | mchOrderNo | 必填 | String(64) | 20160427210604000490 | 每次提交不可重复;商户代付订单号 |
| 代付金额 | amount | 必填 | int | 8000 | 代付金额,单位分 |
| 账户属性 | accountAttr | 可选 | Byte | 0 | 0-对私,1-对公,默认对私 |
| 收款姓名 | accountName | 必填 | String(64) | 张三 | 收款姓名 |
| 收款账号 | accountNo | 必填 | String(64) | 6222020200098541458 | 收款账号,只能是数字,不要带空格或横杠 |
| 开户行所在省份 | province | 可选 | String(32) | 北京 | 开户行所在省份。对公时必填 |
| 开户行所在市 | city | 可选 | String(32) | 北京 | 开户行所在市。对公时必填 |
| 开户行名称 | bankName | 必填 | String(128) | 工商银行 | 无需银行编码,系统智能识别 |
| 联行号 | bankNumber | 可选 | String(64) | 11473707055 | 联行号。对公时必填 |
| 代付结果回调URL | notifyUrl | 可选 | String(128) | https://merchant.example.com/agentpay/notify (商户填写自己的代付结果异步通知地址) | 代付结果异步通知URL |
| 备注 | remark | 必填 | String(128) | 代付80元 | 备注 |
| 扩展域 | extra | 可选 | String(128) | 扩展域 | |
| 请求时间 | reqTime | 可选 | String(14) | 20181009171032 | 请求发起时间,时间格式:yyyyMMddHHmmss |
| 签名 | sign | 必填 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 签名值,详见签名算法 |
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 返回状态码 | retCode | 必填 | String(16) | SUCCESS | SUCCESS 或 FAIL。标识本次请求是否成功 |
| 返回信息 | retMsg | 可选 | String(128) | 签名失败 | 返回信息 |
以下字段在retCode为SUCCESS的时候有返回
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 代付单号 | agentpayOrderId | 必填 | String(30) | T01202608280642059440884 | 支付系统生成的代付订单号 |
| 手续费 | fee | 必填 | long | 300 | 手续费,单位分 |
| 扩展域 | extra | 可选 | String(128) | 扩展域 | |
| 状态 | status | 必填 | int | 1 | 状态:0-待处理,1-处理中,2-成功,3-失败 |
| 转账提示 | transMsg | 可选 | String(128) | 转账提示。仅在 status=3(失败) 时返回,其余状态为空 | |
| 签名 | sign | 必填 | String(32) | 6012FB85432A4BBAA309985A1C054219 | 签名值 |
curl -X POST 'https://接口域名/api/agentpay/apply' \
--data-urlencode 'mchId=20001222' \
--data-urlencode 'productId=9188' \
--data-urlencode 'mchOrderNo=AP20260828001' \
--data-urlencode 'amount=8000' \
--data-urlencode 'accountAttr=0' \
--data-urlencode 'accountName=张三' \
--data-urlencode 'accountNo=6222020200098541458' \
--data-urlencode 'bankName=招商银行深圳分行' \
--data-urlencode 'remark=代付80元' \
--data-urlencode 'notifyUrl=https://merchant.example.com/agentpay/notify' \
--data-urlencode 'reqTime=20260828171032' \
--data-urlencode 'sign=593BDFB6E115763B5268F0ED1FF7BD01'{
"retCode": "SUCCESS",
"agentpayOrderId": "T01202608280642059440884",
"fee": 300,
"status": 1,
"sign": "0405D8812E1B80305E0F225B0F3EEE10"
}3. 查询代付订单
商户通过该接口查询代付订单结果,并根据状态结果进一步处理业务逻辑。
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户ID | mchId | 必填 | long | 20001222 | 分配的商户号 |
| 商户订单号 | mchOrderNo | 二选一 | String(64) | AP20260828001 | 商户生成的订单号,与 agentpayOrderId 二选一 |
| 代付单号 | agentpayOrderId | 二选一 | String(30) | T01202608280642059440884 | 支付中心生成的订单号,与 mchOrderNo 二选一 |
| 请求时间 | reqTime | 必填 | String(14) | 20181009171032 | 请求发起时间,时间格式:yyyyMMddHHmmss |
| 签名 | sign | 必填 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 签名值,详见签名算法 |
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 返回状态码 | retCode | 必填 | String(16) | SUCCESS | SUCCESS 或 FAIL。标识本次请求是否成功 |
| 返回信息 | retMsg | 可选 | String(128) | 签名失败 | 返回信息。如非空则为错误原因 |
以下字段在retCode为SUCCESS的时候有返回
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户订单号 | mchOrderNo | 必填 | String(64) | AP20260828001 | 商户生成的订单号 |
| 代付单号 | agentpayOrderId | 必填 | String(30) | T01202608280642059440884 | 支付中心生成的订单号 |
| 代付金额 | amount | 必填 | String | 8000 | 代付金额,单位分 |
| 手续费 | fee | 必填 | String | 300 | 手续费,单位分 |
| 状态 | status | 必填 | String | 1 | 状态:0-待处理,1-处理中,2-成功,3-失败 |
| 转账提示 | transMsg | 可选 | String(128) | 转账提示。查单接口仅在 status=3(失败) 时返回;代付结果通知中则原样返回 | |
| 签名 | sign | 必填 | String(32) | 3B166CA71811D4A0FEC25D511A365ED3 | 签名值,详见签名算法 |
curl -X POST 'https://接口域名/api/agentpay/query_order' \
--data-urlencode 'mchId=20001222' \
--data-urlencode 'mchOrderNo=AP20260828001' \
--data-urlencode 'reqTime=20260828171032' \
--data-urlencode 'sign=55564FE3EEBC28A63C32E3F3317CB45D'{
"retCode": "SUCCESS",
"mchOrderNo": "AP20260828001",
"agentpayOrderId": "T01202608280642059440884",
"amount": "8000",
"fee": "300",
"status": "2",
"sign": "1DE1A92B8584352449BD0BE5D2671870"
}4. 代付结果通知
代付处理完成后,我方平台将代付结果通知给 notifyUrl。
- 发送:
POST请求,参数放在请求体里,类型application/x-www-form-urlencoded(格式与 URL 查询串一样,参数值经 UTF-8 编码)。空值字段也会带上(写成「字段名=」),但空值不参与签名。 - 返回:验签通过后,响应体只回
success这 7 个字符。必须整串相等——回 JSON、或内容里夹着 success,都算失败。 - 失败:按 1、2、3、4、5 分钟的间隔重发,最多再发 5 次。
- ⚠ 这个地址不能自带
?:平台会在你的地址后面再拼一个?,两个问号会让我方第一个参数的字段名粘进你自己的参数值里,验签必然失败。
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 代付单号 | agentpayOrderId | 必填 | String(30) | T01202608280642059440884 | 支付中心生成的订单号 |
| 商户订单号 | mchOrderNo | 必填 | String(64) | AP20260828001 | 商户订单号 |
| 代付金额 | amount | 必填 | int | 8000 | 代付金额,单位分 |
| 状态 | status | 必填 | int | 2 | 状态:0-待处理,1-处理中,2-成功,3-失败 |
| 手续费 | fee | 必填 | long | 300 | 手续费,单位分 |
| 转账提示 | transMsg | 可选 | String(128) | 转账提示。查单接口仅在 status=3(失败) 时返回;代付结果通知中则原样返回 | |
| 扩展域 | extra | 可选 | String(128) | 扩展域 | |
| 通知时间 | reqTime | 必填 | String(14) | 20181009171032 | 本条通知生成的时间,格式 yyyyMMddHHmmss。重发时不变,不要拿它做时效判断 |
| 签名 | sign | 必填 | String(32) | 3B166CA71811D4A0FEC25D511A365ED3 | 签名值,详见签名算法 |
curl -X POST 'https://merchant.example.com/agentpay/notify' \
--data-urlencode 'agentpayOrderId=T01202608280642059440884' \
--data-urlencode 'mchOrderNo=AP20260828001' \
--data-urlencode 'amount=8000' \
--data-urlencode 'status=2' \
--data-urlencode 'fee=300' \
--data-urlencode 'reqTime=20260828171032' \
--data-urlencode 'sign=98B00D6EA30FC89325F4E7B1AD6F7CDA'success5. 查询余额
商户可通过该接口查询代付账户余额。
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户ID | mchId | 必填 | long | 20001222 | 分配的商户号 |
| 请求时间 | reqTime | 必填 | String(14) | 20181009171032 | 请求发起时间,时间格式:yyyyMMddHHmmss |
| 签名 | sign | 必填 | String(32) | C380BEC2BFD727A4B6845133519F3AD6 | 签名值,详见签名算法 |
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 返回状态码 | retCode | 必填 | String(16) | SUCCESS | SUCCESS 或 FAIL。标识本次请求是否成功 |
| 返回信息 | retMsg | 可选 | String(128) | 签名失败 | 返回信息。如非空则为错误原因 |
以下字段在retCode为SUCCESS的时候有返回
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 可用代付余额 | availableAgentpayBalance | 必填 | String | 943618 | 商户可用代付余额,单位:分;可能为负数 |
| 代付余额 | agentpayBalance | 必填 | String | 943618 | 代付余额,单位:分;可能为负数 |
| 签名 | sign | 必填 | String(32) | 26319C79C2E5A581744C22AD3B61F9F3 | 签名值 |
curl -X POST 'https://接口域名/api/agentpay/query_balance' \
--data-urlencode 'mchId=20001222' \
--data-urlencode 'reqTime=20260828171032' \
--data-urlencode 'sign=E7904B9CCEB8A9C00162B192001F1225'{
"retCode": "SUCCESS",
"availableAgentpayBalance": "943618",
"agentpayBalance": "943618",
"sign": "9A02BB0F0B75995F22518CD9727C0275"
}