Ad

Getting Exception On Webhook From Stripe

- 1 answer

I'm trying to set up a webhook from Stripe to handle the payment_intent.succeeded event, but I get an exception. This is my code from the Node backend (I have extracted all the relevant parts I hope. Let me know if anything else is needed):

const stripeWebHookSecret = 'whsec_WA0Rh4vAD3z0rMWy4kv2p6XXXXXXXXXX';

import express from 'express';
const app = express();
app.use(bodyParser.urlencoded({ extended:true }));
app.use(bodyParser.json());
app.use(session({ <some params here> }));

const openRouter = express.Router();

registerOpenPaymentRoutes(openRouter);

app.use('/open', openRouter);

And the implementation of registerOpenPaymentRoutes looks like this:

export const registerOpenPaymentRoutes = (router) => {
    router.post('/payment/intent/webhook', bodyParser.raw({type: 'application/json'}), (req, res) => {
        let signature = req.headers['stripe-signature'];
        try {
            let event = stripe.webhooks.constructEvent(req.body, signature, stripeWebHookSecret);
            switch(event.type){
                case 'payment_intent.succeeded':
                    let intent = event.data.object;
                    res.json({ message: 'Everything went smooth!', intent });
                default:
                    res.status(400).json({ error: 'Event type not supported' });
            }
        }
        catch (error){
            res.status(400).json({ message: `Wrong signature`, signature, body: req.body, error });
        }
    });
}

So far so good.When I fire a test webhook event from the Stripe dashboard, I hit the endpoint, but get the result from the catch block. The error message is as follows:

No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? https://github.com/stripe/stripe-node#webhook-signing"

I'm returning the signature with the error message as well as you see above, and the signature looks like this:

"t=1557911017,v1=bebf499bcb35198b8bfaf22a68b8879574298f9f424e57ef292752e3ce21914d,v0=23402bb405bfd6bd2a13c310cfecda7ae1905609923d801fa4e8b872a4f82894"

As far as I understand from the documentation, what is needed to get the raw request body as mentioned are the bodyParser.raw({type: 'application/json'})argument to the router that I already have there.

Can anyone see the missing part?

Ad

Answer

It's because you've already set your express app to use the bodyParser.json() middleware, which clashes with the bodyParser.raw() middleware you set up in your webhook route.

If you remove the app.use(bodyParser.json()); line your webhooks will work as intended, but then the rest of your routes won't have a parsed body, which isn't ideal.

I suggest adding a custom middleware to choose the bodyParser version based on route. Something like:

// only use the raw bodyParser for webhooks
app.use((req, res, next) => {
  if (req.originalUrl === '/payment/intent/webhook') {
    next();
  } else {
    bodyParser.json()(req, res, next);
  }
});

Then explicitly use the bodyParser.raw() middleware on the webhook routes.

Ad
source: stackoverflow.com
Ad