0

I am following the stripe docs about validating webhooks and despite I do everything as they do i keep getting 400 error. BTW in the docs here https://stripe.com/docs/webhooks/signatures they don't return from the catch blok but here https://stripe.com/docs/webhooks/quickstart they do, so I assyme that the correct option is to return from it? And back to my main problem I have no idea what am I missing here this is my code:

import { NextApiHandler } from "next";
import { Stripe } from "stripe";
import { apolloClient } from "../../graphql/apolloClient";
import {
  UpdateOrderDocument,
  UpdateOrderMutation,
  UpdateOrderMutationVariables,
} from "../../generated/graphql";
import type { StripeWebhookEvents } from "../../stripeEvents";

const stripeWebhookHandler: NextApiHandler = (req, res) => {
  const webhookSignature = req.headers["stripe-signature"];
  const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
  const stripeSecret = process.env.STRIPE_SECRET_KEY;

  if (!stripeSecret || !webhookSignature || !webhookSecret) {
    return res.status(500).json({ error: "Stripe credential not provided" });
  }
  const stripe = new Stripe(stripeSecret, { apiVersion: "2020-08-27" });

  let event;
  try {
    event = stripe.webhooks.constructEvent(
      req.body,
      webhookSignature,
      webhookSecret
    ) as StripeWebhookEvents;
  } catch (err: unknown) {
    return res
      .status(400)
      .send(`Webhook Error: ${err instanceof Error && err.message}`);
  }

  switch (event.type) {
    case "charge.succeeded":
      apolloClient.mutate<UpdateOrderMutation, UpdateOrderMutationVariables>({
        mutation: UpdateOrderDocument,
        variables: {
          id: {
            id: event.data.object.metadata.cartId,
          },
          data: {
            stripeCheckoutId: event.data.object.id,
            email: event.data.object.receipt_email,
          },
        },
      });
      break;
  }
  res.status(204).end();
};

export default stripeWebhookHandler;

and I thought that maybe next has maybe different shape of req.headers or req.body and I am not sure abouut req body, headers seem to be in tact however. At least the signature seems to be extracted correctly. Dhose are test data of course:

{
  webhookSignature: 't=1658224240,v1=a3f574b3e6c3a02eb86308e5e43f3d0a96664098ee5dd58859fc94e96693fc50,v0=ef29de87716d9d318d6ad960f028fd5960618c853ff686bd44e261aaa2368f3b',
  webhookSecret: 'whsec_0d8a54d09bf221f7c5c77ca7a3fca4b988ccd9e49d8a31d7c91f854025503fe4',
  stripeSecret: 'sk_test_51Kuvp4KsMpogemXo9vUcgihi1vK4dlof76OL4EcYhmVgN8r81tl7r0rSsqWgOtXxYnZPJlo6S2KA0gFWZmyBQIbS00ABzicwum',
  headers: {
    host: 'localhost:3000',
    'user-agent': 'Stripe/1.0 (+https://stripe.com/docs/webhooks)',
    'content-length': '2818',
    accept: '*/*; q=0.5, application/xml',
    'cache-control': 'no-cache',
    'content-type': 'application/json; charset=utf-8',
    'stripe-signature': 't=1658224240,v1=a3f574b3e6c3a02eb86308e5e43f3d0a96664098ee5dd58859fc94e96693fc50,v0=ef29de87716d9d318d6ad960f028fd5960618c853ff686bd44e261aaa2368f3b',
    'accept-encoding': 'gzip'
  }

is there something I do incorrectly here? Thanks a lot

seven
  • 1,183
  • 14
  • 33
  • 2
    It's likely that Next.js is malforming the `req.body` (likely parsing to JSON) before it's used with `constructEvent`. That function needs the raw request body. You should update your handler to provide that. – Jonathan Steele Jul 19 '22 at 11:24
  • 1
    See [this tutorial](https://www.codedaily.io/tutorials/Stripe-Webhook-Verification-with-NextJS) as an example of how to do that. – Jonathan Steele Jul 19 '22 at 11:32
  • yeeeey works! thank you thank you thank you! @Jonathan Stelle :) – seven Jul 19 '22 at 12:07
  • refer to my answer here https://stackoverflow.com/a/69935427/3073272 – GorvGoyl Mar 20 '23 at 09:01

0 Answers0