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

Next.js集成Shopify Webhook遇stream is not readable错误求助

解决Next.js中Shopify GDPR Webhook验证的"stream is not readable"错误

我在开发Shopify应用时,需要添加GDPR Webhook,后端用Next.js实现,写了Webhook验证函数,但运行时抛出InternalServerError: stream is not readable错误。推测是Next.js提前解析了请求体,导致后续读取原始流时出错。原验证代码如下:

export function verifiedShopifyWebhookHandler(
    next: (req, res, body) => Promise
): NextApiHandler {
    return async (req, res) => {
        const hmacHeader = req.headers['x-shopify-hmac-sha256'];
        const rawBody = await getRawBody(req);
        const digest = crypto.createHmac('sha256', process.env.SHOPIFY_API_SECRET).update(rawBody).digest('base64');
        if (digest === hmacHeader) {
            return next(req, res, rawBody);
        }

        const webhookId = req.headers['x-shopify-webhook-id'];

        return res.status(401).end();
    };
}

解决思路及方案

  • 禁用Next.js自动请求体解析
    Next.js默认会自动解析JSON、URL编码表单等请求体,这会直接消耗请求流,导致后续无法读取原始内容。在你的API路由文件中添加config配置,关闭自动解析:
export const config = {
  api: {
    bodyParser: false,
  },
};
  • 调整验证函数适配原始流
    禁用自动解析后,req会是原始的IncomingMessage对象,此时可以正常用getRawBody读取。同时建议添加错误处理,避免流读取失败导致服务崩溃:
import crypto from 'crypto';
import getRawBody from 'raw-body';
import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';

export function verifiedShopifyWebhookHandler(
  next: (req: NextApiRequest, res: NextApiResponse, body: Buffer) => Promise<void>
): NextApiHandler {
  return async (req, res) => {
    try {
      const hmacHeader = req.headers['x-shopify-hmac-sha256'] as string;
      if (!hmacHeader) {
        return res.status(401).end('Missing HMAC header');
      }

      const rawBody = await getRawBody(req, {
        length: req.headers['content-length'],
        limit: '1mb', // 根据Shopify Webhook的实际大小调整
      });

      const digest = crypto
        .createHmac('sha256', process.env.SHOPIFY_API_SECRET!)
        .update(rawBody)
        .digest('base64');

      if (digest === hmacHeader) {
        // 如果后续业务需要JSON格式,可在此处解析原始内容
        // const parsedBody = JSON.parse(rawBody.toString());
        return next(req, res, rawBody);
      }

      return res.status(401).end('Invalid HMAC signature');
    } catch (err) {
      console.error('Webhook verification failed:', err);
      return res.status(500).end('Internal server error');
    }
  };
}

// 路由配置必须添加
export const config = {
  api: {
    bodyParser: false,
  },
};
  • 额外注意事项
    • 确保SHOPIFY_API_SECRET环境变量与Shopify后台配置的密钥完全一致
    • Shopify Webhook默认发送application/json格式,无需修改Content-Type,只需保证读取原始字节用于HMAC验证
    • 测试时可使用Shopify官方的Webhook测试工具,或用curl构造原始请求验证逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:19:47