API 参考:webhook
Webhook 用于在事件发生后将消息推送至您的服务器。在更多 → 商户 API里给您的应用设好 Webhook URL(选填);此后您订阅的每一个事件,平台都会 POST 一段带签名的 JSON。
外层结构
{
"update_id": 123,
"update_type": "invoice_paid",
"request_date": "2026-08-11T12:00:00Z",
"payload": { … }
}
同一个事件重复投递时,update_id 保持不变——请拿它做去重。request_date 记录每次投递尝试
的时间。payload 是该事件类型的完整对象:账单类事件给账单对象,红包类给红包对象,转账类给转账对象,订阅类给订阅对象(各自的结构见对应的参考页面)。
事件类型
update_type | 什么时候触发 | Payload |
|---|---|---|
invoice_paid | 账单被付掉——无需另行订阅 | 账单对象 |
invoice_expired | 账单到了期限还没付 | 账单对象 |
check_activated | 红包或其中一位收款人的份额被领取 | 红包对象;名单红包领取还含 activated_slot |
check_expired | 名单红包到期,未领份额退回应用 | 红包对象,含 recipients 及各项的 claimed_at |
transfer_completed | 转账完成,或链上打款已确认 | 转账或提现对象 |
transfer_returned | 未领取的待领取转账退回应用,或链上打款失败并退回锁定资金 | 转账或提现对象 |
refund_completed | 一笔退款执行完成 | 带 refunded_* 字段的账单对象 |
subscription_activated | 用户完成了套餐授权 | 订阅对象 |
subscription_charged | 某一期扣款完成——charge.kind 说明是哪一种:initial、renewal 或 resubscribe | 订阅对象加 charge:{period_no, kind, asset, amount, fee, paid_at} |
subscription_cancelled | 订阅被任意一方取消 | 订阅对象 |
subscription_expired | 宽限期过完仍未付款 | 订阅对象 |
应用中创建的链上打款也使用这些转账事件。其 payload 包含 kind: "withdrawal"、network、address、txid 等链上字段,状态为 completed 或 failed。其 transfer_id 使用独立的 ID 序列,使用前请先按 kind 区分 payload。可下载的 OpenAPI 参考说明了两种结构。
除 invoice_paid 之外的一切都要主动订阅(这是相对 Crypto Bot 的扩展——严格照 Crypto Bot
写的消费端,除非您自己去开,否则永远碰不到一个陌生的 update_type)。请在应用的 Webhook 部分,通过额外的 webhook 事件为各应用选择订阅;开关使用上表中的标识符。接收事件前须保存 webhook URL。
怎么验签
每次投递都带着 TgPayCrypto-API-Signature 请求头(TgCryptoPay-API-Signature 和 Crypto-Pay-API-Signature
是取值相同的兼容别名):对原始请求体计算 HMAC-SHA256,并以十六进制表示结果,密钥是您应用主 API 令牌的
SHA-256 摘要。这就是 Crypto Bot 那套方案,所以现成的验签代码原样就能用:
import hashlib, hmac
secret = hashlib.sha256(API_TOKEN.encode()).digest()
expected = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, headers["TgPayCrypto-API-Signature"])
请对收到的原始字节验签——重新序列化可能改变字节内容,导致验签失败。只有主 令牌签名;受限令牌永远不签。更换主令牌会立刻给 webhook 签名换密钥,所以请在同一次操作里 把服务器上的密钥也更新掉。
投递和重试
- 在单次尝试超时前收到 2xx 响应,即视为投递成功。请及时响应,将耗时任务另行处理。
- 错误状态码、超时或连接失败会触发重试,间隔逐渐延长,直至达到平台的尝试次数上限。投递不保证成功;服务中断后,请用
getInvoices核对付款。 - 最后一次尝试之后,这次投递就丢弃了。webhook URL 本身永远不会被自动停用——一个不稳的接收端 不会悄悄把您的应用退订掉。
- 正因为有重试,您的处理逻辑必须是幂等的:处理之前先按
update_id去重。
⚠️ 先验签,再发货
任何人都能往您的 webhook URL 上 POST。在签名校验通过之前,请把请求体当作不可信输入:别发货、
别给用户入账、别把什么标记成已付款。安全的顺序是:验签 → 按 update_id 去重 → 处理。
这篇文章对您有帮助吗?
谢谢反馈。