Skip to main content
Webhook 会将您账户的事件推送到您自己的 HTTPS 回调地址,并附带加密签名。

创建订阅

  • event_type:下表中的事件之一,或使用 * 订阅全部事件。
  • callback_url:必须为 HTTPS;localhost 和私有 IP 会被拒绝——本地开发请使用 HTTPS 隧道。
  • secret:至少 16 个字符;用于对每次投递签名。加密存储,无法再次获取。
订阅接收的是您账户的事件。您可以随时列出当前有效的订阅:

停用和重新启用订阅

当某个回调不再使用时,请将其停用而不是删除(订阅永远不会被删除: 会保持 disabled 状态,您可以随时重新启用):
如需重新启用,使用 { "status": "active" } 发起同样的调用。
  • 该开关只影响未来的事件:disabled 状态的订阅停止接收新事件, 但已排队的投递仍会发出。
  • 幂等:重复当前状态会返回 200,不会有任何变化。
  • 您只能操作自己账户的订阅:其他账户的订阅会返回 404(与不存在的 订阅无法区分)。

事件

各事件的载荷

在 payout_status_changed 中,技术筛查更新在任何扣款前可以为 pending。 最终更新为 completed 或 failed(若为 failed,在您收到该事件时扣款已完成退还)。 crypto_withdrawal_status_changed 使用 completed 或 failed。 对于 payout_status_changed,status_code 和 status_message 是核心报告的规范化结果。 当通道没有提供更多细节时,status_message 可以为空;平台会在投递前清理它, 其中不会包含上游服务商身份。

扣款前的终态失败

如果筛查在扣款路径前失败,事件可以以终态 status: "failed" 发送,并带有 predebit_failure: true 和 funds_debited: false;不包含 receipt_url。扣款后的失败不同:准确的 扣款金额会在终态事件前退回。平台也可能持久化非终态的转换修订,因此同一 payout 可能产生多次 payout_status_changed 投递;请按 X-Webhook-Event-ID 去重,不要创建第二笔 payout。

投递格式

每次投递都是一个 JSON POST,带有以下请求头:

验证签名

CBPay 会在每次平台 webhook 投递中同时发送两个签名 header。V1 仍然有效 并会继续发送,因此采用 V2 不会造成兼容性破坏。新的集成应优先验证 V2, 并在迁移现有接收端时保留 V1 fallback。 两种输入在适用时都使用同一请求中的 X-Webhook-Timestamp、 X-Webhook-Event 和 X-Webhook-Event-ID。结果是使用订阅密钥计算的 小写十六进制 HMAC-SHA256。V2 将事件类型和事件 ID 绑定到签名中,因此 不要从重新序列化的 JSON payload 中读取这些值。X-Webhook-Delivery-ID 用于投递追踪;请使用 X-Webhook-Event-ID 去重。
HMAC 必须基于原始请求体(收到的字节原样)计算,而不是重新序列化后的 JSON。请拒绝过旧的时间戳(超过 5 分钟),以防止重放攻击。

重试与幂等性

  • 您的端点必须在超时前返回 2xx;否则将触发重试。
  • 最多 5 次尝试,采用递增退避:
  • 使用 X-Webhook-Event-ID 去重:同一事件可能送达多次(至少一次投递语义)。
  • 如果 5 次尝试全部失败,该事件不会再次发送——请通过资源的 GET 接口恢复状态(这也是任何流程都不应只依赖 webhook 的原因)。

您的幂等键会随负载返回

当事件来自您使用 idempotency_key 创建的操作(payout、银行卡 payin、加密提现、隔离钱包发送、退款……)时,负载会以 idempotency_key 字段将其带回——无需额外 GET 即可将通知与您自己的参考号对账。
  • 该字段为可选:仅当原始请求携带非空键时才出现,否则省略。由平台自身创建的操作永远不会暴露内部键。
  • 覆盖事件:payout_status_changed、payin_credited、payin_settlement_scheduled、payin_expired、payin_refunded、crypto_withdrawal_status_changed 和 wallet_send_status_changed。transfer_received 不携带该字段。
  • payin 资源在 GET /v1/payins/{id} 中也会返回该字段。

最佳实践

  • 立即返回 200,在后台异步处理。
  • 记录 X-Webhook-Delivery-ID 以便追溯。
  • 关键状态不要只依赖 webhook:您随时可以通过 API 查询对象(GET /v1/payouts/{id} 等)。

banking_virtual_iban_inbound

This event reports an inbound EUR transfer received by an owned virtual IBAN. The event is normalized before delivery; consumers should deduplicate by the event ID and fetch the banking operation or virtual account when they need the latest state. The event does not expose an upstream provider identity.

admin_announcement

当组织管理员批准的 broadcast 到达账户通知渠道时,会发出此账户范围事件。 载荷是本地化纯文本,绝不是 HTML:
事件只发送给 campaign 选中的账户。它可以通过账户 webhook 订阅和账户 event stream 接收;请使用 X-Webhook-Event-ID 对投递去重。

dispute_status_changed

签名 payload 和状态变化见争议指南。

收款资产字段

payin_credited 始终包含 credit_asset,本地法币增加 fiat_credited;payin_refunded 增加 debited_asset/debited_amount。不新增事件。
最后修改于 2026年9月24日