把我的头发拉出来试图在 NextJS 上传递 Stripe webhook 的原始主体!。
尝试了很多来自各地的解决方案,但我似乎无法使其发挥作用。
向拥有超能力的开发者开放(我仍在获取其中)。
条纹测试错误:
我的 NextJS webhook 端点测试:未找到与有效负载的预期签名匹配的签名。您是否传递了从 Stripe 收到的原始请求正文?
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);
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
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);
}
这对我有用。希望可以帮到你。
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;