#ayushh_webhooks
1 messages ยท Page 1 of 1 (latest)
๐ 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.
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?
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
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
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?
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.
okay, I am creating a model for it
I will get back to you in short moments
cs_test_a1MeUvhnJhxNM6IPzDP1iD489IQbACztOgMozoBQsvq5cqZFGkqa5biQEi
here is the checkout session id
Taking a look now
thanks
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.
Sign In into existing account
is it safe to give you webhook id over here?
or may I DM you?
the id
Webhook ID (wh_xxx) is safe to share and it can only be accessed by Stripe staff
Can you share the ID in text, so that I can search in my system?
we_1QStqRCaHwobVeJK4yi4p63B
Thanks for sharing! Stripe has attempted to deliver the event to we_1QStqRCaHwobVeJK4yi4p63B, but your system returned 302 to Stripe: https://dashboard.stripe.com/test/events/evt_1QSvGLCaHwobVeJKbHIOTQI6
Sign in to the Stripe Dashboard to manage business payments and operations in your account. Manage payments and refunds, respond to disputes and more.
can I know where the redirect was made?
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
That's awesome! Happy to help ๐