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

使用Express JSON中间件接收Shopify Webhook时出现400 Bad Request问题

问题原因
  • Express 中间件是按注册顺序执行的,你添加的express.urlencoded({extended: true})和express.json()属于全局中间件,会在所有路由之前解析请求体。
  • HTTP 请求体只能被解析一次,当这两个全局中间件先处理了 Shopify Webhook 的 POST 请求后,后续 Webhook 路由里的express.text({type: '*/*'})就无法再读取原始未修改的请求体字符串了。
  • Shopify Webhook 的签名验证逻辑完全依赖原始请求体生成校验值,一旦rawBody不是原始内容,验证就会失败,直接返回 400 Bad Request。
解决方案

有两种实用的处理方式,任选其一即可:

方式1:调整路由注册顺序

把 Webhook 路由放在全局解析中间件之前注册,这样全局中间件就不会处理 Webhook 的请求,让路由自身的express.text来解析原始请求体:

// 先注册Webhook路由,确保它先于全局解析中间件执行
app.post('/webhooks', express.text({type: '*/*'}), async (req, res) => {
  try {
    const d = await shopify.webhooks.process({
      rawBody: req.body,
      rawRequest: req,
      rawResponse: res,
    });
    console.log('PROCESS');
  } catch (e) {
    Sentry.captureException(e);
  }
});

// 再注册全局解析中间件,处理其他路由的请求
app.use(express.urlencoded({extended: true}));
app.use(express.json());

方式2:限制全局中间件的作用范围

给全局解析中间件添加路径过滤,只让它们处理非 Webhook 路径的请求:

// 仅对/webhooks以外的路径应用解析中间件
app.use(/^(?!\/webhooks).*/, express.urlencoded({extended: true}));
app.use(/^(?!\/webhooks).*/, express.json());

// 之后注册Webhook路由
app.post('/webhooks', express.text({type: '*/*'}), async (req, res) => {
  try {
    const d = await shopify.webhooks.process({
      rawBody: req.body,
      rawRequest: req,
      rawResponse: res,
    });
    console.log('PROCESS');
  } catch (e) {
    Sentry.captureException(e);
  }
});

内容的提问来源于stack exchange,提问作者Ömer Ok

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:12:07