fix: improve stripe webhook endpoint
Improve the stripe webhook endpoint by checking for subscriptions prior to performing an update to handle cases where accounts have no created subscription. This can happen in sitations such as when a checkout_session has been created but the payment fails.
This commit is contained in:
@@ -25,9 +25,7 @@ export const webhookHandler = async (req: NextApiRequest, res: NextApiResponse)
|
||||
});
|
||||
}
|
||||
|
||||
log("constructing body...")
|
||||
const body = await buffer(req);
|
||||
log("constructed body")
|
||||
|
||||
const event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
|
||||
log("event-type:", event.type);
|
||||
@@ -70,11 +68,25 @@ export const webhookHandler = async (req: NextApiRequest, res: NextApiResponse)
|
||||
if (event.type === "invoice.payment_succeeded") {
|
||||
const invoice = event.data.object as Stripe.Invoice;
|
||||
|
||||
if (invoice.billing_reason !== "subscription_cycle") {
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
message: "Webhook received",
|
||||
});
|
||||
}
|
||||
|
||||
const customerId =
|
||||
typeof invoice.customer === "string" ? invoice.customer : invoice.customer?.id;
|
||||
|
||||
const subscription = await stripe.subscriptions.retrieve(invoice.subscription as string);
|
||||
|
||||
const hasSubscription = await prisma.subscription.findFirst({
|
||||
where: {
|
||||
customerId,
|
||||
},
|
||||
});
|
||||
|
||||
if (hasSubscription) {
|
||||
await prisma.subscription.update({
|
||||
where: {
|
||||
customerId,
|
||||
@@ -86,6 +98,7 @@ export const webhookHandler = async (req: NextApiRequest, res: NextApiResponse)
|
||||
periodEnd: new Date(subscription.current_period_end * 1000),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
@@ -98,6 +111,13 @@ export const webhookHandler = async (req: NextApiRequest, res: NextApiResponse)
|
||||
|
||||
const customerId = failedInvoice.customer as string;
|
||||
|
||||
const hasSubscription = await prisma.subscription.findFirst({
|
||||
where: {
|
||||
customerId,
|
||||
},
|
||||
});
|
||||
|
||||
if (hasSubscription) {
|
||||
await prisma.subscription.update({
|
||||
where: {
|
||||
customerId,
|
||||
@@ -106,6 +126,7 @@ export const webhookHandler = async (req: NextApiRequest, res: NextApiResponse)
|
||||
status: SubscriptionStatus.PAST_DUE,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
@@ -118,6 +139,13 @@ export const webhookHandler = async (req: NextApiRequest, res: NextApiResponse)
|
||||
|
||||
const customerId = updatedSubscription.customer as string;
|
||||
|
||||
const hasSubscription = await prisma.subscription.findFirst({
|
||||
where: {
|
||||
customerId,
|
||||
},
|
||||
});
|
||||
|
||||
if (hasSubscription) {
|
||||
await prisma.subscription.update({
|
||||
where: {
|
||||
customerId,
|
||||
@@ -129,6 +157,7 @@ export const webhookHandler = async (req: NextApiRequest, res: NextApiResponse)
|
||||
periodEnd: new Date(updatedSubscription.current_period_end * 1000),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
@@ -141,6 +170,13 @@ export const webhookHandler = async (req: NextApiRequest, res: NextApiResponse)
|
||||
|
||||
const customerId = deletedSubscription.customer as string;
|
||||
|
||||
const hasSubscription = await prisma.subscription.findFirst({
|
||||
where: {
|
||||
customerId,
|
||||
},
|
||||
});
|
||||
|
||||
if (hasSubscription) {
|
||||
await prisma.subscription.update({
|
||||
where: {
|
||||
customerId,
|
||||
@@ -149,6 +185,7 @@ export const webhookHandler = async (req: NextApiRequest, res: NextApiResponse)
|
||||
status: SubscriptionStatus.INACTIVE,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
|
||||
Reference in New Issue
Block a user