javascriptnode.jsexpressstripe-payments

Stripe - Webhook payload must be provided as a string or a Buffer


I am trying to code a subscription system with stripe. My following code is mostly copied from the stripe docs, but it always shows me this error:

Webhook signature verification failed. Webhook payload must b
e provided as a string or a Buffer (https://nodejs.org/api/buffer.html) instance representing the _raw_ request body.Payload was provided as a parsed JavaScript object instead.
Signature verification is impossible without access to the original signed material.
Learn more about webhook signing and explore webhook integration 
examples for various frameworks at https://github.com/stripe/stripe-node#webhook-signing

This is my code written in javascript:

app.post(
  '/webhook',
  express.raw({ type: 'application/json' }),
  (request, response) => {
    let event = request.body;

    const endpointSecret = 'whsec_.....';

    if (endpointSecret) {

      const signature = request.headers['stripe-signature'];
      try {
        event = stripe.webhooks.constructEvent(
          request.body,
          signature,
          endpointSecret
        );
      } catch (err) {
        console.log(`⚠️  Webhook signature verification failed.`, err.message);
        return response.sendStatus(400);
      }
    }
    let subscription;
    let status;

    switch (event.type) {
      case 'customer.subscription.created':
        subscription = event.data.object;
        status = subscription.status;
        console.log(`Subscription status is ${status}.`);

        break;
      default:
        console.log(`Unhandled event type ${event.type}.`);
    }
    response.send();
  }
);

Does anyone know what I am doing wrong? I have literally been searching the internet for an hour now and cant find anything. Thanks in advance!


Solution

  • It's because app.use(express.json()); code. Try to move webhook route before app.use(express.json());.

    // webhook route
    app.post(
      '/webhook',
      express.raw({ type: 'application/json' }),
      (request, response) => {
        let event = request.body;
    
        const endpointSecret = 'whsec_.....';
    
        if (endpointSecret) {
    
          const signature = request.headers['stripe-signature'];
          try {
            event = stripe.webhooks.constructEvent(
              request.body,
              signature,
              endpointSecret
            );
          } catch (err) {
            console.log(`⚠️  Webhook signature verification failed.`, err.message);
            return response.sendStatus(400);
          }
        }
        let subscription;
        let status;
    
        switch (event.type) {
          case 'customer.subscription.created':
            subscription = event.data.object;
            status = subscription.status;
            console.log(`Subscription status is ${status}.`);
    
            break;
          default:
            console.log(`Unhandled event type ${event.type}.`);
        }
        response.send();
      }
    );
    
    app.use(express.json());