Webhook HMAC 用 hex 算出来永远对不上怎么修
现象#
同一个 body、同一个 secret,本地算出的签名和 header 里的值长度差一倍,比较永远 false,端点持续返回 401,Logs 里一片红色。
原因#
- X-Shopify-Hmac-Sha256 是 Base64 摘要,digest('hex') 得到的是十六进制,字符集不同
- 比较时一边按 utf8 转 Buffer、一边按 base64 解码,字节序列不同,timingSafeEqual 直接抛错
- 部分框架把 header 名转小写或合并成数组,取到的是 undefined 而不是签名字符串
- 轮换 client secret 后一小时内签名可能仍用旧密钥,刚换完的那批请求必然失败
处理步骤#
- 摘要固定为
createHmac('sha256', secret).update(rawBody).digest('base64') - 两边都先
Buffer.from(x, 'base64')再比,长度不等直接判失败 - header 用
req.headers['x-shopify-hmac-sha256']取,数组时取第一个元素 - 把收到的 header 与本地结果同条日志打印,确认都是 44 位 Base64
- 轮换密钥后等一小时再复测,或临时用新旧两个 secret 各算一次
验收标准#
日志里两个 Base64 串完全一致,端点返回 200,连续 10 条投递都不再出现 401。
本文由 风格技术 技术团队整理,适用于 Shopify 标准版与 Plus 店铺。Shopify 平台能力迭代较快,具体操作路径与字段以官方文档和店铺后台实际版本为准。