# 回调交易结果

# 回调接口验签

验签目的

API 请求在通过公网传输过程中,有被中间人篡改的风险。为确保回调数据的完整性与可信性,平台支持并强烈建议商户在接收回调时进行签名验签

设置方式

登录【收银台后台】→【开发者中心】→【回调地址】→ 添加/编辑。

验签步骤

验签逻辑与接口请求签名大体一致,区别在于数据来源为接收到的回调内容

  1. 获取签名

从 HTTP 请求 Header 中读取签名字段:

sign: {平台生成的签名字符串}
  1. 获取回调参数体

将回调 Body 中的 JSON 参数以 key-value 形式存入一个 Map(字典)结构中。

  1. 添加公共参数

从 Header 中再取出以下字段,并一并加入 Map 中参与验签:

  • access_key
  • timestamp
  • nonce
  1. 构造待签名字符串

将 Map 中的所有 key 按照 ASCII 字典序从小到大排序,并拼接为如下格式的字符串:

key1=value1&key2=value2&...&keyN=valueN
  1. 执行签名计算

使用商户后台绑定的 secret_key 对上述字符串进行以下处理:

  • 使用 HMAC_SHA1 算法加密
  • 将结果进行 Base64 编码,得到本地 sign
  1. 比对签名

将本地生成的 sign 与 Header 中平台传来的 sign 进行比对:

  • ✅ 一致 → 验签通过,可处理业务逻辑
  • ❌ 不一致 → 拒绝处理,建议记录日志以供排查

# 收款回调

回调数据示例

{
  "currencyType": "USD",
  "orderActualAmount": "1",
  "orderId": "OCRYPPAID202307310902391690794159441DOCKER020000000400001108",
  "tradeHash": "0x806d5b3da29c8426a644e2ded85b865b37504dcdec4cfb9db13af5e962815528",
  "orderFee": "1",
  "orderStatus": "Completed",
  "chainType": "ETH",
  "externalOrderId": "402297358314559082",
  "addressTo": "0xe072c63c1e04f8c6f36133f6629f66778147d5d8",
  "orderAmount": "1",
  "orderTime": 1690794159000,
  "exchangeRate": "0.983",
  "orderStatusCode": 4,
  "orderPayTime": 1690794247000,
  "addressFrom": "0x0cbfd17ae9e1d6d881b2cade71277f48abf64d24",
  "tokenType": "USDT"
}

回调字段说明

参数名 类型 描述
currencyType String 法币类型(如 USD)
orderActualAmount String 实际支付金额
orderId String 平台订单ID
tradeHash String 区块链交易哈希
orderFee String 手续费金额
orderStatus String 订单状态文本(如 Completed)
orderStatusCode int64 订单状态码(见下方说明)
chainType String 区块链主链类型(如 ETH)
externalOrderId String 商户订单号
addressTo String 收款地址
addressFrom String 出款地址
orderAmount String 原始订单金额
orderTime int64 订单创建时间(Unix 毫秒)
orderPayTime int64 实际支付时间(Unix 毫秒)
exchangeRate String 汇率
tokenType String 加密代币类型(如 USDT)
markStatus String 标记状态(如需支持)
errorMsg String 错误信息(中文)
errorMsgEn String 错误信息(英文)

订单状态码说明(orderStatusCode)

状态码 描述
1 待支付:订单创建成功,等待用户付款
2 链上确认中:用户点击“我已付款”,等待链上确认
4 已完成:支付成功,平台会自动发送回调通知
8 支付金额不匹配:仍回调通知,请根据实际金额入账
16 超时收款:用户未按时支付,不再回调通知
32 未支付:地址过期回收,不再处理

⚠️ 回调处理建议

  • 回调一旦验签通过且 orderStatusCode == 4,即可视为支付成功,应立即执行上分 / 业务处理。
  • 平台可能因网络等原因重复推送回调,请务必做好幂等处理,避免重复入账。
  • 若验签失败或数据异常,请记录日志并返回错误响应,平台将在最多 30 分钟内自动重试 2 次。

手动回调说明

商户可在后台订单管理中手动触发回调,用于修复漏回调情况。但请注意:

  • 若订单状态非终态(如:待支付、确认中),不建议手动回调。
  • 若手动回调时订单尚未完成,平台在状态变为终态后仍会再次回调,请商户做好业务层面的去重处理。

# 代付回调

回调数据示例

{
  "orderAmount": "1",
  "orderTime": 1690794160000,
  "orderId": "OCRYPDRAW202307310902401690794160841DOCKER020000000200001109",
  "orderStatusCode": 2,
  "tradeHash": "0xe9d043c9cbdb96ed7a71c5a0923baabe9e23316b3f1b0a01975bcd6d69b41fa3",
  "orderFee": "0.01",
  "orderStatus": "Completed",
  "orderPayTime": 1690794182000,
  "chainType": "ETH",
  "externalOrderId": "622257420681202921",
  "tokenType": "USDT",
  "addressTo": "0xa8666442fA7583F783a169CC9F5449ec660295E8"
}

