Webhook 验签必须用原始请求体吗
现象#
本地用同样密钥算出的 HMAC 与 X-Shopify-Hmac-Sha256 不一致,改了几次编码仍失败。
原因#
- 框架先把 JSON 解析再序列化,字段顺序与空格变化导致字节不一致
- 对 body 做了字符集转换(如转成对象再
json.dumps) - 签名用了 Base64 编码后的 body 而不是原始字节
- 密钥取错(用了 API secret 之外的字段)
处理步骤#
- 在路由层保留原始字节(如 Express 的
rawBody、FastAPI 的await request.body()) - 对原始字节做 HMAC-SHA256,再用 Base64 编码,与请求头逐字节比较
- 比较时使用恒定时间比较函数,避免时序侧信道
- 确认密钥是应用的 API secret key,而不是 access token
验收标准#
对所有真实回调验签通过;篡改 body 后验签失败并返回 401。
本文由 风格技术 技术团队整理,适用于 Shopify 标准版与 Plus 店铺。Shopify 平台能力迭代较快,具体操作路径与字段以官方文档和店铺后台实际版本为准。