You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js Express中Shopify Webhook完整性校验失败求助

Shopify Webhook HMAC校验失败的排查建议

我来帮你梳理下这个问题的排查方向,你遇到的情况其实在Express环境里挺常见的,咱们一步步来定位:

  • 先确认req.rawBody是否是真正的原始请求体
    Express默认会用中间件解析请求体,如果你已经加了express.json()或者body-parser,那req.rawBody很可能已经被修改甚至不存在了。正确的做法是在解析中间件里保留原始内容,比如用body-parser的verify选项:

    const bodyParser = require('body-parser');
    app.use(bodyParser.json({
      verify: (req, res, buf) => {
        req.rawBody = buf; // 直接存Buffer,不要转字符串,避免编码问题
      }
    }));
    

    另外,你之前把req.rawBody转成JSON.stringify再处理是错误的!Shopify的HMAC签名是基于原始请求体的字节内容计算的,不是JSON序列化后的字符串——原始请求里的空格、换行符和序列化后的可能不一样,这直接导致签名不匹配。

  • 检查你的APP_SHARED_SECRET是否正确
    一定要确认你用的是Shopify后台对应App的Shared Secret,不是API Key或者Access Token。这个密钥在Shopify Partner Dashboard的App设置里,复制的时候别多了空格、换行或者少了字符,大小写完全敏感。

  • 校验请求头的获取是否正确
    Shopify的签名头是X-Shopify-Hmac-Sha256,注意HTTP请求头在Express里会被转成小写,所以你要通过req.headers['x-shopify-hmac-sha256']来获取,别拼写错了。另外要确保没有代理或者中间件篡改了这个头的值。

  • 修正HMAC计算的代码逻辑
    正确的计算应该直接用原始请求体的Buffer,不需要额外的转换,而且要用timingSafeEqual来做安全的签名对比(避免时序攻击):

    const crypto = require('crypto');
    
    const validateWebhook = (req) => {
      const shopifyHmac = req.headers['x-shopify-hmac-sha256'];
      const hmac = crypto.createHmac('sha256', APP_SHARED_SECRET);
      hmac.update(req.rawBody); // 直接用原始的Buffer
      const digest = hmac.digest('base64');
      
      return crypto.timingSafeEqual(Buffer.from(digest), Buffer.from(shopifyHmac));
    };
    
  • 用命令行辅助测试
    你可以用Shopify后台的Webhook测试工具发送一个测试请求,然后把req.rawBody保存成本地文件,用命令行计算HMAC,对比和Shopify返回的签名是否一致:

    cat raw-body.txt | openssl dgst -sha256 -hmac "你的Shared Secret" -binary | base64
    

    如果命令行计算的结果和Shopify的签名一致,但代码里的不一样,那肯定是代码里处理req.rawBody的环节出了问题。

内容的提问来源于stack exchange,提问作者user269867

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:32:02