跳转到主要内容

概述

Webhooks 让您在账户发生重要事件时自动收到 HTTP 通知,例如支付已确认、退款已处理或提现已完成。

可用事件

Payload 结构

所有 webhook 都遵循相同的基础结构:

子账户

当事件属于某个子账户时,subAccount 字段带有该子账户的 reference:
如果子账户没有登记自己的 webhook 端点,它的事件将投递到主账户的端点。 这正是 subAccount 至关重要的原因:由它说明事件属于哪个钱包。请始终使用该字段把事件记入正确的钱包——切勿假定主账户端点收到的所有事件都属于主账户。

发送的请求头

每个 webhook 请求都包含以下请求头:

验证签名

每个 webhook 都使用 HMAC-SHA256 签名,密钥为您端点的 secret (仅在创建时显示一次)。请按以下步骤验证:
  1. 以您的 secret 为密钥,对请求的原始 body 计算 HMAC-SHA256
  2. 在十六进制结果前加上前缀 sha256=
  3. 使用恒定时间比较,与 X-BrazilPix-Signature 请求头进行比对
Node.js (crypto)
请始终使用恒定时间比较(timingSafeEqual)以防止时序攻击。 切勿使用 === 比较签名。

Payload 示例

payment_completed

PIX 支付确认时发送。
webhook 中的 split 是实际分配的结果,而不是您在创建收款时请求的内容。当账户手续费在收款创建与支付之间发生变化时,两者会出现差异:净额缩小,各笔分账按发送顺序被削减,而不是让结算失败。与钱包账单对账时,请始终使用 webhook 中的金额——切勿使用您在请求中发送的金额。该字段仅在发生分账时出现;没有 split 的收款不会带有该键。

密钥直接收款

当您的账户有一个已开通直接收款的 PIX 密钥时,未创建收款单而直接发送到该密钥的 PIX 同样会产生 payment_completed。由于没有收款单,事件不带 externalReference 和 metadata,并由 pixKey 字段说明是哪个密钥收到了款项:
该金额与任何已确认的支付一样计入余额,并按账户的 PIX 手续费计费。对账时请使用 e2eId(每笔 PIX 唯一)和 pixKey;比较密钥时不区分大小写。为密钥开通直接收款由我们的团队完成——请联系客服。

payment_expired

PIX 支付未经确认即过期时发送。

payment_failed

当一笔 PIX 支付已收到但无法入账时发送——目前是指账户拦截法人付款人(CNPJ)入账的情况。该金额不会计入您的余额,不产生手续费,并自动退回付款人。blockedDeposit.refund 说明退回的进度。
退回由支付机构在拦截后立即执行。webhook 中的 refund.status 是发送时刻的状态;退回的 E2E(refund.e2eId)通常在几秒后才到达——请查询 GET /transactions/{id} 获取最终数据,并据此答复付款人。

refund_completed

退款处理完成时发送。
退款中 netAmount 的约定:表示事件的收款方(最终客户)实际收到的金额——即退款的全额。退款手续费从商户余额中单独扣除。商户为该笔退款承担的总成本为 amount + feeAmount。

withdrawal_completed

提现成功处理时发送。

withdrawal_failed

提现被拒绝或失败时发送。

withdrawal_reversed

提现被 PSP 冲正时发送。

balance_block_created

余额冻结创建时发送(MED、司法或行政)。

balance_block_approved

余额冻结获批准、金额退回原付款人时发送。

balance_block_rejected

余额冻结被驳回、金额退回商户可用余额时发送。

最佳实践

尽快返回 200 OK 状态。如有需要,请异步处理 webhook。
使用 eventId 避免重复处理同一事件。投递失败时 webhook 可能会被重新发送。
端点请仅使用 HTTPS,以确保数据安全。

重试

如果您的端点未返回 2xx 状态,我们将尝试重新发送 webhook:
  • 5 次尝试,采用指数退避
  • 初始间隔:2 秒
  • 最大间隔:两次尝试之间约 30 秒
5 次尝试均未成功后,该 webhook 将被标记为失败。