Next.js 13 App目录下获取Stripe Webhook原始请求体遇阻
解决Next.js中Stripe Webhook原始请求体获取问题
你遇到的核心问题在于:
- 开启
bodyParser: true时,Next.js会自动解析请求体为JSON对象,破坏了Stripe签名验证所需的原始未加工字节流,导致"invalid body"错误 - 关闭
bodyParser后,请求是原生的可读流,若buffer函数实现不当或未正确处理请求头,会出现"content-type is undefined"错误
正确实现方案
以下是适配Next.js(App Router)的完整代码,包含原始请求体读取、content-type校验和Stripe签名验证:
import { NextResponse } from 'next/server'; import Stripe from 'stripe'; // 必须禁用bodyParser,保留原始请求体 export const config = { api: { bodyParser: false, }, }; // 自定义函数读取请求流为Buffer async function buffer(req: Request) { const chunks: Uint8Array[] = []; for await (const chunk of req.body!) { chunks.push(chunk); } return Buffer.concat(chunks); } export async function POST(request: Request) { try { // 手动获取content-type请求头 const contentType = request.headers.get('content-type'); if (!contentType || !contentType.includes('application/json')) { return NextResponse.json({ error: '无效的内容类型' }, { status: 400 }); } // 读取原始请求体 const rawBody = await buffer(request); // Stripe签名验证(必须步骤) const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { apiVersion: '2024-06-20', // 替换为你的Stripe API版本 }); const signature = request.headers.get('stripe-signature'); const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!; let event: Stripe.Event; try { event = stripe.webhooks.constructEvent( rawBody, signature!, webhookSecret ); } catch (err) { console.error('Stripe签名验证失败:', err); return NextResponse.json({ error: '无效签名' }, { status: 400 }); } // 处理具体Stripe事件示例 switch (event.type) { case 'payment_intent.succeeded': const paymentIntent = event.data.object as Stripe.PaymentIntent; console.log('支付成功:', paymentIntent.id); // 此处添加你的业务逻辑 break; default: console.log(`未处理的事件类型: ${event.type}`); } return NextResponse.json({ status: 200 }); } catch (err) { console.error('请求处理失败:', err); return NextResponse.json({ error: '服务器内部错误' }, { status: 500 }); } }
关键说明
- 禁用bodyParser:这是Stripe Webhook的硬性要求,只有原始字节流才能通过签名验证
- 正确读取请求流:在Next.js App Router中,
request.body是ReadableStream,需用for await...of循环读取所有chunk并拼接为Buffer - 手动校验content-type:关闭bodyParser后Next.js不会自动解析请求头,需手动获取并验证是否为Stripe发送的
application/json类型 - 签名验证不可省略:即使你暂时只需要原始体,也必须保留签名验证步骤,避免恶意请求
内容的提问来源于stack exchange,提问作者strmzi
相关产品推荐
相关产品推荐

