加密支付 Webhook:事件、安全与可靠的订单履约
Webhook 是你的商店得知一笔加密付款已最终确认的时刻。本文介绍如何设计安全、幂等、稳定可靠的处理程序,并附事件对照表和上线检查清单。

加密支付 Webhook是支付网关在账单状态每次变化时发送到你服务器的 HTTP 请求:转账已检测到、链上已确认、少付、多付或已过期。你的处理程序校验签名、更新订单并触发履约。由于加密付款是异步到达的——往往在客户离开页面几分钟之后——真正可信的依据是 Webhook,而不是浏览器。
本文聚焦集成中的 Webhook 部分:会收到哪些事件、如何校验、同一事件到达两次时如何安全处理,以及如何测试和监控。创建账单请参阅加密支付 API 集成指南。
为什么用 Webhook,而不是轮询或跳转?
- 跳转不是证据——客户回到“感谢”页面,并不能说明钱已到账。
- 轮询很浪费——每隔几秒就为每张未完成账单调用 API,无法扩展而且仍有延迟。
- Webhook 是推送——一有变化网关就会通知你,并附带可校验的签名。
你会收到的事件
| 事件 | 含义 | 处理程序应做什么 |
|---|---|---|
| invoice.paid | 已检测到转账,等待确认 | 显示“已收到付款,确认中”;暂不发货 |
| invoice.confirmed | 已达到所需确认数 | 标记已付并履约 |
| invoice.underpaid | 少于应付金额,低于容差 | 告知客户差额,等待补款 |
| invoice.overpaid | 到账多于应付 | 正常履约,并决定如何处理差额 |
| invoice.expired | 期限内无有效付款 | 释放预留库存,订单保持未付 |
以上是 mistKET 使用的事件名称。其他网关的状态类似但名称不同,请在一个地方统一映射到你的订单状态。
校验签名
任何人都可以向公开 URL 发送 POST 请求,因此每个 Webhook 都必须验证身份。mistKET 用 HMAC-SHA256 对每次投递签名,并发送以下请求头:
- X-Mistket-Event——事件名称。
- X-Mistket-Timestamp——参与签名的 Unix 时间戳。
- X-Mistket-Signature——
sha256=加上用你的 Webhook 密钥对{timestamp}.{raw body}计算的 HMAC。 - X-Mistket-Delivery——用于日志记录的投递 ID。
- 读取原始请求体——在解析 JSON 之前读取,因为重新编码会改变字节。
- 重新计算 HMAC——对时间戳、一个点号和原始请求体,使用 Webhook 密钥计算。
- 常量时间比较——使用
hash_equals、hmac.compare_digest或crypto.timingSafeEqual。 - 拒绝过旧的时间戳——例如超过五分钟,以防重放攻击。
- 然后再解析和处理——并尽快返回 2xx。
该机制遵循标准 HMAC 模式;密钥只保存在服务器上,一旦泄露立即轮换。
选择并保护回调 URL
使用独立的 HTTPS 路径,例如 /webhooks/mistket,与普通页面分开,并在创建每张账单时作为回调 URL 传入。把它排除在 CSRF 防护、缓存和跳转之外:301 跳转或缓存响应是 Webhook 静默失败的常见原因。不要要求会话 Cookie——网关不是已登录用户,HMAC 签名才是身份验证。最后,为每次投递记录事件、订单号和响应码,这样几秒钟就能回答“Webhook 到了吗?”。
幂等性:同一事件可能到达两次
如果你的接口超时或返回错误,网关会在数小时内以递增间隔重试。网络抖动也可能重复投递你已处理过的事件。因此处理程序必须是幂等的:
- 以订单号为键——找到账单关联的订单。
- 检查当前状态——若订单已履约,直接确认收到,不做其他操作。
- 使用事务或锁——防止两次并行投递都发货。
- 保存投递 ID——便于排查重复投递。
围绕事件设计订单状态
一个简单的状态机就能避免大多数问题:待付款 → 确认中(收到 paid)→ 已付款(收到 confirmed)→ 已履约,另有 少付 和 已过期 分支。只允许向前流转:在 invoice.confirmed 之后到达的 invoice.paid 绝不能让订单回退。过期账单上的延迟付款应生成待审核记录,而不是悄悄重新打开订单。
处理棘手情况
- 少付——准确告知客户还差多少,并说明可在同一付款页面补齐;部分付款会累计。
- 多付——正常履约,再按你的政策决定计入余额还是转账退款。
- 过期——释放库存,若客户仍想购买,提供新账单。
- 网络错误——由客服而非代码处理;在收银页清楚标明网络即可预防。
测试与监控
- 开放测试接口——通过 HTTPS,记录请求头和原始请求体。
- 触发每种事件——用小额真实付款触发 paid、confirmed、underpaid、overpaid 和 expired。
- 重放一次投递——确认处理程序会忽略重复事件。
- 破坏签名——改动一个字节,确认请求被拒绝。
- 查看投递日志——商家后台会显示每次尝试、响应码和交易哈希。
- 失败告警——非 2xx 响应激增意味着订单没有被履约。
机器人和付费社群遵循同样的模式;在在 Telegram 机器人中接受加密付款一文中可以看到它如何融入聊天流程。
mistKET 的 Webhook
mistKET 为每种账单状态发送 HMAC 签名的 Webhook,对失败的投递按递增间隔重试,并在商家后台显示投递日志、应收与实收金额以及交易哈希。API 请求也以同样方式签名,一个辅助函数即可覆盖双向。
在开发者专区查看请求和 Webhook 示例,了解价格,并通过商家登录管理密钥。如需接入,请通过 Telegram @mistnetwork 申请。


