I have a project in Next.js with Strapi & Stripe. There is a webhook that is executed after successful payment and after that, it should run markProductAsSold
callback, and it does but only at localhost. Also if I run only a callback (idk. on button click somewhere on a page) it's working on stage and localhost!
Webhook code:
export const config = {
api: {
bodyParser: false,
},
};
export default async function webhookHandler(req, res) {
const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_SECRET, {
apiVersion: '2022-11-15',
});
if (req.method === 'POST') {
const buf = await buffer(req);
const sig = req.headers['stripe-signature'];
const webhookSecret = process.env.NEXT_PUBLIC_STRAPI_WEBHOOK_KEY;
let event;
try {
if (!sig || !webhookSecret) return;
event = stripe.webhooks.constructEvent(buf, sig, webhookSecret);
} catch (error) {
return res.status(400).send(`Webhook error: ${error.message}`);
}
if (event.data.object.status === 'succeeded') {
await markProductAsSold(event.data.object.metadata.MarkAsSold);
}
}
res.status(200).send();
}
Callback code
const markProductAsSold = async (slug: string) => {
const findProduct = await fetch(
`${process.env.NEXT_PUBLIC_DATABASE_URL}/api/products?filters[slug][$eq]=${slug}`
);
const data = await findProduct.json();
const isSold = data.data[0].attributes.isSold;
const productData = {
...data.data[0]
};
productData.attributes.isSold = !isSold;
await fetch(
`${process.env.NEXT_PUBLIC_DATABASE_URL}/api/products/${productData.id}`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.NEXT_PUBLIC_STRAPI_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: productData.attributes,
}),
}
);
return productData;
};
export default markProductAsSold;
All data like metadata.MarkAsSold
or env's are 100% valid and triple checked. I just don't know where could be a problem cause callback doesn't work only after being fired on stage by Stripe webhook.
Solved
It turns out that my callback wasn't running after everything was triggered by Stripe. Idk. why but when I moved markProductAsSold
function directly into if (event.data.object.status === 'succeeded')
it started to working.