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

NextJS 13.2.3集成Stripe Webhook签名验证报错求助

NextJS 13.2.3 Stripe Webhook 签名验证问题解决方案

问题背景

结账流程可正常完成并跳转至successUrl,但添加Stripe签名验证后出现两类报错:

  • 初始使用req.json()解析Payload时,触发StripeSignatureVerificationError,提示需传入原始请求体的字符串/Buffer,而非解析后的JS对象
  • 禁用bodyParser尝试获取原始请求体后,又出现No signatures found matching the expected signature for payload,使用micro/raw-body库时遇到req.body为ReadableStream的类型错误

核心原因

Stripe Webhook签名验证完全依赖原始请求体的字节内容,任何对请求体的解析(如req.json())或二次转换(如JSON.stringify())都会改变原始内容的格式(空格、键顺序、数值表示等),导致签名不匹配;同时NextJS 13 App Router默认自动解析请求体,需手动禁用并直接获取原始内容。


正确实现代码(App Router)

在app/api/webhook/stripe/route.ts中编写如下代码:

import { NextRequest, NextResponse } from 'next/server';
import Stripe from 'stripe';

// 初始化Stripe客户端(API版本需与Stripe Dashboard一致)
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2023-10-16',
});

// 禁用NextJS自动解析请求体
export const config = {
  api: {
    bodyParser: false,
  },
};

export async function POST(req: NextRequest) {
  // 获取原始请求体字符串
  const rawBody = await req.text();
  // 获取Stripe签名头
  const signature = req.headers.get('stripe-signature');
  const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!;

  let event: Stripe.Event;

  try {
    // 验证签名并构造Stripe事件
    event = stripe.webhooks.constructEvent(rawBody, signature!, webhookSecret);
  } catch (err) {
    console.error('签名验证失败:', err);
    return NextResponse.json({ error: 'Webhook签名验证失败' }, { status: 400 });
  }

  // 处理具体事件类型
  switch (event.type) {
    case 'checkout.session.completed':
      const session = event.data.object as Stripe.Checkout.Session;
      // 示例逻辑:更新订单状态、发送用户通知等
      console.log('结账完成,Session ID:', session.id);
      break;
    // 可添加其他事件处理逻辑(如payment_intent.succeeded等)
    default:
      console.log(`未处理事件类型: ${event.type}`);
  }

  return NextResponse.json({ received: true }, { status: 200 });
}

常见问题排查

  1. 签名不匹配

    • 确认STRIPE_WEBHOOK_SECRET是Stripe Dashboard中对应Webhook端点的签名密钥(不是API密钥)
    • 本地测试必须使用Stripe CLI转发:stripe listen --forward-to localhost:3000/api/webhook/stripe,避免手动模拟请求导致签名错误
    • 检查中间件/反向代理是否修改了stripe-signature请求头或请求体
  2. 类型错误

    • NextJS 13 App Router中req为NextRequest,无需引入micro或raw-body,直接用req.text()/req.arrayBuffer()获取原始内容即可,避免ReadableStream类型问题
  3. 初始解析后转换无效

    • req.json()解析后再JSON.stringify()会改变原始请求体的格式,Stripe签名基于原始字节,因此必须使用未解析的原始内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:35:10