// In my case, this goes into functions/src/functions/stripe-webhook.ts import * as logger from 'firebase-functions/logger'; import { onRequest } from 'firebase-functions/v2/https'; import Stripe from 'stripe'; import { handleSubscriptionUpdated } from '../services/stripe'; export const stripeWebhook = onRequest(async (request, response) => { const stripe = new Stripe(process.env.STRIPE_SECRET_KEY || '', { apiVersion: '2025-02-24.acacia', }); const sig = request.headers['stripe-signature']; if (!sig) { response.status(400).send('Missing stripe-signature header'); return; } try { const event = stripe.webhooks.constructEvent(request.rawBody, sig, process.env.STRIPE_WEBHOOK_SECRET || ''); // Handle the event switch (event.type) { case 'customer.subscription.created': case 'customer.subscription.updated': case 'customer.subscription.deleted': case 'customer.subscription.paused': case 'customer.subscription.resumed': await handleSubscriptionUpdated(event); break; default: logger.info(`Unhandled event type ${event.type}`); } response.json({ received: true }); } catch (err: unknown) { logger.error('Error processing webhook:', err); response.status(400).send(`Webhook Error: ${err instanceof Error ? err.message : 'Unknown error'}`); } });