跳到主要内容

验签与重试

保存签名密钥​

创建 Webhook 配置时,平台会返回该配置的签名密钥。请在创建后立即将密钥保存到密钥管理服务或服务端环境变量中,不要写入代码、日志或前端页面。后续查询仅返回脱敏后的密钥,无法用于验签。

签名规则​

平台使用 Webhook 配置的密钥,以 HTTP 原始请求体字节作为消息计算 HMAC-SHA256,再将摘要转换为 Base64 编码,并通过 x-wk-signature 请求头发送:

x-wk-signature = Base64(HMAC-SHA256(webhook_secret, raw_request_body))

接收端必须用相同方式计算签名,并与 x-wk-signature 比较。不要先解析再重新序列化 JSON;即使字段和值相同,空格、换行或字段顺序变化也会产生不同的签名。

验签示例​

以下函数均直接接收框架保留的原始请求体,不限定 Webhook URL。请先验签,验签通过并将事件成功入队后再返回 HTTP 200。

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public static boolean verifyWebhookSignature(
byte[] rawPayload, String signature, String secret) throws Exception {
if (signature == null || secret == null) return false;

Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] expected = mac.doFinal(rawPayload);

try {
byte[] received = Base64.getDecoder().decode(signature);
return MessageDigest.isEqual(received, expected);
} catch (IllegalArgumentException exception) {
return false;
}
}

接收端要求​

  • 只接受 HTTPS 请求。
  • 缺少 x-wk-signature 或验签失败时,返回 401 或 403,且不要处理事件。
  • 使用常量时间比较签名,避免时序攻击。
  • 在成功入队后尽快返回 HTTP 200。

幂等处理​

Webhook 可能重复投递或乱序到达。以事件 ID 建立唯一约束,并根据资源版本或事件时间判断是否更新本地状态。不要假设每个事件只会出现一次。

重试策略​

HTTP 请求发生错误,或接收端响应状态码不在 2xx 范围内时,平台会进入重试流程。每次重试间隔为 60 秒,最多重试 3 次。

接收端应在验签通过且事件成功入队后返回 HTTP 200。业务处理应异步执行,避免处理超时触发重复投递。请记录每次投递的事件 ID、响应结果和失败原因;达到重试上限后,可根据事件 ID 查询日志并人工补偿。