浦云支付 · API 对接文档
浦云支付为商户提供 USDT TRC20 链上代收/代付 与 支付宝/微信 等聚合支付接入。本文档涵盖签名规则、接口定义、回调规范与错误码。
概览
本系统支持两大类业务:
- 代收(商户收款):通过
/api/pay/unifiedOrder创建订单,用户完成支付后系统异步回调商户notifyUrl。 - 代付(商户出款):通过
/api/pay/transferOrder提交出款申请,运营审核 + 链上广播,到账后回调商户。
所有接口使用 HTTPS + JSON,域名:
⚠️ 重要: 所有接口的
channelCode 字段一律使用数字编码:
800=USDT TRC20 · 801=支付宝 · 802=微信 (微信暂未开放).
传字符串 USDT_TRC20/ALIPAY/WXPAY 仍兼容但不推荐.
⭐ 商户对接 API 根域名
生产:
所有
生产:
https://api.dns19.com所有
/api/pay/* 接口都用此域名。例如:https://api.dns19.com/api/pay/unifiedOrderhttps://api.dns19.com/api/pay/query/{orderNo}https://api.dns19.com/api/pay/refund
接入准备
- 登录落地页 www.puyunpay.com 注册商户。
- 等待运营审核通过,获得
tenantId商户号。 - 登录商户后台 mch.puyunpay.com → API 接入 页面获取
appId与appSecret。 - 运营为该商户开通所需支付方式并设置费率(代收/代付各自独立)。
- 在商户后台填入
notifyUrl(接收异步通知的 URL)。
签名算法
所有请求与回调必须附带 sign 字段,算法 MD5:
- 把所有参数(排除
sign本身,排除 空值参数)按 key 字典序升序排列。 - 拼接成
key1=val1&key2=val2&...。 - 末尾追加
&key={appSecret}。 - 整串 MD5 小写即
sign。
示例
// 假设参数:
{
"appId": "APP5CB39B774F4EF3F8",
"mchOrderNo": "ORDER-001",
"channelCode": 800,
"amount": 100,
"currency": "USDT",
"subject": "充值 100 USDT",
"notifyUrl": "https://your-site.com/pay/notify"
}
// 排序后拼接:
"amount=100&appId=APP5CB39B774F4EF3F8&channelCode=800¤cy=USDT&mchOrderNo=ORDER-001¬ifyUrl=https://your-site.com/pay/notify&subject=充值 100 USDT&key=YOUR_APP_SECRET"
// MD5 小写 ⇒ sign
💡 签名用
appSecret 参与,请勿在前端/客户端代码中暴露。调试环境
暂无独立沙箱域名。建议用小额金额(如 1 CNY / 0.1 USDT)在生产环境测试,或联系运营在 超管后台 → 订单管理 对测试订单使用 "手动确认到账" 触发回调验证签名解析。
统一下单
POST
/api/pay/unifiedOrder请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| appId | string | 是 | 应用 ID |
| mchOrderNo | string | 是 | 商户订单号,自建,同一 appId 下唯一 |
| channelCode | int | 是 | 支付方式 数字编码: 800=USDT TRC20 · 801=支付宝 · 802=微信 (内部映射 USDT_TRC20/ALIPAY/WXPAY, 商户对接必须用数字) |
| amount | decimal | 是 | 订单金额(法币 2 位小数 / USDT 8 位小数) |
| currency | string | 否 | 币种 CNY/USDT,默认 CNY |
| subject | string | 否 | 订单标题 |
| notifyUrl | string | 否 | 异步通知 URL,不传用 app 默认 |
| returnUrl | string | 否 | 同步返回 URL |
| clientIp | string | 否 | 用户 IP |
| extParam | string | 否 | 透传参数 (channel=801 支付宝通道复用为 guest_real_name) |
| sign | string | 是 | 签名(见 签名算法) |
响应示例
// USDT TRC20 (返回收款地址 + 扰动金额)
{
"code": 200,
"msg": "操作成功",
"data": {
"orderNo": "P2047697023374028800",
"payAddress": "TXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"actualAmount": 100.00012345,
"currency": "USDT",
"contractAddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"network": "TRC20",
"expiredTime": "2026-04-25 12:30:00"
}
}
// 支付宝 (返回支付 URL)
{
"code": 200,
"msg": "操作成功",
"data": {
"orderNo": "P2047697023374028801",
"payUrl": "https://qr.alipay.com/bax..."
}
}
⚠️ USDT 通道的
actualAmount 可能带"扰动小数"用于识别不同订单,请引导用户按此精确金额转账;转账金额不符将无法自动匹配。订单查询
GET
/api/pay/query/{orderNo}传平台订单号 orderNo。返回订单当前 state:
| state | 说明 |
|---|---|
| 0 | 待支付 |
| 1 | 支付中 |
| 2 | 支付成功 |
| 3 | 失败 |
| 4 | 已退款 |
| 5 | 已关闭 |
| 6 | 已过期 |
支付回调通知
订单支付成功后,系统 POST JSON 至商户的 notifyUrl。商户 必须返回 HTTP 200 + body=SUCCESS,否则视为失败,系统自动重试(最多 3 次,间隔 0/3/8 秒)。
通知参数
{
"orderNo": "P2047697023374028800",
"mchOrderNo": "ORDER-001",
"appId": "APP5CB39B774F4EF3F8",
"amount": 100,
"actualAmount": 100.00012345,
"currency": "USDT",
"channelCode": "800",
"channelOrderNo": "abc123...txid",
"state": 2,
"payTime": "2026-04-25 12:15:33",
"sign": "xxxxxxxxxxxxxxxxx"
}
收到回调后务必 验签:用同样的签名算法 + 自己的
appSecret 重算,对比 sign。验签失败的通知视为非法请求,应返回 4xx。商户侧示例 (Node.js Express)
app.post('/pay/notify', (req, res) => {
const body = req.body;
const sign = body.sign;
delete body.sign;
const qs = Object.keys(body).sort().filter(k=>body[k]!=='').map(k=>`${k}=${body[k]}`).join('&');
const expected = md5(`${qs}&key=${APP_SECRET}`);
if (expected !== sign) return res.status(400).send('bad sign');
if (body.state === 2) {
// 订单支付成功, 更新你的订单表
}
res.send('SUCCESS');
});
代付申请
POST
/api/pay/transferOrder请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| appId | string | 是 | 应用 ID |
| mchTransferNo | string | 是 | 商户代付单号 |
| channelCode | int | 是 | 当前支持 800 (USDT TRC20) |
| toAddress | string | 是 | 收款地址(TRC20) |
| amount | decimal | 是 | 出款金额 |
| toRealName | string | 否 | 收款人姓名(银行通道用) |
| notifyUrl | string | 否 | 通知 URL |
| sign | string | 是 | 签名 |
提交后系统会 冻结 amount + fee 的商户余额,等待运营审核。
代付查询
GET
/api/pay/transfer/query/{transferNo}返回字段中 state:0=待审核 1=审核通过待发起 2=链上发起中 3=成功 4=失败 5=已驳回
代付回调通知
出款成功或失败时 POST 到 notifyUrl,商户需返回 SUCCESS。内容类似代收通知,多出 transferNo / toAddress / channelOrderNo(链上 txid) 字段。
退款
POST
/api/pay/refund| 参数 | 必填 | 说明 |
|---|---|---|
| appId | 是 | 应用 ID |
| orderNo | 是 | 原平台订单号 |
| mchRefundNo | 否 | 商户退款单号(缺省自动生成) |
| amount | 是 | 退款金额(≤ 原订单金额) |
| reason | 否 | 退款原因 |
提交后冻结商户对应余额,运营确认后正式扣账。
余额查询
GET
/pay/balance/my需商户 token(商户后台登录后使用),返回可用余额 / 冻结余额 / 累计入账 / 累计出账。
错误码
| code | 说明 |
|---|---|
| 200 | 成功 |
| 400 | 参数错误(缺字段/格式非法) |
| 401 | 未登录 / token 过期 |
| 403 | 无权限 |
| 500 | 业务错误,msg 字段含具体原因 |
常见业务错误
app 无效— appId 不存在或被禁用通道未配置或已禁用: 800/801/...— 该商户未开通此通道商户单号已存在— mchOrderNo/mchTransferNo 重复余额不足— 代付/退款超出可用余额超过日限额— 触发风控规则该账号未找到所属商户— 登录用户名不属于任何商户
SDK 下载
提供以下语言的 SDK 示例:
| 语言 | 下载 | 包含 |
|---|---|---|
| PHP | puyunpay-php.zip | 签名工具 + HTTP 客户端 + 下单/查询/回调 demo |
| .NET (C#) | puyunpay-dotnet.zip | .NET 6+ / Console demo |
| Java | puyunpay-java.zip | Maven 项目 + OkHttp 请求 + JUnit 验签测试 |
| Go | puyunpay-go.zip | 单文件 package + main demo |
| App (Android/iOS) | puyunpay-app.zip | Android Kotlin + iOS Swift 调用示例 |
更新日志
- 2026-04-25 v1.0 — 首版文档发布,覆盖代收/代付/退款/回调/签名全链路