#ayushh_webhooks

1 messages ยท Page 1 of 1 (latest)

ashen knotBOT
#

๐Ÿ‘‹ Welcome to your new thread!

โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.

โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.

๐Ÿ”— This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1314466254668697632

๐Ÿ“ Have more to share? Add more details, code, screenshots, videos, etc. below.

north sun
#

Could you share the Payment Intent ID (pi_xxx) that you expect their events to be sent to your Webhook endpoint, so that I can take a look?

inland cedar
#

I think I didn't record it

#

model Purchase {
id String @id @default(uuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@unique([userId])
@@index([userId])
}

model StripeCustomer {
id String @id @default(uuid())
userId String @unique
stripeCustomerId String @unique
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

#

this is my model to record purchase

#

export async function POST(req: NextRequest) {
    const body = await req.text()
    const signature = (await headers()).get("Stripe-Signature") as string;

    let event: Stripe.Event;
    try {
        event = stripe.webhooks.constructEvent(
            body,
            signature,
            process.env.STRIPE_WEBHOOK_SECRET!,

        )
    } catch (error: any) {
        console.log("[WEBHOOK ERROR] ", error.message);
        return NextResponse.json({ error: error.message }, { status: 400 });
    }

    const session = event.data.object as Stripe.Checkout.Session;
    const userId = session?.metadata?.userId
    if (event.type === "checkout.session.completed") {
        // Fetch the existing user profile
        if (!userId) {
            return NextResponse.json({ error: "Invalid metadata" }, { status: 400 });
        }

        // Fetch the available credits
        const existingCredits = await db.user.findFirst({ where: { id: userId }, select: { credits: true } });
        if (!existingCredits) return NextResponse.json({ error: "Invalid user id" }, { status: 400 });

        // Record the purchase
        await db.purchase.create({
            data: {
                userId,
            }
        })


        // Add the credits
        await db.user.update({
            data: {
                credits: existingCredits?.credits + Number(process.env.SUBSCRIPTION_CREDITS!)
            }, where: { id: userId }
        })

    }
    else {
        return NextResponse.json({ error: "Unhandled event type" }, { status: 200 });
    }
    return NextResponse.json(null, { status: 200 });
}
#

I will be right back in few moments

north sun
#

We will need to know the object ID that you expect to receive in order to troubleshoot why your webhook endpoint doesn't receive the event

#

This is usually due to configuration issue, but we will need the Checkout Session ID (cs_xxx) to see how it is created, so that we can investigate further

inland cedar
#

I can get the items you required from line_items?


const line_items: Stripe.Checkout.SessionCreateParams.LineItem[] = [{
          quantity: 1,
          price_data: {
              currency: "USD",
              product_data: {
                  name: "AI Credits",
                  description: "AI Credits"
              },
              unit_amount: Math.round(Number(process.env.SUBSCRIPTION_PRICE!) * 100)
          }
      }]
#

or from checkout session?

    const checkoutSession = await stripe.checkout.sessions.create({
            customer: stripeCustomer.stripeCustomerId,
            line_items,
            mode: 'payment',
            success_url: `${process.env.NEXTAUTH_URL}/success`,
            cancel_url: `${process.env.NEXTAUTH_URL}/cancel`,
            metadata: {
                userId: session.user.id
            }
        })
#

and can you tell me also which things should I store it in the db? like as you said, payment_intent and object_id what other fields are required to be stored?

north sun
#

You should store the Checkout Session (cs_xxx) if you're creating the payment from the Checkout Session

#

By sharing the Checkout Session ID (cs_xxx), we will then be able to look into it further on why your webhook endpoint doesn't receive the event.

inland cedar
#

I will get back to you in short moments

inland cedar
#

cs_test_a1MeUvhnJhxNM6IPzDP1iD489IQbACztOgMozoBQsvq5cqZFGkqa5biQEi

#

here is the checkout session id

north sun
#

Taking a look now

inland cedar
#

thanks

north sun
#

Which webhook endpoint do you expect to receive the event? Could you share the webhook endpoint ID (wh_xxx) or URL? I can see that checkout.session.completed has been sent to two webhook endpoints for this Checkout Session, but one returned 503 while another returned 302. None of them returned 200 status code to Stripe.

inland cedar
inland cedar
#

or may I DM you?

#

the id

north sun
#

Webhook ID (wh_xxx) is safe to share and it can only be accessed by Stripe staff

inland cedar
#

wait

#

this is the id

north sun
#

Can you share the ID in text, so that I can search in my system?

inland cedar
#

we_1QStqRCaHwobVeJK4yi4p63B

north sun
inland cedar
#

can I know where the redirect was made?

north sun
#

The redirect was made by your system, not Stripe. This was the response returned by your system that Stripe doesn't have any context how your server is set up

inland cedar
#

okay

#

Done

#

fixed

#

thank you

north sun
#

That's awesome! Happy to help ๐Ÿ˜„

inland cedar
#

the webhook route was protected by middleware

#

so it redirected to signin and I put the webhook in public route

#

thanks for your quick and kind response

#

I appreciate stripe for their best service