验证 Webhook 签名
通过检查 X-Xenonpay-Signature 标头,并将其与使用 webhook 签名密钥计算出的哈希值进行比对,验证 webhook 是否来自 XenonPay。拒绝签名不匹配的任何传送。
签名标头
配置签名密钥后,每次传送都会包含:
X-Xenonpay-Signature: t=1756032000,v1=hexdigest...该标头包含两部分:t 是我们为请求签名时的 Unix 时间戳,v1 是签名。签名计算方式如下:
HMAC-SHA256( key = your webhook secret, message = "{t}.{raw request body}" )编码为小写十六进制。
验证方法
读取接收到的 原始 请求正文。请勿先将其解析为 JSON 再重新序列化——这会改变字节内容并导致签名验证失败。
将
X-Xenonpay-Signature标头解析为t和v1。使用 webhook 密钥作为密钥,对字符串
t+"."+ 原始正文计算HMAC-SHA256。将结果编码为小写十六进制,并使用时序安全比较将其与
v1进行比对。可选:拒绝
t早于当前时间过久的传送,以防止重放攻击。
Node.js 示例
const crypto = require("crypto");
function verifyXenonPaySignature(secret, header, rawBody) {
// header looks like: "t=1756032000,v1=abc123..."
const parts = Object.fromEntries(
header.split(",").map((kv) => kv.split("="))
);
const expected = crypto
.createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1 || "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}您的签名密钥
您的 webhook 签名密钥格式为 whsec_ 后跟随机十六进制字符。请从 webhook 设置中生成或轮换该密钥,并将其安全地存储在服务器上。
如果您设置了 webhook URL,但未配置签名密钥,我们仍会传送事件,但这些事件不会带有签名。请始终配置密钥,并在生产环境中验证签名。
这对您有帮助吗?
这对您有帮助吗?