mirror of
https://github.com/marcogll/TaxHacker_s23.git
synced 2026-01-13 13:25:18 +00:00
fix: better webhook error handling
This commit is contained in:
@@ -37,7 +37,7 @@ export default async function RootLayout({ children }: { children: React.ReactNo
|
|||||||
id: user.id,
|
id: user.id,
|
||||||
name: user.name || "",
|
name: user.name || "",
|
||||||
email: user.email,
|
email: user.email,
|
||||||
avatar: user.avatar || undefined,
|
avatar: user.avatar ? user.avatar + "?" + user.id : undefined,
|
||||||
membershipPlan: user.membershipPlan || "unlimited",
|
membershipPlan: user.membershipPlan || "unlimited",
|
||||||
storageUsed: user.storageUsed || 0,
|
storageUsed: user.storageUsed || 0,
|
||||||
storageLimit: user.storageLimit || -1,
|
storageLimit: user.storageLimit || -1,
|
||||||
|
|||||||
@@ -36,25 +36,28 @@ export async function POST(request: Request) {
|
|||||||
const customerId = session.customer as string
|
const customerId = session.customer as string
|
||||||
const subscriptionId = session.subscription as string
|
const subscriptionId = session.subscription as string
|
||||||
const subscription = await stripeClient.subscriptions.retrieve(subscriptionId)
|
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
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
case "customer.subscription.created":
|
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 subscription = event.data.object as Stripe.Subscription
|
||||||
const customerId = subscription.customer as string
|
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
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.log(`Unhandled event type ${event.type}`)
|
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 })
|
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, {
|
await updateUser(user.id, {
|
||||||
membershipPlan: plan.code,
|
membershipPlan: plan.code,
|
||||||
membershipExpiresAt: new Date(item.current_period_end * 1000),
|
membershipExpiresAt:
|
||||||
|
user.membershipExpiresAt && user.membershipExpiresAt > newMembershipExpiresAt
|
||||||
|
? user.membershipExpiresAt
|
||||||
|
: newMembershipExpiresAt,
|
||||||
storageLimit: plan.limits.storage,
|
storageLimit: plan.limits.storage,
|
||||||
aiBalance: plan.limits.ai,
|
aiBalance: plan.limits.ai,
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log(`Updated user ${user.id} with plan ${plan.code} and expires at ${newMembershipExpiresAt}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import * as Sentry from "@sentry/nextjs"
|
import * as Sentry from "@sentry/nextjs"
|
||||||
import { Angry } from "lucide-react"
|
import { Ghost } from "lucide-react"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ export default function GlobalError({ error }: { error: Error }) {
|
|||||||
<body>
|
<body>
|
||||||
<div className="min-h-screen flex flex-col items-center justify-center bg-background p-4">
|
<div className="min-h-screen flex flex-col items-center justify-center bg-background p-4">
|
||||||
<div className="text-center space-y-4">
|
<div className="text-center space-y-4">
|
||||||
<Angry className="w-24 h-24 text-destructive mx-auto" />
|
<Ghost className="w-24 h-24 text-destructive mx-auto" />
|
||||||
<h1 className="text-4xl font-bold text-foreground">Oops! Something went wrong</h1>
|
<h1 className="text-4xl font-bold text-foreground">Oops! Something went wrong</h1>
|
||||||
<p className="text-muted-foreground max-w-md mx-auto">
|
<p className="text-muted-foreground max-w-md mx-auto">
|
||||||
We apologize for the inconvenience. Our team has been notified and is working to fix the issue.
|
We apologize for the inconvenience. Our team has been notified and is working to fix the issue.
|
||||||
|
|||||||
@@ -15,7 +15,12 @@ export default function ProfileSettingsForm({ user }: { user: User }) {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<form action={saveAction} className="space-y-4">
|
<form action={saveAction} className="space-y-4">
|
||||||
<FormAvatar title="Avatar" name="avatar" className="w-24 h-24" defaultValue={user.avatar || ""} />
|
<FormAvatar
|
||||||
|
title="Avatar"
|
||||||
|
name="avatar"
|
||||||
|
className="w-24 h-24"
|
||||||
|
defaultValue={user.avatar ? user.avatar + "?" + user.id : ""}
|
||||||
|
/>
|
||||||
|
|
||||||
<FormInput title="Account Name" name="name" defaultValue={user.name || ""} />
|
<FormInput title="Account Name" name="name" defaultValue={user.name || ""} />
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user