0

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.

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
Lazarusss
  • 11
  • 6

2 Answers2

1

you had to register your app in production. you should already have run this commmand for development.

 // installed stripe cli 
 // api/webhook your enpoint
stripe listen --events checkout.session.completed --forward-to localhost:3000/api/webhook 

similarly you should register your production endpoint.

you can follow webhooks/go-live docs

Yilmaz
  • 35,338
  • 10
  • 157
  • 202
0

Verify you webhook secret key, remember there is two keys for webhook one that work on in localhost and second for production in stripe developer signing secret ,enter image description here