firebasegoogle-cloud-firestorestripe-paymentsfirebase-extensionsstripe-payments-js

Successful Checkout condition with Firebase and Stripe "Run Payment with Stripe"


I need some help with my next.js application and I can't seem to find an answer that fully works. I am using Firebase as my backend, and using the "Run Payment with Stripe" extension to handle my web payments. I have implemented the subscription method successfully, but I want to add a one-time payment option to my website. I have implemented everything the same and added the "mode: "payment" " to my checkout function. I want to fire another function once there is a successful payment, but I am not sure how to integrate that with my existing code. The webhook documentation for the extension doesn't provide any insight into how to handle a success case, so here I am asking for some help / guidance. Any help is greatly appreciated! Below is my code for creating a checkout session based on the extension docs:

export async function createTenCheckoutSession(uid) {
    const firestore = firebase.firestore();

    const checkoutSessionRef = await firestore
        .collection("users")
        .doc(uid)
        .collection("checkout_sessions")
        .add({
            mode: "payment",
            price: "price_xxxxxxxxxxxxxxxxxx",
            success_url: window.location.origin,
            cancel_url: window.location.origin,
        });

    checkoutSessionRef.onSnapshot(async (snap) => {
        const { sessionId } = snap.data();
        if (sessionId) {
            const stripe = await getStripe();
            stripe.redirectToCheckout({ sessionId });
        }
    });
};

Solution

  • Figured out a way to do this using Firebase Functions.

    My current createCheckoutSession function is as follows:

    export async function createCheckoutSession(uid) {
        const firestore = firebase.firestore();
    
        const checkoutSessionRef = await firestore
            .collection("users")
            .doc(uid)
            .collection("checkout_sessions")
            .add({
                price: "price_xxxxxxxxxxxxxxxxxxxxxxxx",
                success_url: window.location.origin,
                cancel_url: window.location.origin,
            });
    
        checkoutSessionRef.onSnapshot(async (snap) => {
            const { sessionId } = snap.data();
            if (sessionId) {
                const stripe = await getStripe();
                stripe.redirectToCheckout({ sessionId });
            }
        });
    };
    

    I wanted to update my RTDB after a successful checkout session dependent on which one-time purchase was made. This is my Firebase Function:

    const firestore = admin.firestore();
    const realtimeDatabase = admin.database();
    
    exports.updateRealtimeDatabase = functions.firestore
        .document('users/{userId}/payments/{paymentId}')
        .onCreate(async (snapshot, context) => {
            const paymentId = context.params.paymentId;
            const userId = context.params.userId;
    
            // Get the data of the newly created document
            const eventData = snapshot.data();
    
            // Check if the event data meets the specified conditions
            if (eventData.status === 'succeeded') {
                if (eventData.amount === 4900) {
                    // Increase the Realtime Database viewCount for the corresponding user by 10
                    const updates = {};
                    updates[`/users/${userId}/viewCount`] = admin.database.ServerValue.increment(10);
    
                    try {
                        await realtimeDatabase.ref().update(updates);
                        console.log('Realtime Database updated successfully.');
                    } catch (error) {
                        console.error('Error updating Realtime Database:', error);
                    }
                } else if (eventData.amount === 19900) {
                    // Increase the Realtime Database viewCount for the corresponding user by 50
                    const updates = {};
                    updates[`/users/${userId}/viewCount`] = admin.database.ServerValue.increment(50);
    
                    try {
                        await realtimeDatabase.ref().update(updates);
                        console.log('Realtime Database updated successfully.');
                    } catch (error) {
                        console.error('Error updating Realtime Database:', error);
                    }
                } else {
                    console.log('No specific condition met. No update needed.');
                }
            } else {
                console.log('Status is not "succeeded". No update needed.');
            }
        });