Skip to content

回调(事件) ​

充值入账、提现状态变化时,我们向你配置的回调地址 POST 一条事件。

事件格式 ​

json
{
  "event_id": "evt_1987654321098754",
  "type": "deposit.confirmed",
  "created_at": "1762650000000",
  "data": { "deposit_id": "1987654321098752", "status": "CONFIRMED", "amount": "12.5", "...": "..." }
}

data 与对应 GET 接口的返回完全一致,是事件发生时的快照:

type触发时机data 等同于
deposit.confirmed充值达到确认数、已入账GET /v1/deposits/{deposit_id}
withdraw.broadcasted提现交易已广播,等待链上确认GET /v1/withdraws/{withdraw_id}
withdraw.confirmed提现已确认(终态);池内转账直接进入此状态同上
withdraw.failed提现失败(终态),原因见 data.reason;资金池商户创建时冻结的金额已解冻同上
withdraw.rejected提现审核被拒(终态),原因见 data.reason;资金池商户创建时冻结的金额已解冻同上

以后可能新增事件类型,不认识的 type 请直接返回 2xx 忽略。

请求头与验签 ​

请求头说明
X-Webhook-Id等于 event_id
X-Timestamp本次投递时间,Unix 毫秒(每次重试都会变)
X-Signaturehex(HMAC-SHA256(回调密钥, X-Timestamp + "\n" + body))

验签时必须用收到的原始 body 字节,不要先解析 JSON 再序列化。建议同时拒绝时间戳与本机相差超过 5 分钟的请求,防止重放。

测试数据:回调密钥 whsec-test,X-Timestamp: 1762650000000,body 为

json
{"event_id":"evt_1","type":"deposit.confirmed","created_at":"1762650000000","data":{}}

签名应为 31c194e933a5f62c752bace322b571f8e281edf589c97c5b672ac245e8a54664。各语言实现见 多语言示例。

应答、重试与去重 ​

  • 返回任意 2xx 视为成功,响应体不限。单次请求超时 30 秒。
  • 失败(非 2xx、超时、连不上)时:每轮先即时重试最多 3 次,仍失败则按退避等待下一轮——1 秒、3 秒、10 秒、30 秒、2 分钟、5 分钟、10 分钟、30 分钟、2 小时、6 小时,之后每 12 小时一轮;共 15 轮(约 3 天)仍失败则标记为 FAILED 并停止。
  • 同一事件可能送达多次(重试、手动重发),请按 event_id 去重,处理逻辑要幂等。
  • 事件可能乱序。以 data.status 为准;需要时用 GET 接口查最新状态。
  • 请尽快返回 2xx,耗时的业务放到异步队列里处理。

漏收补救 ​

  • GET /v1/events?delivery_status=FAILED 找出没送达的事件,按 data 补处理;
  • POST /v1/events/{event_id}/resend 让我们立即按当前回调地址重新投递一次(event_id 不变);
  • 充值没有回调也查不到记录时(例如链上推送遗漏),可用 POST /v1/deposits/rescan 按交易哈希补单。