From 3976db1114ae77efd499b04b232df18ff20e7879 Mon Sep 17 00:00:00 2001 From: vas3k Date: Thu, 22 May 2025 17:04:19 +0200 Subject: [PATCH] fix: better webhook error handling --- app/(app)/layout.tsx | 2 +- app/api/stripe/webhook/route.ts | 24 +++++++++++++------ app/global-error.tsx | 4 ++-- components/settings/profile-settings-form.tsx | 7 +++++- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/app/(app)/layout.tsx b/app/(app)/layout.tsx index 4fdc826..9941084 100644 --- a/app/(app)/layout.tsx +++ b/app/(app)/layout.tsx @@ -37,7 +37,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo id: user.id, name: user.name || "", email: user.email, - avatar: user.avatar || undefined, + avatar: user.avatar ? user.avatar + "?" + user.id : undefined, membershipPlan: user.membershipPlan || "unlimited", storageUsed: user.storageUsed || 0, storageLimit: user.storageLimit || -1, diff --git a/app/api/stripe/webhook/route.ts b/app/api/stripe/webhook/route.ts index bb273a9..f7d7ff9 100644 --- a/app/api/stripe/webhook/route.ts +++ b/app/api/stripe/webhook/route.ts @@ -36,25 +36,28 @@ export async function POST(request: Request) { const customerId = session.customer as string const subscriptionId = session.subscription as string const subscription = await stripeClient.subscriptions.retrieve(subscriptionId) - const item = subscription.items.data[0] - await handleUserSubscriptionUpdate(customerId, item) + for (const item of subscription.items.data) { + await handleUserSubscriptionUpdate(customerId, item) + } break } case "customer.subscription.created": - case "customer.subscription.updated": { + case "customer.subscription.updated": + case "customer.subscription.deleted": { const subscription = event.data.object as Stripe.Subscription const customerId = subscription.customer as string - const item = subscription.items.data[0] - await handleUserSubscriptionUpdate(customerId, item) + for (const item of subscription.items.data) { + await handleUserSubscriptionUpdate(customerId, item) + } break } default: console.log(`Unhandled event type ${event.type}`) - return new NextResponse("No handler for event type", { status: 200 }) + return new NextResponse("No handler for event type", { status: 400 }) } return new NextResponse("Webhook processed successfully", { status: 200 }) @@ -91,11 +94,18 @@ async function handleUserSubscriptionUpdate( } } + const newMembershipExpiresAt = new Date(item.current_period_end * 1000) + await updateUser(user.id, { membershipPlan: plan.code, - membershipExpiresAt: new Date(item.current_period_end * 1000), + membershipExpiresAt: + user.membershipExpiresAt && user.membershipExpiresAt > newMembershipExpiresAt + ? user.membershipExpiresAt + : newMembershipExpiresAt, storageLimit: plan.limits.storage, aiBalance: plan.limits.ai, updatedAt: new Date(), }) + + console.log(`Updated user ${user.id} with plan ${plan.code} and expires at ${newMembershipExpiresAt}`) } diff --git a/app/global-error.tsx b/app/global-error.tsx index 2f511fd..3a445b1 100644 --- a/app/global-error.tsx +++ b/app/global-error.tsx @@ -2,7 +2,7 @@ import { Button } from "@/components/ui/button" import * as Sentry from "@sentry/nextjs" -import { Angry } from "lucide-react" +import { Ghost } from "lucide-react" import Link from "next/link" import { useEffect } from "react" @@ -16,7 +16,7 @@ export default function GlobalError({ error }: { error: Error }) {
- +

Oops! Something went wrong

We apologize for the inconvenience. Our team has been notified and is working to fix the issue. diff --git a/components/settings/profile-settings-form.tsx b/components/settings/profile-settings-form.tsx index 02d4466..89982a0 100644 --- a/components/settings/profile-settings-form.tsx +++ b/components/settings/profile-settings-form.tsx @@ -15,7 +15,12 @@ export default function ProfileSettingsForm({ user }: { user: User }) { return (

- +