#BILLY

1 messages · Page 1 of 1 (latest)

ionic furnaceBOT
molten violet
#

Hi there! We have examples for Node.js but you basically need to configure a POST routing to handle webhook events in your Next.js app

plush light
#

I don't think it will work. The webhook keeps giving 500 internal error whilst using POST however get seems to work.

#

Whilst GET works, I cannot use the body as it's not a post/patch request

molten violet
#

What have you tried so far? Can you share your webhook handler code?

#

Be careful to remove/redact your secret key

plush light
#
import { headers } from "next/headers"
import { database } from "@/libs/db"
import { stripe } from "@/libs/stripe"

export async function POST(req) {
  const body = await req.json();
  const signingSecret = process.env.STRIPE_WEBHOOK_SECRET;
  const signature = headers().get("stripe-signature")

  let event;

  try {
    event = stripe.webhooks.constructEvent(
      body,
      signature,
      signingSecret
    )
  } catch (error) {
    return new Response(`Webhook Error: ${error.message}`, { status: 400 })
  }

  const db = database();
  const session = event.data.object

  if (event.type === "checkout.session.completed") {
    const subscription = await stripe.subscriptions.retrieve(
      session.subscription
    )

    await db.user.update({
      where: {
        id: session?.metadata?.userId,
      },
      data: {
        stripeSubscriptionId: subscription.id,
        stripeCustomerId: subscription.customer,
        stripePriceId: subscription.items.data[0].price.id,
        stripeCurrentPeriodEnd: new Date(
          subscription.current_period_end * 1000
        ),
      },
    })
  }

  if (event.type === "invoice.payment_succeeded") {
    const subscription = await stripe.subscriptions.retrieve(
      session.subscription
    )

    await db.user.update({
      where: {
        stripeSubscriptionId: subscription.id,
      },
      data: {
        stripePriceId: subscription.items.data[0].price.id,
        stripeCurrentPeriodEnd: new Date(
          subscription.current_period_end * 1000
        ),
      },
    })
  }

  return new Response(null, { status: 200 })
}```
#

Here's what I'm about to test.

#

Webhook Error: Webhook payload must be 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 NEW

GitHub

Node.js library for the Stripe API. . Contribute to stripe/stripe-node development by creating an account on GitHub.

#

I assume stringify the json

molten violet
#

Yep, I believe that's it. body is the request parsed as a JSON but you should use the body of the raw request

plush light
#
import { headers } from "next/headers"
import { database } from "@/libs/db"
import { stripe } from "@/libs/stripe"

export async function POST(req) {
  const body = await req.text();
  const signingSecret = process.env.STRIPE_WEBHOOK_SECRET;
  const signature = headers().get("stripe-signature")

  let event;

  try {
    event = stripe.webhooks.constructEvent(
      body,
      signature,
      signingSecret
    )
  } catch (error) {
    return new Response(`Webhook Error: ${error.message}`, { status: 400 })
  }

  const db = database();
  const session = event.data.object

  if (event.type === "checkout.session.completed") {
    const subscription = await stripe.subscriptions.retrieve(
      session.subscription
    )

    await db.user.update({
      where: {
        id: session?.metadata?.userId,
      },
      data: {
        stripeSubscriptionId: subscription.id,
        stripeCustomerId: subscription.customer,
        stripePriceId: subscription.items.data[0].price.id,
        stripeCurrentPeriodEnd: new Date(
          subscription.current_period_end * 1000
        ),
      },
    })
  }

  if (event.type === "invoice.payment_succeeded") {
    const subscription = await stripe.subscriptions.retrieve(
      session.subscription
    )

    await db.user.update({
      where: {
        stripeSubscriptionId: subscription.id,
      },
      data: {
        stripePriceId: subscription.items.data[0].price.id,
        stripeCurrentPeriodEnd: new Date(
          subscription.current_period_end * 1000
        ),
      },
    })
  }

  return new Response(null, { status: 200 })
}```

https://dashboard.stripe.com/test/events/evt_1NG7dUFl0B4OxTWPOUN33knN
#

Getting 500 internal error

#

I'm heading off now, please feel free to take your time whilst trying to resolve my issue.

It's probably my fault.

molten violet
#

I think it still comes down to how you're parsing the request

#

Give me a min

plush light
#

.text() gives the raw body. please take your time, there's no rush

molten violet
#

what if you use req.body; instead?