NextJS Stripe Webhook 原始主体

问题描述 投票:0回答:4

把我的头发拉出来试图在 NextJS 上传递 Stripe webhook 的原始主体!。

尝试了很多来自各地的解决方案,但我似乎无法使其发挥作用。

向拥有超能力的开发者开放(我仍在获取其中)。

条纹测试错误:

未找到与有效负载的预期签名匹配的签名。您是否传递了从 Stripe 收到的原始请求正文?

我的 NextJS webhook 端点测试:

import { buffer } from 'micro'; const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY); export default async function handler(req, res) { console.log("Payment intent") const event = req.body console.log(event) if (process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET) { // Get the signature sent by Stripe const signature = req.headers['stripe-signature']; console.log(signature) try { event = stripe.webhooks.constructEvent( req.body, signature, process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET ); } catch (err) { console.log(`⚠️ Webhook signature verification failed.`, err.message); return res.sendStatus(400); } } console.log(event.type) // Handle the event switch (event.type) { case 'payment_intent.succeeded': console.log("Success!") break; default: console.log(`Unhandled event type ${event.type}`); } }
也尝试过:

import { buffer } from 'micro'; import Cors from 'micro-cors'; const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY); const webhookSecret = process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET_NEW; // Stripe requires the raw body to construct the event. export const config = { api: { bodyParser: false, }, }; const cors = Cors({ allowMethods: ['POST', 'HEAD'], }); const webhookHandler = async (req, res) => { if (req.method === 'POST') { const buf = await buffer(req); console.log(buf.toString()) const sig = req.headers['stripe-signature']; console.log(process.env.STRIPE_SECRET_KEY) console.log(webhookSecret) console.log(sig) let event; try { event = stripe.webhooks.constructEvent( buf.toString(), sig, webhookSecret ); } catch (err) { console.log(`❌ Error message: ${err.message}`); res.status(400).send(`Webhook Error: ${err.message}`); return; } if (event.type === 'payment_intent.succeeded') { const paymentIntent = event.data.object; console.log(`💰 PaymentIntent status: ${paymentIntent.status}`); } else if (event.type === 'payment_intent.payment_failed') { const paymentIntent = event.data.object; console.log( `❌ Payment failed: ${paymentIntent.last_payment_error?.message}` ); } else if (event.type === 'charge.succeeded') { const charge = event.data.object; console.log(`💵 Charge id: ${charge.id}`); } else { console.warn(`🤷‍♀️ Unhandled event type: ${event.type}`); } res.json({ received: true }); } else { res.setHeader('Allow', 'POST'); res.status(405).end('Method Not Allowed'); } }; export default cors(webhookHandler);
    
javascript next.js stripe-payments webhooks serverless-framework
4个回答
7
投票
默认情况下,NextJS 根据标头中传入的 Content-Type 解析请求正文。您需要禁用此 [0],然后使用

buffer

 将其作为流使用。

下面的代码对我有用:

export const config = { api: { bodyParser: false, }, }; import { buffer } from 'micro'; const stripe = require('stripe')(process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET); export default async function handler(req, res) { let event; if (process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET) { // Get the signature sent by Stripe const signature = req.headers['stripe-signature']; const buf = await buffer(req); try { event = stripe.webhooks.constructEvent( buf, signature, process.env.STRIPE_WEBHOOK_ENDPOINT_SECRET ); ...
[0] 

https://nextjs.org/docs/api-routes/api-middlewares#custom-config


2
投票
为了解决这个问题,我通过在同一个 api 路由文件中导出配置对象来禁用 NextJS 主体解析器:

export const config = { api: { bodyParser: false, }, };
然后我导入了 

raw-body 包,这样我就可以将请求流转换为原始缓冲区:

var getRawBody = require('raw-body')
最后我通过 Promise 接口使用了 raw-body 包:

if (endpointSecret) { const signature = request.headers['stripe-signature']; console.log("sig", signature); getRawBody(request) .then(function (buf) { rawBody = buf; event = stripe.webhooks.constructEvent( rawBody, signature, endpointSecret ); let subscription; let status; // Handle the event switch (event.type) { case 'customer.subscription.trial_will_end': subscription = event.data.object; default: // Unexpected event type console.log(`Unhandled event type ${event.type}.`); } // Return a 200 response to acknowledge receipt of the event return response.status(200); }) .catch(function (err) { console.log(`⚠️ Webhook signature verification failed.`, err.message); return response.status(500); }) } else { console.log("Missing endpoint secret"); return response.status(500); }
这对我有用。希望可以帮到你。


0
投票
我知道这个问题可能已经很老了,但是对于将来遇到这个问题的任何人,我想分享一下,我已经使用 webhooks 和新的 /app 路由器成功地将 Stripe 集成到我的项目中。

我已在 README.md 文件中记录了整个分步教程。

请随时通过以下链接查看存储库:

https://github.com/BastidaNicolas/nextauth-prisma-stripe


0
投票
我明白了,兄弟,这样做了一个小时,终于让它工作了,只需将其用于您的端点,它就会记录事件

import { buffer } from "micro"; import Stripe from "stripe"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, { }); const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; const handler = async (req, res) => { if (req.method === "POST") { console.log("req", req, "time to buffer"); const buf = await buffer(req); const sig = req.headers["stripe-signature"]; let event; console.log("buf", buf); try { event = stripe.webhooks.constructEvent(buf, sig, webhookSecret); console.log("Success:", event); res.status(200).send("Success"); return; } catch (err) { res.status(400).send(`Webhook Error: ${err.message}`); return; } } else { res.setHeader("Allow", "POST"); res.status(405).end("Method Not Allowed"); } }; export const config = { api: { bodyParser: false, }, }; export default handler;
    
© www.soinside.com 2019 - 2024. All rights reserved.