回调字段说明

参数名 类型 描述
orderAmount String 订单金额
orderTime int64 订单创建时间(Unix 毫秒)
orderId String 平台订单ID
orderStatusCode int64 订单状态码(见下方说明)
tradeHash String 区块链交易哈希
orderFee String 手续费金额
orderStatus String 订单状态描述(如 Completed)
orderPayTime int64 出款完成时间(Unix 毫秒)
chainType String 区块链主链类型(如 ETH)
externalOrderId String 商户订单号
tokenType String 加密代币类型(如 USDT)
addressTo String 收款地址

订单状态码说明(orderStatusCode)

状态码 描述
1 已受理
2 已完成(出款成功)
4 出款失败
8 待审批
16 拒绝出款

⚠️ 回调处理建议

  • orderStatusCode == 2 且验签通过,即可确认出款成功,请执行上分 / 发货 / 状态更新等操作。
  • 回调推送支持多次重发,请务必支持幂等性处理。
  • 若返回非 200 响应或验签失败,平台将尝试再次回调。

手动回调说明

商户可登录后台进行手动触发回调操作。请注意以下事项:

  • 不建议对“非终态订单”发起手动回调,如:状态为“已受理”、“待审批”等;
  • 若手动回调的订单仍处于非终态,未来状态变更为终态时平台仍将再次回调,商户需做好业务层面的冗余处理;

# 回调响应

说明

  • 所有回调均包含签名字段,建议商户务必对回调进行验签,确保回调内容未被篡改。
  • 商户在收到回调数据并处理完成后,需以 JSON格式 响应网关如下数据:

示例响应(成功)

{
  "code": 200,
  "success": true
}

回调补发机制说明(重要)🔥

为确保回调通知的稳定送达与业务一致性,平台设计了多次重试策略。当商户系统未能成功响应回调时(如网络超时、返回非200状态码等),系统将按以下规则进行回调补发:

回调重试节奏(共 4 次):

尝试次数 间隔时间(约) 说明
第 1 次 约 2 分钟后 首次失败后触发第一次重试
第 2 次 约 2 分钟后 第一次充实失败后触发第二次重试
第 3 次 再约 11分钟后 第二次重试失败后再次重试
第 4 次 再约 2分钟后 第三次重试失败后进入下一次重试

注意:以上间隔时间为系统内部调度间隔,商户后台所记录的“回调时间”包含了商户处理/响应时间,因此显示上可能与实际推送时间存在 1 分钟左右误差。

实际情况提醒

  • 当线上订单量较大时,回调可能存在队列延迟,请确保服务端支持高并发处理能力;
  • 每次回调均为幂等操作,建议商户侧务必支持幂等判断;
  • 最多 4 次重试推送仍失败后,则不再自动重试,建议通过后台手动触发回调。

回调响应参数

Param Type Required Description
code int 状态码,成功为 200
success boolean 响应是否成功

回调响应要求

商户服务需返回如下标准响应:

{
  "code": 200,
  "success": true
}

响应类型

HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8

⚠️ 特别说明

  • 平台只判断 HTTP Status Code 是否为 200,只要状态码为 200,即视为回调成功,不再校验响应内容
  • 若返回非 200 状态(如 500 / 404),则会视为失败并触发重试机制。

商户建议实践

  • 验签成功且业务处理完成后立即返回 200
  • 若处理失败,记录日志并确保平台后续补发能正常接收。
  • 建议使用异步任务处理回调内容,避免阻塞响应。

# 回调通知 URL 配置

支持两种通知地址配置方式:

  1. 【商户后台】配置统一回调地址
  • 可在「商户后台」→「开发者中心」中配置。
  • 适用于大部分订单共用的回调处理逻辑。

img

2.订单级别手动指定回调地址(notifyUrl)

  • 在创建订单接口中可传 notifyUrl 字段。
  • 若订单中指定了 notifyUrl 参数,则系统将仅使用该地址作为回调通知目标地址

地址优先级说明

订单中的 notifyUrl 优先级高于统一配置的回调地址。

响应状态码优先级说明

平台以 HTTP 响应状态码 (status_code) 是否为 200 作为通知是否成功的唯一判断标准

具体规则如下:

  • 只要商户系统返回 HTTP 200****,平台即认为回调成功
    • 此时即使返回内容不是 { "code": 200, "success": true } 也会被忽略。
  • ❌ 如果返回 status_code ≠ 200(如 400/500)或无响应,则判定为失败,平台将自动进行重试推送。