import Stripe from 'stripe'; import AccountService from '~~/lib/services/account.service'; const config = useRuntimeConfig(); const stripe = new Stripe(config.stripeSecretKey, { apiVersion: '2022-11-15' }); export default defineEventHandler(async (event) => { const stripeSignature = getRequestHeader(event, 'stripe-signature'); if(!stripeSignature){ throw createError({ statusCode: 400, statusMessage: 'Webhook Error: No stripe signature in header' }); } const rawBody = await readRawBody(event) if(!rawBody){ throw createError({ statusCode: 400, statusMessage: 'Webhook Error: No body' }); } let stripeEvent: Stripe.Event; try { stripeEvent = stripe.webhooks.constructEvent(rawBody, stripeSignature, config.stripeEndpointSecret); } catch (err) { console.log(err); throw createError({ statusCode: 400, statusMessage: `Error validating Webhook Event` }); } if(stripeEvent.type && stripeEvent.type.startsWith('customer.subscription')){ console.log(`****** Web Hook Recieved (${stripeEvent.type}) ******`); let subscription = stripeEvent.data.object as Stripe.Subscription; if(subscription.status == 'active'){ const sub_item = subscription.items.data.find(item => item?.object && item?.object == 'subscription_item') const stripe_product_id = sub_item?.plan.product?.toString(); // TODO - is the product ever a product object and in that case should I check for deleted? if(!stripe_product_id){ throw createError({ statusCode: 400, statusMessage: `Error validating Webhook Event` }); } const accountService = new AccountService(); let current_period_ends: Date = new Date(subscription.current_period_end * 1000); current_period_ends.setDate(current_period_ends.getDate() + config.subscriptionGraceDays); console.log(`updating stripe sub details subscription.current_period_end:${subscription.current_period_end}, subscription.id:${subscription.id}, stripe_product_id:${stripe_product_id}`); accountService.updateStripeSubscriptionDetailsForAccount(subscription.customer.toString(), subscription.id, current_period_ends, stripe_product_id); } } return `handled ${stripeEvent.type}.`; });