商户信息
建议 256×256 PNG/JPG/WebP,≤200KB;选图后点「保存商户信息」生效
2-31 位小写字母、数字或 -
修改登录密码
① 调用安全(必填)
平台统一使用 USDT 计价,不能选择其他业务单位;支付时买家仍可选择不同链和代币。
默认 5 分钟;从创建订单开始计时,超时仍未上链就会失效。
默认 0 分钟;交易必须在付款时限内上链。链上拥堵时可临时调大。
② 支付资产(链 / 代币 / 收款地址)
可多链多币;保存资产前必须点击“查询合约”,并以服务端返回的名称、符号和精度为准。
状态显示“需重新验证”时,请点击“编辑”→“查询合约”→“保存资产”。
| # | 链 | 代币 | 收款地址 | 兑换比例 | 状态 | 操作 |
|---|---|---|---|---|---|---|
| 加载中… | ||||||
③ 发放通道
支付校验通过后 POST 到此地址。请求带签名(与打开收银台相同算法),无需单独配账号密钥。
| 订单号 | 数量 | 应付 | 状态 | 发放 | 时间 | 操作 |
|---|---|---|---|---|---|---|
| 加载中… | ||||||
接入说明文档
职责划分:业务按 USDT 计价传「数量 + 单号 + 业务数据」;买家在收银台选链选币;我们收款验链后回调你的发放接口。
0. 接入顺序
- 先在“支付配置”确认 USDT 计价;默认付款时限 5 分钟、链上延迟宽限 0 分钟。
- 在“调用安全”生成 AppSecret,并只保存到你的业务服务端。
- 在“支付资产”查询并确认链上代币,再填写同链收款地址和固定汇率。
- 在“发放通道”填写公网 HTTPS 接口;平台验证到账后会回调它。
- 用测试业务单号完成一笔支付,确认回调验签和幂等逻辑后再上线。
1. 打开收银台
-
当前计价单位为 USDT;支付链/代币由买家在页面选择,业务方无需指定。
2. URL 参数
| 参数 | 必填 | 说明 |
|---|---|---|
| qty | 是 | 正十进制字符串,如 4.99;最多 18 位小数 |
| qtyUnit | 是 | 固定为 USDT,必须参与签名 |
| outTradeNo | 是 | 业务订单号(1–128 字符)。同一业务订单号同一时刻只能有一笔存活的支付订单:重复打开链接会返回同一笔订单,已付款则拒绝再次下单 |
| payload | 否 | 业务 JSON 字符串,不解析,回调原样带回 |
| timestamp | 是 | 毫秒时间戳,签名生成后 30 分钟内有效 |
| sign | 是 | HMAC-SHA256 见下;AppSecret 未配置时支付不可用 |
| payChainId / payToken | 否 | 预选支付链/代币(仍可改) |
3. 签名算法(规范拼串)
字段顺序固定;key 与 value 均 URL 编码,再用 & 连接。
打开收银台时 orderNo 传空字符串。
// 待签名串(顺序固定)
raw = "orderNo=" + urlencode(orderNo)
+ "&outTradeNo=" + urlencode(outTradeNo)
+ "&payload=" + urlencode(payload)
+ "&qty=" + qty
+ "&qtyUnit=" + urlencode(qtyUnit)
+ "×tamp=" + urlencode(timestamp)
sign = lowercase_hex( HMAC_SHA256( key = appSecret, message = raw ) )
// 示例:qty=4.99, qtyUnit=USDT, outTradeNo=BIZ-001, payload={"userId":"u888"}
// raw = "orderNo=&outTradeNo=BIZ-001&payload=%7B%22userId%22%3A%22u888%22%7D&qty=4.99&qtyUnit=USDT×tamp=1717000000000"
// Node.js(只在业务服务端执行)
const crypto = require('node:crypto');
const escape = s => encodeURIComponent(String(s)).replace(/%20/g, '+');
const raw = 'orderNo=&outTradeNo=' + escape(outTradeNo) +
'&payload=' + escape(payload) + '&qty=' + escape(qty) +
'&qtyUnit=' + escape(qtyUnit) + '×tamp=' + escape(timestamp);
const sign = crypto.createHmac('sha256', process.env.MERCHANT_APP_SECRET).update(raw).digest('hex');
校验失败:HTTP 403 INVALID_SIGN。timestamp 为毫秒,签名生成后 30 分钟内有效。
AppSecret 与签名均为必填,不提供无签名测试模式。
payload 须为合法 JSON且不超过 4KB,否则下单返回 INVALID_PAYLOAD。
4. 履约回调(支付成功后)
在「支付配置 · 发放通道」只配接口地址。请求不带 Basic Auth,带同一规范签名(orderNo 为本单 ORD-...)。
POST {发放接口地址}
Content-Type: application/json
{
"orderNo": "ORD-74fb0bfd...",
"status": "paid",
"txHash": "链对应的交易哈希",
"chainId": 56,
"tokenAddress": "链对应的代币地址",
"tokenSymbol": "USDT",
"paidAmount": "30000",
"paidAmountRaw": "30000000000",
"qty": "4.99",
"qtyUnit": "USDT",
"outTradeNo": "BIZ-001",
"payload": { "userId": "u888" },
"idempotencyKey": "ORD-74fb0bfd...",
"timestamp": "1717000012345",
"sign": "a1b2c3..."
}
// 业务字段原样返回,我们只附加支付事实
// 签名规则同上;其中 payload 取本回调请求体中 payload 字段的原始文本,无 payload(或业务 payload 为 null)时为空串。
// 平台只去掉 payload 里 JSON 记号之间的空白,字符串内容逐字节保留,不做 HTML 转义(< > & 原样发送)。
// 请从收到的请求体中截取 payload 的原始文本验签,不要解析后再重新序列化:
// 重新序列化可能改变转义、空白或键顺序,导致验签失败。
// paidAmountRaw 为链上实际到账;应付金额含不超过 0.1% 的随机尾数(用于区分订单)
// 同时附带 signVersion: "2" 与 signV2(完整签名):覆盖除 sign / signV2 外的全部字段,
// raw 按 key 字典序拼接 chainId, idempotencyKey, orderNo, outTradeNo, paidAmount, paidAmountRaw, payload,
// qty, qtyUnit, signVersion, status, timestamp, tokenAddress, tokenSymbol, txHash(value 做 URL 编码,& 连接),
// signV2 = lowercase_hex(HMAC_SHA256(appSecret, raw))。新接入请校验 signV2;sign 为兼容保留,不保护金额与状态字段。
// 收到回调后先验签、再核对本地订单的 qty 与 outTradeNo,最后发放;不要直接按回调里的金额发放。
// 幂等:先按 outTradeNo 判断业务订单是否已发放,再按 idempotencyKey 识别同一笔订单的重试
// 响应必须 HTTP 200 且为 JSON:
{ "status": "saved" | "pending" | "failed", "message": "ok" }
// 非 200、非 JSON、status 取值不在上述范围:视为失败。
// failed / pending:按 2^n 分钟(最长 60 分钟)退避自动重试,最多 12 次;之后可在「订单」中手工「重新发放」。
// 发放接口地址必须是公网 https://,不允许明文 http、localhost 或内网 IP;不跟随重定向(3xx 视为失败)。
EVM 交易哈希为 0x 加 64 位十六进制;TRON 为 64 位十六进制;Solana 为 64 字节 Base58 签名。
TRON 收款使用 TronLink,Solana 收款使用 Phantom 等钱包。TRON/Solana 当前使用固定汇率,实时汇率资产不会显示为可支付。
5. 常见错误
| code | 含义 |
|---|---|
| INVALID_SIGN | 签名缺失 / 不合法 / 时间戳超过 30 分钟 |
| INVALID_OUT_TRADE_NO | outTradeNo 缺失、超过 128 字符或含控制字符 |
| OUT_TRADE_NO_IN_PROGRESS | 该业务订单已提交付款交易、正在核验(响应带 orderNo) |
| OUT_TRADE_NO_PAID | 该业务订单已支付,不能重复下单(响应带 orderNo) |
| INVALID_PAYLOAD | payload 不是合法 JSON 或超过 4KB |
| AMOUNT_BUSY | 同金额订单支付中(极小金额无法错开),稍后重试 |
| CHAIN_NOT_READY | 该链适配器当前不可用,请稍后重试或联系平台管理员 |
| CHAIN_UNSUPPORTED | 不支持的链 |
| PRICE_UNAVAILABLE | 实时汇率不可用(行情缺失 / 可信度不足 / 稳定币脱锚) |
| ORDER_EXPIRED | 订单超过付款截止,请重新下单 |
| INVALID_AMOUNT | qty 无效 |
| PAYMENT_NOT_READY | 商户资产未配好 |
| MERCHANT_NOT_FOUND | 支付链接无效 |
建议全程 HTTPS;AppSecret 至少 16 位随机串,勿写入客户端。
多付订单不会自动发放,状态为「多付待确认」,请核对后在「订单」中确认收款(平台不持有私钥,无法自动退款)。
买家已付款但哈希丢失的订单,可在「订单」中「补录哈希」。