Next.js中Stripe webhook的constructEvent未定义问题求助
问题分析与解决方案
核心问题1:Stripe Webhook方法拼写错误
你的代码中调用了stripe.webhook.constructEvent,但Stripe Node.js SDK(v8及以上版本)中正确的方法名是复数形式的stripe.webhooks.constructEvent。单数的stripe.webhook不存在,因此会抛出Cannot read properties of undefined (reading 'constructEvent')错误。
核心问题2:变量作用域错误
payload和sig变量定义在if (req.method === "POST")的代码块内部,外部的try块无法访问这两个变量,即使修复了方法名,也会因为参数未定义导致验证失败。
修复后的完整代码
import { buffer } from "micro"; import * as admin from "firebase-admin"; const serviceAccount = require("../../../credentials.json"); const app = !admin.apps.length ? admin.initializeApp({ credentials: admin.credential.cert(serviceAccount), }) : admin.app(); // 初始化Stripe const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); const endpointSecret = process.env.SIGNING_SECRET; const fulfillOrder = async (session) => { console.log("Fill Order"); return app .firestore() .collection("users") .doc(session.metadata.email) .collection("orders") .doc(session.id) .set({ amount: session.amount_total / 100, amount_shipping: session.total_details.amount_shipping / 100, images: JSON.parse(session.metadata.images), timestamp: admin.firestore.FieldValue.serverTimestamp(), }) .then(() => { console.log(`Success: Order ${session.id} added to db `); }); }; export default async (req, res) => { // 仅处理POST请求 if (req.method !== "POST") { return res.status(405).send("Method Not Allowed"); } const requestBuffer = await buffer(req); const payload = requestBuffer.toString(); const sig = req.headers["stripe-signature"]; let event; // 验证事件来源 try { // 修正为复数形式的webhooks event = stripe.webhooks.constructEvent(payload, sig, endpointSecret); } catch (error) { console.log("Error", error.message); return res.status(400).send(`Webhook error: ${error.message}`); } // 处理结账完成事件 if (event.type === "checkout.session.completed") { const session = event.data.object; return fulfillOrder(session) .then(() => res.status(200).send("Success")) // 补充响应内容 .catch((error) => res.status(400).send(`Webhook error: ${error.message}`) ); } // 处理其他事件类型 res.status(200).send("Received"); }; export const config = { api: { bodyParser: false, externalResolver: true, }, };
额外注意事项
- 环境变量验证:确保
.env.local文件中正确配置了STRIPE_SECRET_KEY和SIGNING_SECRET,且Stripe CLI输出的签名密钥与SIGNING_SECRET一致。 - 字段修正:原代码中
session.amount.total应为session.amount_total(Stripe Checkout Session的正确字段名),避免后续写入Firestore时出现错误。 - 响应完整性:所有分支都需要返回完整的HTTP响应(如
res.status(200).send('Success')),避免请求超时。
内容的提问来源于stack exchange,提问作者PinPiguin
相关产品推荐
相关产品推荐

