49 lines
1.8 KiB
TypeScript
49 lines
1.8 KiB
TypeScript
import { pbAdmin } from '$lib/server/pocketbase';
|
|
import type Stripe from 'stripe';
|
|
|
|
// Shared Stripe event handling. The real webhook (/api/webhooks/stripe) routes
|
|
// through here so the DB effects are identical.
|
|
export async function handleStripeEvent(event: Stripe.Event): Promise<void> {
|
|
switch (event.type) {
|
|
case 'checkout.session.completed': {
|
|
const session = event.data.object as Stripe.Checkout.Session;
|
|
const famId = session.metadata?.famId;
|
|
if (famId && session.customer) {
|
|
await pbAdmin.update('fams', famId, {
|
|
stripeCustomerId: String(session.customer),
|
|
active: true,
|
|
paymentMode: 'sub'
|
|
});
|
|
}
|
|
break;
|
|
}
|
|
case 'customer.subscription.created':
|
|
case 'customer.subscription.updated':
|
|
case 'customer.subscription.paused': {
|
|
const sub = event.data.object as Stripe.Subscription;
|
|
await setActiveFromSubscription(sub);
|
|
break;
|
|
}
|
|
case 'customer.subscription.deleted': {
|
|
const sub = event.data.object as Stripe.Subscription;
|
|
const fams = await pbAdmin.getList('fams', `stripeCustomerId = '${sub.customer}'`);
|
|
const fam = fams[0];
|
|
if (fam) {
|
|
await pbAdmin.update('fams', fam.id, { active: false, paymentMode: 'canceled' });
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
async function setActiveFromSubscription(sub: Stripe.Subscription) {
|
|
// The fam that owns this subscription — look up by the customer id stored
|
|
// on the fam (set at checkout). Stripe customer id is unique per fam.
|
|
const fams = await pbAdmin.getList('fams', `stripeCustomerId = '${sub.customer}'`);
|
|
const fam = fams[0];
|
|
if (!fam) return;
|
|
// Active only while the sub is trialing/active (not past_due/canceled/paused).
|
|
const active =
|
|
sub.status === 'trialing' || sub.status === 'active' || sub.status === 'past_due';
|
|
await pbAdmin.update('fams', fam.id, { active, paymentMode: 'sub' });
|
|
} |