文档 / 集成
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))- 使用原始请求体,即 JSON 解析之前的字节。
- 检查
X-Webhook-Timestamp与当前时间相差不超过 5 分钟。 - 按逗号拆分
X-Webhook-Signature。只要任意一段与预期值一致(使用恒定时间比较),签名即有效。 - 不一致时返回
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 开始同时使用新旧两个签名密钥签名。
- 在服务器上添加新密钥(同时接受两个密钥)。
- 点击「完成轮换」,旧密钥随即被删除。
- 从服务器上移除旧密钥。