API 接入文档
1. 接入概览
| 项目 | 说明 |
|---|---|
| 域名 | https://api-bs.360xpay.com |
| 基础路径 | /api/v1/ |
| 协议 | HTTPS |
| 请求方式 | POST |
| 请求格式 | Content-Type: application/json |
| 鉴权方式 | Header: Authorization: api-key {apiKey} |
| 签名算法 | HMAC-SHA256,Base64 输出 |
| 下单超时 | 服务端异步任务超时时间 300 秒 |
说明:服务端也兼容
Authorization: {apiKey},但建议统一使用api-key前缀。
2. 通用响应格式
所有商户主动调用接口统一返回:
| 字段 | 类型 | 说明 |
|---|---|---|
| code | Integer | 业务响应码,0 表示成功 |
| message | String | 响应描述 |
| data | String | JSON 字符串;客户端需要再次 JSON 解析 |
示例:
{
"code": 0,
"message": "success",
"data": "{\"transactionNo\":\"COLL123\",\"merchantOrderNo\":\"M202604300001\",\"amount\":\"100.00\"}"
}
为便于阅读,本文后续示例会把 data 展开为 JSON 对象。当前实现会把响应数据中的金额类数值转换为字符串。
3. 签名规则
3.1 Authorization
每个商户由平台分配:
| 凭据 | 用途 |
|---|---|
| apiKey | 放在 Authorization 请求头中,用于识别商户 |
| signKey | 用于请求签名和平台回调验签 |
请求头示例:
Authorization: api-key YOUR_API_KEY
Content-Type: application/json
3.2 签名生成步骤
- 根据接口签名字段白名单取值,不参与签名的字段不要放入签名串。
- 移除值为
null的字段。 - 移除空字符串字段。
- 按字段名升序排序。
- 拼接为
key=value&key=value。 - 使用
signKey对拼接串做 HMAC-SHA256。 - 将摘要结果 Base64 编码,得到
sign。
伪代码:
stringA = sort(params)
.filter(value != null && value != "")
.map(key + "=" + value)
.join("&")
sign = Base64(HMAC_SHA256(stringA, signKey))
Java 示例:
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(signKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
String sign = Base64.getEncoder().encodeToString(mac.doFinal(stringA.getBytes(StandardCharsets.UTF_8)));
3.3 金额与对象字段注意事项
| 项目 | 要求 |
|---|---|
| amount | 建议使用普通十进制格式,如 100.00,不要使用科学计数法 |
| sign | 不参与签名 |
| channelParams | 如果传入,会参与签名;不同语言对象字符串化结果可能不一致,建议为空或与平台联调确认 |
| manualOrderType | 不传时下单默认为系统订单;如果传入,会参与签名 |
4. 订单状态
| 状态码 | 状态名 | 说明 |
|---|---|---|
| 0 | PENDING | 待处理 |
| 1 | PROCESSING | 处理中 |
| 2 | SUCCESS | 成功 |
| 3 | FAILED | 失败 |
| 4 | EXPIRED | 已过期 |
| 5 | REVERSED | 已冲正 |
接口返回中的 status 当前为字符串形式的状态码,如 "1"、"2"。
5. 创建代收订单
| 项目 | 说明 |
|---|---|
| URL | /api/v1/createCollectionOrder |
| Method | POST |
| 鉴权 | 需要 Authorization |
| 签名 | 需要 |
5.1 请求字段
| 字段 | 类型 | 必填 | 是否参与签名 | 说明 |
|---|---|---|---|---|
| merchantId | String | 是 | 是 | 商户 ID |
| merchantOrderNo | String | 是 | 是 | 商户订单号,代收订单内唯一 |
| paymentNo | String | 是 | 是 | 商户通道编码 |
| amount | Decimal | 是 | 是 | 代收金额,必须大于 0 |
| currency | String | 是 | 是 | 币种,如 VND、PKR、IDR、USD、CNY |
| notificationUrl | String | 是 | 是 | 平台异步通知商户的回调地址 |
| channelParams | String | 否 | 是,非空时参与 | 渠道扩展参数 |
| remark | String | 否 | 是,非空时参与 | 备注 |
| manualOrderType | Integer | 否 | 是,非空时参与 | API 默认不传;调试可选 3、4 ,3 :会发生金额的测试订单, 4 : 不会发生金额,可回退订单 |
| sign | String | 是 | 否 | 请求签名 |
签名字段白名单:
merchantId, merchantOrderNo, paymentNo, amount, currency, notificationUrl, channelParams, remark, manualOrderType
5.2 请求示例
{
"merchantId": "M10001",
"merchantOrderNo": "COLL202604300001",
"paymentNo": "PAYMENT_A",
"amount": "100.00",
"currency": "USDT",
"notificationUrl": "https://merchant.example.com/api/v1/notify",
"remark": "test collection",
"sign": "BASE64_HMAC_SHA256_SIGN"
}
5.3 成功响应 data
data 为 JSON 对象;实际接口外层 data 字段当前以 JSON 字符串形式返回,客户端需要先解析。
| 字段 | 类型 | 说明 |
|---|---|---|
| amount | String | 订单金额 |
| transactionNo | String | 平台交易号,代收以 COLL 开头 |
| merchantOrderNo | String | 商户订单号 |
| currency | String | 币种 |
| createTime | String | 当前代收创建响应为时间字符串 |
| status | String | 订单状态码 |
| qrCode | String | 可选,渠道返回图片或者 Base64 |
| cashierUrl | String | 可选,渠道返回收银台地址 |
| payUrl | String | 可选,渠道返回支付地址 |
示例:
{
"code": 0,
"message": "success",
"data": {
"amount": "100.00",
"transactionNo": "COLL1234567890",
"merchantOrderNo": "COLL202604300001",
"currency": "USDT",
"createTime": "1776052048",
"status": "1",
"payUrl": "https://pay.example.com/order/xxx"
}
}
6. 创建代付订单
| 项目 | 说明 |
|---|---|
| URL | /api/v1/createPayOutOrder |
| Method | POST |
| 鉴权 | 需要 Authorization |
| 签名 | 需要 |
6.1 请求字段
| 字段 | 类型 | 必填 | 是否参与签名 | 说明 |
|---|---|---|---|---|
| merchantId | String | 是 | 是 | 商户 ID |
| merchantOrderNo | String | 是 | 是 | 商户订单号,代付订单内唯一 |
| paymentNo | String | 是 | 是 | 商户通道编码 |
| amount | Decimal | 是 | 是 | 代付金额,必须大于 0 |
| currency | String | 是 | 是 | 币种 |
| notificationUrl | String | 是 | 是 | 平台异步通知商户的回调地址 |
| bankCode | String | 否 | 是,非空时参与 | 收款银行或支付机构编码;如果 channelParams 已包含渠道所需信息,可为空 |
| accountName | String | 否 | 是,非空时参与 | 收款账户名称 |
| accountNo | String | 否 | 是,非空时参与 | 收款账号 |
| channelParams | String | 否 | 是,非空时参与 | 渠道扩展参数 |
| remark | String | 否 | 是,非空时参与 | 备注 |
| manualOrderType | Integer | 否 | 是,非空时参与 | API 默认不传;调试可选 3、4 ,3 :会发生金额的测试订单, 4 : 不会发生金额,可回退订单 |
| sign | String | 是 | 否 | 请求签名 |
签名字段白名单:
merchantId, merchantOrderNo, paymentNo, amount, currency, notificationUrl, bankCode, accountName, accountNo, channelParams, remark, manualOrderType
6.2 请求示例
{
"merchantId": "M10001",
"merchantOrderNo": "PAY202604300001",
"paymentNo": "PAYOUT_A",
"amount": "50.00",
"currency": "USDT",
"notificationUrl": "https://merchant.example.com/pakgopay/notify",
"bankCode": "BANK001",
"accountName": "Alice",
"accountNo": "1234567890",
"remark": "test payout",
"sign": "BASE64_HMAC_SHA256_SIGN"
}
6.3 成功响应 data
data 为 JSON 对象;实际接口外层 data 字段当前以 JSON 字符串形式返回,客户端需要先解析。
| 字段 | 类型 | 说明 |
|---|---|---|
| amount | String | 订单金额 |
| transactionNo | String | 平台交易号,代付以 PAY 开头 |
| merchantOrderNo | String | 商户订单号 |
| currency | String | 币种 |
| createTime | String | 当前代付创建响应为时间戳字符串 |
| status | String | 订单状态码 |
7. 查询订单
| 项目 | 说明 |
|---|---|
| URL | /api/v1/queryOrder |
| Method | POST |
| 鉴权 | 需要 Authorization |
| 签名 | 需要 |
当前实现按商户订单号查询当前月订单;跨月历史订单需要平台另行扩展查询范围。
7.1 请求字段
| 字段 | 类型 | 必填 | 是否参与签名 | 说明 |
|---|---|---|---|---|
| merchantId | String | 是 | 是 | 商户 ID |
| merchantOrderNo | String | 是 | 是 | 商户订单号 |
| orderType | String | 是 | 是 | 订单类型:COLL 代收,PAY 代付 |
| sign | String | 是 | 否 | 请求签名 |
签名字段白名单:
merchantId, merchantOrderNo, orderType
7.2 请求示例
{
"merchantId": "M10001",
"merchantOrderNo": "COLL202604300001",
"orderType": "COLL",
"sign": "BASE64_HMAC_SHA256_SIGN"
}
7.3 成功响应 data
| 字段 | 类型 | 说明 |
|---|---|---|
| merchantOrderNo | String | 商户订单号 |
| transactionNo | String | 平台交易号 |
| amount | String | 订单金额 |
| currency | String | 币种 |
| status | String | 订单状态码 |
| createTime | String | 时间戳字符串 |
| updateTime | String | 时间戳秒字符串 |
| failureReason | String | 失败原因;仅失败订单返回,当前实现可能为空字符串 |
| successCallBackTime | String/null | 成功回调时间;仅成功订单返回 |
8. 查询余额
| 项目 | 说明 |
|---|---|
| URL | /api/v1/balance |
| Method | POST |
| 鉴权 | 需要 Authorization |
| 签名 | 需要 |
8.1 请求字段
| 字段 | 类型 | 必填 | 是否参与签名 | 说明 |
|---|---|---|---|---|
| merchantId | String | 是 | 是 | 商户 ID |
| sign | String | 是 | 否 | 请求签名 |
签名字段白名单:
merchantId
8.2 请求示例
{
"merchantId": "M10001",
"sign": "BASE64_HMAC_SHA256_SIGN"
}
8.3 成功响应 data
data 按币种分组,每个币种包含可用、冻结、总额。
| 字段 | 类型 | 说明 |
|---|---|---|
{currency}.available | String | 可用余额 |
{currency}.frozen | String | 冻结余额 |
{currency}.total | String | 总余额 |
示例:
{
"code": 0,
"message": "success",
"data": {
"USDT": {
"available": "1000.00",
"frozen": "50.00",
"total": "1050.00"
}
}
}
9. 平台异步通知商户
商户在创建订单时传入 notificationUrl,订单终态变化后平台会向该地址发起 POST application/json 通知。
9.1 代收通知字段
| 字段 | 类型 | 是否参与签名 | 说明 |
|---|---|---|---|
| merchantUserId | String | 是 | 商户 ID |
| transactionNo | String | 是 | 平台交易号 |
| merchantOrderNo | String | 是 | 商户订单号 |
| createTime | String | 是 | 订单创建时间,时间戳字符串 |
| amount | String | 是 | 原订单金额,保留 2 位小数 |
| actualAmount | String | 是 | 实际金额,保留 2 位小数 |
| merchantFee | String | 是 | 商户手续费,保留 2 位小数 |
| depositTime | String | 是,非空时参与 | 成功时间,时间戳字符串 |
| notifyTime | String | 是 | 通知发送时间,时间戳字符串 |
| status | String | 是 | 状态名,如 SUCCESS、FAILED |
| origAmount | String | 是 | 原始金额,保留 2 位小数 |
| payerName | String/null | 否,当前为空 | 付款人名称 |
| sign | String | 否 | 平台回调签名 |
9.2 代付通知字段
| 字段 | 类型 | 是否参与签名 | 说明 |
|---|---|---|---|
| merchantUserId | String | 是 | 商户 ID |
| transactionNo | String | 是 | 平台交易号 |
| merchantOrderNo | String | 是 | 商户订单号 |
| createTime | String | 是 | 订单创建时间,时间戳字符串 |
| amount | String | 是 | 原订单金额,保留 2 位小数 |
| actualAmount | String | 是 | 实际金额,保留 2 位小数 |
| merchantFee | String | 是 | 商户手续费,保留 2 位小数 |
| depositTime | String | 是,非空时参与 | 成功时间 ,时间戳字符串 |
| notifyTime | String | 是 | 通知发送时间,时间戳字符串 |
| status | String | 是 | 状态名,如 SUCCESS、FAILED |
| origAmount | String | 是 | 原始金额,保留 2 位小数 |
| fromCardNo | String/null | 否,当前为空 | 出款卡号 |
| sign | String | 否 | 平台回调签名 |
9.3 商户响应要求
平台认为商户通知成功的条件:商户回调接口返回 JSON,且响应体中的 code 为 200。
推荐响应:
{
"code": 200,
"data": "ok"
}
10. 常见错误码
| code | message | 说明 |
|---|---|---|
| 0 | success | 成功 |
| 1 | server internal error | 服务内部错误 |
| 100113 | request time out | 请求超时 |
| 100115 | params is invalid | 参数或签名错误 |
| 100118 | http request error | 请求上游通道失败 |
| 100201 | request param is valid | 订单参数校验失败 |
| 100202 | client ip is not in white list | 请求 IP 不在商户白名单 |
| 100203 | user is not enabled | 商户未启用 |
| 100204 | merchant order id is exits | 商户订单号重复 |
| 100205 | the merchant has no available channels. | 商户无可用通道 |
| 100206 | the order over amount limit. | 订单金额超过限制 |
| 100207 | exceeding the daily/monthly available limit for the channel | 通道日/月限额不足 |
| 100208 | channel is not support this currency | 通道不支持币种 |
| 100209 | merchant is not support collection | 商户不支持代收 |
| 100210 | merchant is not support payout | 商户不支持代付 |
| 100211 | merchantOrderNo is not exits | 商户订单号不存在 |
| 100212 | user has no balance data | 商户无余额数据 |
| 100213 | merchants with insufficient available balance | 商户余额不足 |
11. 签名验证
平台请求与平台回调均使用同一套签名规则:按字段白名单过滤、移除 null 和空字符串、按字段名升序拼接 key=value,再使用 signKey 做 HMAC-SHA256 并进行 Base64 编码。详细说明见 签名验证说明。
12. 联调检查清单
| 检查项 | 要求 |
|---|---|
| Header | Authorization 使用平台分配的 apiKey |
| 签名 | 按接口白名单字段签名,排除 sign |
| 金额 | 使用普通十进制字符串,避免科学计数法 |
| 商户订单号 | 同一订单类型下保持唯一 |
| IP 白名单 | 代收、代付分别配置对应请求源 IP 白名单 |
| 回调验签 | 使用同一 signKey 按 HMAC-SHA256 + Base64 验签 |
| 回调响应 | 返回 JSON 且 code=200 |