代付下单接口
接口路径: /peerpay/bussiness/order
请求方式: POST
Content-Type: application/x-www-form-urlencoded 或 application/json(两种均支持)
提交方式
本接口支持表单提交和 JSON 提交两种方式,业务参数和签名规则完全一致。详见 旧版 API 概览 - 提交方式说明。
一、请求参数
| 参数名称 | 参数变量名 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| 签名 | sign | String | 是 | 按签名规则(MD5) |
| 友商编号 | alliesNo | String | 是 | 接入方友商的唯一 ID,由平台方提供 |
| 订单号 | tradeNo | String(128) | 是 | 订单唯一编号 |
| 订单金额 | orderAmount | Number(9,2) | 是 | 订单总金额以元为单位,精确到小数点后两位 |
| 支付方式 | tradeType | int | 是 | 与代收下单时提交的通道码一致 |
| 请求参数 | attach | String | 是 | attach 参数列表 json 字符串,用 Base64 编码后放入 |
| 回调地址 | noticeUrl | String(128) | 是 | 支付成功后,异步返回订单情况的接入方提供的接口回调地址 |
| 产品ID | productId | Int | 是 | 默认填 0,详情请查看开户资料或咨询客服 |
二、attach 参数说明
attach 字段是一个 JSON 字符串的 Base64 编码,包含以下参数:
| 参数名称 | 参数变量名 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
| 姓名 | bankAccount | String | 是 | 收款人开户姓名 |
| 银行卡号 | bankCard | String | 是 | 收款人银行账号 |
| 银行编号 | bankMark | String | 是 | 银行编码,详见下方【菲律宾银行列表】 |
| 银行名称 | bankName | String | 是 | 银行全称,详见下方【菲律宾银行列表】 |
| 省份 | bankProv | String | 否 | 如:台湾省 |
| 城市 | bankCity | String | 否 | 如:台北市 |
| 开户支行 | bankBranch | String | 否 | 如:建设银行台北XX支行 |
菲律宾银行列表
下表列出了菲律宾代付支持的银行及其编码:
| 银行编号(bankMark) | 银行名称(bankName) | 银行全称 |
|---|---|---|
GCASH | GCASH | GCash (G-Xchange, Inc.) |
PMP | PMP | PayMaya Philippines |
BPI | BPI | BPI Bank |
CPI | CPI | CIMB Philippines, Inc |
PDAX | PDAX | Philippine Digital Asset Exchange, Inc |
COINS | COINS | DCPay / COINS.PH |
UBP | UBP | Union Bank of the Philippines |
BDO | BDO | BDO Unibank, Inc. |
GOT | GOT | GoTymeBank |
KOMO | KOMO | East West Rural Bank / Komo |
AUB | AUB | Asia United Bank Corporation |
SB | SB | Seabank Philippines |
MBT | MBT | Metropolitan Bank and Trust Co. (Metrobank) |
MYA | MYA | Maya Bank, Inc. |
RCBC | RCBC | RCBC / DiskarTech |
LBOB | LBOB | LAND BANK / OFBank |
SBC | SBC | Security Bank Corporation |
CBC | CBC | China Banking Corporation |
PNB | PNB | Philippine National Bank |
PSB | PSB | Philippine Savings Bank |
MBP | MBP | Maybank Philippines |
PPS | PPS | PalawanPay |
CLB | CLB | Cebuana Lhuillier Bank / Cebuana Xpress |
RBB | RBB | Robinson Bank |
说明:
bankMark和bankName均填写相同的大写简写代码,系统会自动识别对应的银行。
attach 编码示例
原始 JSON:
json
{
"bankAccount": "小王",
"bankCard": "3501101111255501",
"bankMark": "GCASH",
"bankName": "建设银行",
"bankProv": "台湾省",
"bankCity": "台北市",
"bankBranch": "建设银行台北分行"
}**编码方式(PHP):
php
$attach = base64_encode(json_encode([
'bankAccount' => '小王',
'bankCard' => '3501101111255501',
'bankMark' => 'GCASH',
'bankName' => '建设银行',
'bankProv' => '台湾省',
'bankCity' => '台北市',
'bankBranch' => '建设银行台北分行',
]));**编码方式(Java):
java
JSONObject json = new JSONObject();
json.put("bankAccount", "小王");
json.put("bankCard", "3501101111255501");
json.put("bankMark", "GCASH");
json.put("bankName", "建设银行");
json.put("bankProv", "台湾省");
json.put("bankCity", "台北市");
json.put("bankBranch", "建设银行台北分行");
String attach = Base64.encodeBase64String(json.toString().getBytes("UTF-8"));三、请求示例
表单提交
bash
curl -X POST "http://接口域名/peerpay/bussiness/order" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "alliesNo=your_allies_no&tradeNo=ORDER20250115001&orderAmount=100.00&tradeType=31&attach=eyJiYW5rQWNjb3VudCI6...¬iceUrl=https://example.com/notify&productId=0&sign=XXXX"JSON 提交
bash
curl -X POST "http://接口域名/peerpay/bussiness/order" \
-H "Content-Type: application/json" \
-d '{
"alliesNo": "your_allies_no",
"tradeNo": "ORDER20250115001",
"orderAmount": "100.00",
"tradeType": "31",
"attach": "eyJiYW5rQWNjb3VudCI6...",
"noticeUrl": "https://example.com/notify",
"productId": "0",
"sign": "XXXX"
}'关于 attach 参数
无论使用表单还是 JSON 提交,attach 均为 JSON 字符串 Base64 编码后的字符串(不要把 JSON 对象直接放进请求体)。
四、响应参数
| 参数名称 | 参数变量名 | 类型 | 是否有值 | 说明 |
|---|---|---|---|---|
| 返回码 | code | String(10) | 是 | 编码为 10000 成功,其他为失败 |
| 返回消息 | msg | String(128) | 是 | 订单成功失败的详细信息 |
| 交易号 | tradeNo | String(128) | 是 | 请求下单的订单号 |
| 平台单号 | outTradeNo | String(128) | 是 | 平台生成的单号 |
成功响应示例
json
{
"code": "10000",
"msg": "成功",
"tradeNo": "ORDER20250115001",
"outTradeNo": "PO20250115001001"
}失败响应示例
json
{
"code": "2010",
"msg": "签名错误"
}五、PHP 调用示例
php
<?php
// 构造 attach 参数
$attachData = [
'bankAccount' => '小王',
'bankCard' => '3501101111255501',
'bankMark' => 'GCASH',
'bankName' => '建设银行',
];
$attach = base64_encode(json_encode($attachData, JSON_UNESCAPED_UNICODE));
// 构造请求参数
$params = [
'alliesNo' => 'your_allies_no',
'tradeNo' => 'ORDER' . date('YmdHis') . mt_rand(1000, 9999),
'orderAmount' => '100.00',
'tradeType' => '31',
'attach' => $attach,
'noticeUrl' => 'https://example.com/notify',
'productId' => '0',
];
// 按参数名 ASCII 字典序排序
ksort($params);
// 拼接签名串
$stringA = http_build_query($params, '', '&');
$key = 'your_api_key';
$sign = strtoupper(md5($stringA . '&key=' . $key));
$params['sign'] = $sign;
// 发送请求(表单提交)
$ch = curl_init('http://接口域名/peerpay/bussiness/order');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
if ($result['code'] === '10000') {
echo "代付订单创建成功,平台单号:" . $result['outTradeNo'];
} else {
echo "代付订单创建失败:" . $result['msg'];
}JSON 提交方式(PHP)
php
<?php
// 生成签名同上($params['sign'] = $sign)
// 发送请求(JSON 提交)
$ch = curl_init('http://接口域名/peerpay/bussiness/order');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);六、Java 调用示例
java
import java.util.*;
import java.security.MessageDigest;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.apache.commons.codec.binary.Base64;
public class PayoutDemo {
public static void main(String[] args) throws Exception {
// 构造 attach 参数
JSONObject attachJson = new JSONObject();
attachJson.put("bankAccount", "小王");
attachJson.put("bankCard", "3501101111255501");
attachJson.put("bankMark", "GCASH");
attachJson.put("bankName", "建设银行");
String attach = Base64.encodeBase64String(attachJson.toString().getBytes("UTF-8"));
// 构造请求参数(TreeMap 自动按 ASCII 字典序排序)
Map<String, String> params = new TreeMap<>();
params.put("alliesNo", "your_allies_no");
params.put("tradeNo", "ORDER" + System.currentTimeMillis());
params.put("orderAmount", "100.00");
params.put("tradeType", "31");
params.put("attach", attach);
params.put("noticeUrl", "https://example.com/notify");
params.put("productId", "0");
// 拼接签名串
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
sb.append(entry.getKey()).append("=")
.append(URLEncoder.encode(entry.getValue(), "UTF-8"))
.append("&");
}
sb.deleteCharAt(sb.length() - 1);
// 生成签名
String key = "your_api_key";
String signStr = sb.toString() + "&key=" + key;
String sign = md5(signStr).toUpperCase();
params.put("sign", sign);
System.out.println("请求参数:" + params.toString());
}
private static String md5(String input) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : digest) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}
}七、注意事项
- 订单号唯一性:
tradeNo必须全局唯一,建议使用时间戳 + 随机数 - 金额格式:必须保留两位小数,如
100.00 - 余额检查:下单前确保账户有足够余额
- 账户验证:确保收款账户信息正确无误
- 回调地址:必须是公网可访问的 URL,用于接收代付结果通知
- attach 编码:attach 参数必须先转为 JSON 字符串后再做 Base64 编码
- 通道类型:tradeType 必须与代收下单时使用的通道码保持一致
- 签名顺序:参数按参数名 ASCII 字典序排序后再拼接 key 生成签名
八、错误码说明
| 代码 | 描述 | 说明 |
|---|---|---|
| 10000 | Success | 处理成功 |
| 1001 | Unable to find user / transfer not enabled | alliesNo 错误或商户未开启代付功能 |
| 1003 | Amount exceeds channel limit | 金额超出通道限额(最小/最大) |
| 1004 | Merchant channel amount limit | 商户参数未配置 |
| 1005 | Query too frequent | 订单查询过于频繁,请3秒后重试 |
| 1008 | IP whitelist not configured | 请联系管理员配置IP白名单 |
| 1009 | RSA public key not configured | RSA公钥未配置,请联系管理员 |
| 2004 | Merchant null | alliesNo 参数为空或无效 |
| 2005 | Amount null | 代付金额为空或无效 |
| 2006 | TradeNo null | 订单号为空 |
| 2008 | TradeNo already exists | 订单号已存在,请更换 |
| 2010 | Sign Fail | 签名校验失败 |
| 2011 | Order creation failed | 订单创建失败,请重试 |
| 2014 | Sign null | 签名参数为空 |
| 2017 | Channel unauthorized | 通道未配置或未授权 |
| 2018 | Bank card null / Attach null | 银行卡号为空或 attach 参数为空 |
| 2019 | Bank account null | 收款人姓名为空 |
| 3001 | Insufficient wallet balance | 商户钱包余额不足 |
| 9999 | Channel close / System error | 代付通道关闭或系统异常 |
