summaryrefslogtreecommitdiff
path: root/apps/web/app/api/billing/webhook/route.ts
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-08 08:09:04 -0800
committerFuwn <[email protected]>2026-02-08 08:09:04 -0800
commit2bbe11a56b3df971bcc15b56da4988cfe624fd6e (patch)
treea8962a4bc3967d9eaa88bbf813de1d5f679e7018 /apps/web/app/api/billing/webhook/route.ts
parentdebug: add webhook signature verification logging (diff)
downloadasa.news-2bbe11a56b3df971bcc15b56da4988cfe624fd6e.tar.xz
asa.news-2bbe11a56b3df971bcc15b56da4988cfe624fd6e.zip
fix: invoice.paid handler now retrieves subscription for correct tier resolution
Diffstat (limited to 'apps/web/app/api/billing/webhook/route.ts')
-rw-r--r--apps/web/app/api/billing/webhook/route.ts29
1 files changed, 13 insertions, 16 deletions
diff --git a/apps/web/app/api/billing/webhook/route.ts b/apps/web/app/api/billing/webhook/route.ts
index dc87249..37944c2 100644
--- a/apps/web/app/api/billing/webhook/route.ts
+++ b/apps/web/app/api/billing/webhook/route.ts
@@ -116,19 +116,20 @@ async function handleInvoicePaymentFailed(invoice: Stripe.Invoice) {
async function handleInvoicePaid(invoice: Stripe.Invoice) {
const stripeCustomerIdentifier = invoice.customer as string
- const lineItem = invoice.lines?.data?.[0]
- const priceIdentifier = (lineItem as unknown as { price?: { id?: string } } | undefined)?.price?.id
- const developerPriceIdentifiers = [
- process.env.STRIPE_DEVELOPER_MONTHLY_PRICE_IDENTIFIER,
- process.env.STRIPE_DEVELOPER_YEARLY_PRICE_IDENTIFIER,
- ]
- const tier =
- priceIdentifier && developerPriceIdentifiers.includes(priceIdentifier)
- ? "developer"
- : "pro"
+ const invoiceRecord = invoice as unknown as Record<string, unknown>
+ const subscriptionIdentifier =
+ typeof invoiceRecord.subscription === "string"
+ ? invoiceRecord.subscription
+ : (invoiceRecord.subscription as { id?: string } | null)?.id
+
+ if (!subscriptionIdentifier) return
+
+ const subscription = await getStripe().subscriptions.retrieve(
+ subscriptionIdentifier
+ )
await updateBillingState(stripeCustomerIdentifier, {
- tier,
+ tier: determineTierFromSubscription(subscription),
stripe_subscription_status: "active",
})
}
@@ -144,7 +145,6 @@ export async function POST(request: Request) {
const signature = request.headers.get("stripe-signature")
if (!signature) {
- console.error("webhook: missing stripe-signature header")
return NextResponse.json({ error: "missing signature" }, { status: 400 })
}
@@ -156,10 +156,7 @@ export async function POST(request: Request) {
signature,
process.env.STRIPE_WEBHOOK_SECRET!
)
- } catch (verificationError) {
- console.error("webhook: signature verification failed:", verificationError)
- console.error("webhook: secret defined:", !!process.env.STRIPE_WEBHOOK_SECRET)
- console.error("webhook: body length:", body.length)
+ } catch {
return NextResponse.json({ error: "invalid signature" }, { status: 400 })
}