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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 10:35:07