Subscription webhook

You will need to configure a webhook on Stripe to receive events when subscriptions are created, updated or deleted. You can add a webhook from the Stripe Dashboard here

This webhook will have to be listening for the following events:

customer.subscription.created

customer.subscription.deleted

customer.subscription.updated

updatedSubscriptionWebhook.ts

This code example updates the user's subscription in firestore

It will delete the subscription if the user was delete from Stripe or add the subscription if it's a new one or simply update it if there was an existing one already in the database

import { firestore, admin } from "../utils/firebase"
import stripe, { Stripe } from "../utils/stripe"
import * as express from "express"

const router = express.Router()

router.post("/", (req: any, res) => {
    let event
    try {
        // check stripe event signature
        event = stripe.webhooks.constructEvent(
            req.rawBody,
            req.headers["stripe-signature"],
            process.env.YOUR_WEBHOOK_SIGNING_SECRET // visible on the Stripe Dashboard (https:
        )
    } catch (error) {
        reportError(error, { request: req, details: "stripe-signature check error" }, req)
        return res.status(400).send({ error })
    }

    if (!event || !event.type || !event.data?.object) return res.status(400).send({ event, error: "Missing data" })

    const {
        status,
        customer: stripeCustomerId,
        id: subscriptionId,
        trial_end: trialEnd,
        current_period_end: periodEnd,
        cancel_at_period_end: cancelAtPeriodEnd
    } = event.data.object

    const { id: plan } = event.data.object?.plan

    return stripe.customers
        .retrieve(stripeCustomerId)
        .then((customer): any => {
            if (customer.deleted) {
                // if customer is deleted, delete subscription
                return firestore
                    .collection("users")
                    .where("subscription.stripeCustomerId", "==", stripeCustomerId)
                    .get()
                    .then((querySnapshot) => {
                        if (querySnapshot.empty) {
                            throw Error("user not found")
                        }

                        // get first matching user
                        const matchingUser = querySnapshot.docs[0]

                        const userId = matchingUser.id

                        return firestore.collection("users").doc(userId).set(
                            {
                                subscription: admin.firestore.FieldValue.delete() // delete subscription if customer is deleted
                            },
                            { merge: true }
                        )
                    })
                    .then(
                        () => `The subscription's owner was deleted so the subscription has been removed from the user.`
                    )
            }

            // if customer is not deleted, update or add subscription
            return firestore
                .collection("users")
                .where("email", "==", (customer as Stripe.Customer).email)
                .get()
                .then((querySnapshot) => {
                    if (querySnapshot.empty) {
                        throw Error("user not found")
                    }

                    // get first matching user
                    const matchingUser = querySnapshot.docs[0]

                    const userId = matchingUser.id

                    const subscription = {
                        stripeCustomerId,
                        id: subscriptionId,
                        status,
                        plan,
                        trialEnd,
                        periodEnd,
                        cancelAtPeriodEnd
                    }

                    return firestore.collection("users").doc(userId).set(
                        {
                            subscription
                        },
                        { merge: true }
                    )
                })
                .then(() => `The subscription was updated in firebase.`)
        })
        .then((status) => res.status(200).send({ status }))
        .catch((error) => {
            console.error(`>> WEBHOOK ERROR: ${error}`)
            res.status(400).send({ event, error })
        })
})

export default router

Last updated