跳到主要内容

Webhook 概览

Webhook 用于向商户系统异步推送 Payin、Payout 的状态变化。创建订单或发起出金的同步响应只代表请求已被接收,不代表资金已经完成处理。

商户系统应同时接入:

  1. Webhook:实时接收状态变化
  2. 查询接口:在 Webhook 丢失、超时或对账时做补偿确认

标准处理流程

  1. 接收 Beyounger 的 HTTP POST 请求
  2. 读取原始请求体 raw_body
  3. 使用 Webhook secret 校验 X-Beyounger-Signature
  4. event_id 做事件幂等
  5. 按业务 ID 做业务幂等,例如 order_idpayout_id
  6. 根据 event_type 更新本地业务状态
  7. 返回 HTTP 2xx

如果验签失败,不要更新业务状态。

请求头

Header说明
Content-Type固定为 application/json
X-Beyounger-Webhook-IdWebhook 配置 ID
X-Beyounger-Event事件类型
X-Beyounger-Delivery-Id本次投递 ID,用于排查重复投递
X-Beyounger-Signature请求签名

签名规则

签名使用原始请求体和 Webhook secret 计算:

hex(HMAC_SHA256(raw_body, webhook_secret))

注意:

  1. 必须使用原始请求体,不要使用重新序列化后的 JSON。
  2. 签名比较应使用 timing-safe compare。
  3. 当前签名不包含时间戳和 nonce,商户必须通过 event_id 做幂等和防重放。

Node.js 示例:

import crypto from 'crypto';

export function verifyWebhook(rawBody, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');

return crypto.timingSafeEqual(
Buffer.from(expected.toLowerCase()),
Buffer.from(String(signature).trim().toLowerCase()),
);
}

事件分类

产品事件用途
Payinacquiring.order.updated收款订单状态变化
Payoutpayout.verify.request请求商户验证出金信息
Payoutpayout.review.approved / payout.review.rejected / payout.review.returned出金审核状态变化
Payoutpayout.execution.processing / payout.execution.completed / payout.execution.failed出金执行状态变化

响应要求

标准状态通知 Webhook:

  1. 商户处理成功后返回任意 HTTP 2xx
  2. 2xx、网络错误、超时都会被视为投递失败
  3. Beyounger 可能重试投递,商户必须保证幂等

验证类 Webhook:

  1. payout.verify.request 需要返回明确 JSON
  2. 通过:{"verified": true}
  3. 拒绝:{"verified": false}
  4. 任何不明确响应都不会被当作通过

幂等建议

建议商户至少保存:

字段用途
event_id防止同一事件重复处理
event_type判断事件语义
business_id对应业务对象 ID,例如 order_idpayout_id
occurred_at排查事件发生时间
X-Beyounger-Delivery-Id排查投递和重试

重复事件建议直接返回 2xx,不要重复发货、重复入账或重复通知用户。

查询补偿

Webhook 用于实时通知,但最终对账建议仍调用查询接口确认:

场景查询接口
Payin 收款订单GET /payment/acquiring/orders/{order_id}
Payin 支付记录排查GET /payment/acquiring/orders/{order_id}/payments
Payout 出金GET /payment/payouts/{payout_id}

最佳实践

  1. Webhook URL 必须使用 HTTPS。
  2. 不要在 Webhook 请求中执行耗时任务,建议先落库再异步处理。
  3. 验签失败直接拒绝,不更新业务状态。
  4. 对重复事件返回 2xx
  5. 对终态事件再调用查询接口做补偿确认。
  6. 不要在日志中打印 Webhook secret。