文档 / 集成

Webhook

账单发生变化时,Coinetic 会向您的服务器发送 POST 请求。Webhook 只是“去查看账单”的信号,而不是付款凭证。

配置

  • 后台 →「密钥与 Webhook」→「添加」。URL 必须为 https://,指向公网地址和 443 端口(沙盒中还可以使用 http://localhost)。
  • Endpoint 的签名密钥只显示一次。最多可配置 5 个有效 Endpoint,每个事件都会发送到所有 Endpoint。

请求

HTTP
POST /webhooks/coinetic HTTP/1.1
Content-Type: application/json
User-Agent: cryptopay-webhooks/1
X-Webhook-Id: evt_3f9c…
X-Webhook-Timestamp: 1760000000
X-Webhook-Signature: v1=5d1e…

{"id":"evt_3f9c…","type":"invoice.paid","created_at":"2026-10-12T15:04:05Z","livemode":true,"data":{"invoice_id":"inv_x7k2…","order_id":"ORDER-1001","status":"paid","paid_amount":"49990000"}}

重试时 X-Webhook-Id 保持不变。轮换签名密钥期间,X-Webhook-Signature 中会包含两个以逗号分隔的签名。技术名称(cryptopay-webhooks/1)属于历史遗留,您无需在自己的系统中修改。

校验签名

text
expected = "v1=" + hex(HMAC-SHA256(webhook_secret, X-Webhook-Timestamp + "." + raw_body))
  1. 使用原始请求体,即 JSON 解析之前的字节。
  2. 检查 X-Webhook-Timestamp 与当前时间相差不超过 5 分钟。
  3. 按逗号拆分 X-Webhook-Signature。只要任意一段与预期值一致(使用恒定时间比较),签名即有效。
  4. 不一致时返回 401,且不做任何处理。

参考示例:签名密钥 whsec-0123456789abcdef0123456789abcdef,timestamp 1760000000,请求体 {"id":"evt_1","type":"invoice.paid"} → v1=aceeb56215ba09e7a2923d48f89afb8331f422f2d0a8cf60f76fef69fe06a6a4。

处理

text
校验签名 → 按 X-Webhook-Id 去重 → GET /v1/invoices/{invoice_id}
→ 按 API 返回的状态更新订单(只发货一次)→ 返回 2xx
  • 去重。同一事件可能送达多次。请保存已处理的 X-Webhook-Id;“已发货”标记应与发货操作在同一个事务中写入。
  • 快速响应,10 秒以内。耗时任务请放入队列处理。
  • 响应码:2xx 表示已接收;410 Gone 表示不再重试本次投递;其他任何响应码(包括 3xx,不会跟随重定向)或超时都会触发重试。
  • 请忽略未知的字段和事件类型,后续还会增加新的内容。

四种语言的现成处理程序见快速开始。

重试

10 秒 → 30 秒 → 2 分钟 → 10 分钟 → 30 分钟 → 1 小时 → 3 小时 ×7 → 1 小时,间隔带少量随机抖动。最后一次尝试大约在一天之后。投递失败的事件可以重新发送:后台 →「Webhook」→「重新发送」。

顺序

同一张账单的事件按顺序投递到 Endpoint:上一条投递仍在等待重试时,下一条不会发出。无论上一条最终成功与否,后续事件都会继续发送。因此请以 GET /v1/invoices/{id} 返回的状态为准,而不是依赖事件的先后顺序。不同账单的事件彼此独立。

事件类型

事件触发时机
invoice.detected链上已看到付款
invoice.confirming付款已打包进区块,正在累积确认数
invoice.paid已支付并确认,可以发货(需再次核实)。data.late: true 表示稳定币在过期后到账并已自动计入
invoice.overpaid已支付且有多付
invoice.underpaid已确认金额少于应付金额
invoice.awaiting_payment账单重新等待付款(例如唯一一笔付款因链重组被回滚后)
invoice.expired已过期且未付款
invoice.late_payment过期后使用波动性资产付款
invoice.manual_review付款正在接受 AML 审查
invoice.payment_held付款被 AML 暂扣(隔离)
invoice.reorged包含付款的区块被回滚,状态已重新计算(例如 paid → confirming)
invoice.payment_after_close付款转入了已关闭的账单:不计入订单,可申请退款
invoice.cancelled账单因执行退款而在未付款的情况下关闭
refund.sent退款已执行,data.refund 中包含金额、地址和 tx_hash

计费事件(billing.*)与平台手续费账单相关:已开具、已支付、已逾期、服务暂停及恢复。

数字商品与 invoice.reorged在 paid 之后发生链重组的情况很少见,但确实存在。如果您的商品是即时交付的,请订阅此事件,并将此类情况转交客服处理。

轮换签名密钥

后台 →「更换签名密钥」:Coinetic 开始同时使用新旧两个签名密钥签名。

  1. 在服务器上添加新密钥(同时接受两个密钥)。
  2. 点击「完成轮换」,旧密钥随即被删除。
  3. 从服务器上移除旧密钥。