stripe-samples / firebase-subscription-payments

Example web client for the `firestore-stripe-subscriptions` Firebase Extension using Stripe Checkout and the Stripe Customer Portal.
https://stripe-subs-ext.web.app/
MIT License
289 stars 78 forks source link

TypeError: snap.data is not a function #22

Closed mmz15 closed 3 years ago

mmz15 commented 3 years ago

Subscription Payments Issue

Describe the bug

I'm getting an error (TypeError: snap.data is not a function) when creating a checkout session using the Firebase "Run Subscription Payments with Stripe" extension. This issue is quite similar to the following StackOverflow issue, which has gone unresolved: https://stackoverflow.com/questions/63677671/firebase-extension-run-subscription-payments-with-stripe-doesnt-return-a-sessi

To Reproduce

I followed the steps outlined in the extensions tutorial, with the slight modification of removing the async/await syntactic sugar.

db.collection("customers")
    .doc(user)
    .collection("checkout_sessions")
    .add({
      price: "price_1I42zfKct2IqsPff6b6vFNKx",
      success_url: window.location.origin,
      cancel_url: window.location.origin,
    })
    .then(() => {
      db.collection("customers")
        .doc(user)
        .collection("checkout_sessions")
        .onSnapshot((snap) => {
          const { sessionId } = snap.data();
          if ({ sessionId }) {
            const stripe = loadStripe(<STRIPE_API_KEY>);
            stripe.redirectToCheckout({ sessionId });
          }
        });
    });

Expected behavior

I expected, upon the successful creation of a sessionId, to be redirected to a Stripe checkout page. Instead, I received an error and the redirect failed.

Screenshots

Session successfully created:

Screen Shot 2021-02-14 at 20 03

checkout_sessions successfully created:

Screen Shot 2021-02-14 at 20 03 1

Getting the error:

Screen Shot 2021-02-14 at 20 03 2

System information

thorsten-stripe commented 3 years ago

You need to listen to updates to the specific document that you juts added via the .add() function. This function returns a reference to that specific document: https://github.com/stripe/stripe-firebase-extensions/blob/next/firestore-stripe-subscriptions/POSTINSTALL.md#start-a-subscription-with-stripe-checkout

If you don't want to / can't use async/await syntax you will need to get that document reference from the .then() function: https://firebase.google.com/docs/firestore/manage-data/add-data#web_6

db.collection("customers")
    .doc(user)
    .collection("checkout_sessions")
    .add({
      price: "price_1I42zfKct2IqsPff6b6vFNKx",
      success_url: window.location.origin,
      cancel_url: window.location.origin,
    })
  .then((docRef) => {
      docRef.onSnapshot((snap) => {
          const { sessionId } = snap.data();
          if ({ sessionId }) {
            // NOTE: loadstripe is an async function. If you can't use async/await then you need to use .then
            loadStripe(<STRIPE_API_KEY>).then((stripe) => {
              stripe.redirectToCheckout({ sessionId });
            });
          }
        });
    });
mmz15 commented 3 years ago

Works perfectly. Thanks for following up and for your work on this!