#Next.js Stripe webhook

14 messages · Page 1 of 1 (latest)

glad vineBOT
#

🔎 This post has been indexed in our web forum and will be seen by search engines so other users can find it outside Discord

🕵️ Your user profile is private by default and won't be visible to users outside Discord, if you want to be visible in the web forum you can add the "Public Profile" role in id:customize

✅ You can mark a message as the answer for your post with Right click -> Apps -> Mark Solution
(if you don't see the option, try refreshing Discord with Ctrl + R)

vocal karma
#

You can listen to the „payment_intent.succeeded“ event to listen to successful payments. This event is executed once after the payment is completed. Inside it you will get all the informations, that are inside your paymentintent object. These information can be used to add it inside your database.

If you are using hosted sessions from stripe, you can listen to the „checkout.sessions.complete“ event to access the items or also use the paymentintent

glad vineBOT
#
✅ Success!

This question has been marked as answered! If you have any other questions, feel free to create another post

Jump to answer

[Click here](#1239171803935543357 message)

vocal karma
sage knot
#

Did you mean like that

#
  console.log("recived", event.type);

  switch (event.type) {
    case "payment_intent.succeeded":
      const paymentIntentSucceeded = event.data.object;
      console.log("paymentIntentSucceeded", paymentIntentSucceeded);
      break;

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

  return NextResponse.json({ received: true });
vocal karma
sage knot
#
import { auth } from "@/auth";
import stripe from "@/lib/stripe";
import { absoluteUrl } from "@/lib/utils";
import { NextResponse } from "next/server";

export async function GET() {
  try {
    const session = await auth();
    const user = session?.user;

    if (!user || !user.id) {
      return new NextResponse("Unauthorized", { status: 401 });
    }

    const userId = user.id;

    const stripeSession = await stripe.checkout.sessions.create({
      success_url: absoluteUrl("/coin-shop"),
      cancel_url: absoluteUrl("/coin-shop"),
      payment_method_types: ["card"],
      mode: "payment",
      billing_address_collection: "auto",
      customer_email: user.email!,
      line_items: [
        {
          price_data: {
            currency: "EUR",
            product_data: {
              name: "100 coins",
            },
            unit_amount: 1000,
          },
          quantity: 1,
        },
      ],
      metadata: {
        userId,
      },
    });
    return new NextResponse(JSON.stringify({ url: stripeSession.url }));
  } catch (error) {
    console.log(error);
    return new NextResponse("Internal error", { status: 500 });
  }
}
#

Changed it a bit. Now i just need to set line items to be dynamic

#

I think it will work need to test it first

vocal karma
sage knot
#

Yep I do that!

#
import stripe from "@/lib/stripe";
import prisma from "@/prisma/db";
import { NextResponse } from "next/server";
import Stripe from "stripe";

export async function POST(request: Request) {
  const body = await request.text();
  console.log("Body", body);

  const sig = request.headers.get("Stripe-Signature");

  if (!sig) {
    console.log("No signature");
    return NextResponse.json({ error: "No signature" });
  }

  let event: Stripe.Event;

  try {
    event = stripe.webhooks.constructEvent(
      body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET!,
    );
  } catch (error: any) {
    console.log(`Webhook signature verification failed.`, error.message);
    return new NextResponse(error, { status: 400 });
  }
  const session = event.data.object as Stripe.Checkout.Session;
  if (event.type === "checkout.session.completed") {
    if (!session?.metadata?.userId) {
      return new NextResponse("User id is required!"), { status: 400 };
    }

    console.log(session);

    await prisma.purchase.create({
      data: {
        stripePurchaseId: session.id,
        price: Number(session.amount_total),
        coinsAmount: Number(session?.metadata?.coinsAmount),
        userId: session?.metadata?.userId,
      },
    });
  }

  return NextResponse.json({ received: true });
}