Next.js 13中Stripe Webhook处理器的req请求异常问题求助
问题根源
Next.js 13 App Router采用Web标准Request对象,而非传统Node.js的http.IncomingMessage,你使用的micro/buffer工具是为Node.js原生请求设计的,两者不兼容导致读取请求体时抛出Invalid body错误。同时,标准Headers对象不能用索引方式访问,必须用get()方法获取头信息。
修复方案
按以下三点修改代码:
- 移除
micro/buffer依赖,改用Request原生的arrayBuffer()方法获取原始请求体 - 用
req.headers.get('stripe-signature')替代索引访问方式获取签名 - 添加响应返回,满足Stripe对Webhook的状态码要求
修改后的完整代码
import Stripe from "stripe"; import { connectToDB } from "@utils/database"; import Job from "@models/job"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); export const config = { api: { bodyParser: false, }, }; export const POST = async (req) => { let event; const signature = req.headers.get('stripe-signature'); const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; try { // 用Web标准Request的arrayBuffer获取原始请求体 const buf = await req.arrayBuffer(); event = stripe.webhooks.constructEvent( buf, signature, webhookSecret ); } catch (error) { console.error("Webhook签名验证失败:", error); // 返回400给Stripe,表示验证失败 return new Response(`Webhook Error: ${error.message}`, { status: 400 }); } // 处理checkout.session.completed事件 if (event.type === "checkout.session.completed") { console.log("Checkout session completed"); const session = event.data.object; const jobData = session.metadata.jobData; try { await connectToDB(); // 注意:如果jobData是JSON字符串,需要先解析 const newJob = new Job(typeof jobData === 'string' ? JSON.parse(jobData) : jobData); await newJob.save(); console.log("Job post saved:", newJob); } catch (error) { console.error("Failed to save job post:", error); } } // 返回200给Stripe,确认事件已接收 return new Response(null, { status: 200 }); };
额外注意点
- 确保
jobData是合法的JSON格式:如果在Stripe Checkout会话中传入的metadata是字符串化的JSON,记得用JSON.parse()解析后再传入Job模型 - 保持
bodyParser: false的配置,避免Next.js提前解析请求体,导致签名验证失败 - 测试时可以用Stripe CLI的
stripe listen --forward-to localhost:3000/api/stripe-webhooks命令,确保本地转发正确
内容的提问来源于stack exchange,提问作者nmenic
相关产品推荐
相关产品推荐

