PayZuDocs

收款状态变化时发送到你系统的通知。

您的系统无需反复轮询"付款了吗?",有事件发生时 PayZu 会主动调用您:收款状态变化、反欺诈状态更新、拒付(chargeback)或新的循环扣款周期。

如何配置

在创建收款时(POST /charges)提供 postbackUrl。每当有事件发生,PayZu 都会向该 URL 发送一个 JSON 格式的 POST 请求。

事件

事件类型说明
charge.update支付状态变化
antifraud.update反欺诈分析完成,结果体现在收款的 statusreasonCode
chargeback拒付通知
recurrence.cycle新的循环扣款周期已扣款

Payload 结构

参数说明类型
event触发 webhook 的事件参见事件
data收款的最新数据查询收款返回的值相同
{
  "event": "charge.update",
  "data": {}
}

data 对象的格式与查询收款的响应完全一致。

请求 Header

每个 POST 请求都带有以下 header:

Header说明
Content-Type始终为 application/json
X-Webhook-SignaturePayload 的 HMAC SHA-256 签名,十六进制格式(64 个字符)
X-Webhook-Timestamp发送时刻,自 Unix 纪元起的毫秒数
X-Webhook-Nonce请求的唯一标识符(32 个十六进制字符)

重试

事件发生后会立即进行首次投递。只有当您的 URL 在 5 秒内返回 HTTP 2xx 状态码,投递才视为成功:任何其他状态码或超时的响应均视为失败。

投递失败后,webhook 最多进行 5 次重试。每次失败后,距下一次尝试的间隔逐步增大:各次重试分别在 1 分钟、10 分钟、1 小时、6 小时和 24 小时后进行。此后不再重试。

请尽快响应 webhook(返回一个简单的 200 即可),并异步处理 payload,以免超出 5 秒的限制。由于超时可能导致已处理过的事件被重新投递,消费必须是幂等的:请使用收款的 id 加上状态变化作为去重键。不要用 X-Webhook-Nonce 去重,它标识的是 HTTP 请求,每次重新投递都会变化。

HMAC 验证

每个 webhook 都使用您的 webhook secret 签名,该密钥由 PayZu 随您的 API 凭据一同提供。您的 API 应在处理 payload 之前先验证签名:

提取 x-webhook-timestampx-webhook-noncex-webhook-signature 三个 header。

将 timestamp、nonce 和 payload 的值用 . 连接,得到验证基础字符串:timestamp.nonce.payload

使用您的 webhook secret,对该字符串以 SHA-256 算法生成 HMAC 签名。

将生成的签名与 x-webhook-signature header 的值比较。不一致则拒绝该 webhook。

Node.js 示例,使用 crypto.timingSafeEqual 以恒定时间比较签名:

const crypto = require("node:crypto");

function verifyWebhookSignature(request, webhookSecret) {
  const timestamp = request.headers["x-webhook-timestamp"];
  const nonce = request.headers["x-webhook-nonce"];
  const signature = request.headers["x-webhook-signature"];

  if (typeof signature !== "string" || !/^[0-9a-f]{64}$/i.test(signature)) {
    return false;
  }

  const baseString = `${timestamp}.${nonce}.${request.rawBody}`;
  const expectedSignature = crypto
    .createHmac("sha256", webhookSecret)
    .update(baseString)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature, "hex"),
    Buffer.from(signature, "hex"),
  );
}

HMAC 必须基于请求的原始报文体(raw body)计算,即收到的原样内容,在任何 JSON 解析之前。

Nonce 验证(可选)

x-webhook-nonce header 的值是每个请求唯一且临时的标识符。提取后,检查该 nonce 是否已被记录过:

  • 若该值已被使用过,则拒绝请求,以防范重放攻击(replay attacks)。
  • 若 nonce 是新的,则将其记录为已使用,确保后续调用无法重复使用。

Timestamp 验证(可选)

x-webhook-timestamp header 的值是发送时刻自 Unix 纪元起的毫秒数。将其与当前时间比较:若差值超过 5 分钟,则拒绝请求。此项校验可丢弃已过期的 webhook,避免处理陈旧或潜在恶意的消息。

本页内容