Getting undefined for error and url when using stripe checkout

Viewed 24

I have the a createCheckoutSession.ts:

import { db } from '../firebase/firebaseInit';
import { collection, addDoc, onSnapshot } from 'firebase/firestore';
import { User } from 'firebase/auth';

export async function createCheckoutSession(user: User) {

    console.log('clicked')
    

    const docRef = await addDoc(collection(db, `users/${user?.uid}/checkout_sessions`), {
        price: 'price_1Lb3hiKi0c1bV0RosKIhQ699',
        success_url: `http://localhost:3000/success`,
        cancel_url: `http://localhost:3000/cancel`,
    });

    console.log(docRef)

    onSnapshot(docRef, (snap) => {
        console.log('dsfdsfdf')
        const { error, url } = snap.data();
        console.log(error, 'snap')
            if (error) {
                // Show an error to your customer and
                // inspect your Cloud Function logs in the Firebase console.
                alert(`An error occured: ${error.message}`);
            }
            if (url) {
                // We have a Stripe Checkout URL, let's redirect.
                window.location.assign(url);
            }
        });
}

In vscode I get an error for the line const { error, url } = snap.data();:

Property 'error' does not exist on type 'DocumentData | undefined'.ts(2339)

Error from console:

Uncaught (in promise) FirebaseError: Missing or insufficient permissions.

Security rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{uid} {
      allow read, write: if request.auth.uid == uid;

      match /checkout_sessions/{id} {
        allow read, write: if request.auth.uid == uid;
      }
      match /subscriptions/{id} {
        allow read: if request.auth.uid == uid;
      }
    }

    match /products/{id} {
      allow read: if true;

      match /prices/{id} {
        allow read: if true;
      }

      match /tax_rates/{id} {
        allow read: if true;
      }
    }
  }
}

So I'm getting undefined for the error and url... any ideas what I'm doing wrong?

1 Answers

The snap.data() would be undefined in case the document does not exist and you cannot read properties of undefined. You should check if the document exists as shown below:

onSnapshot(docRef, snap => {
  console.log("In onSnapshot");

  // check if the document exists
  if (snap.exists()) {
    const { name, error } = snap.data(); // This will never be undefined
  } else {
    console.log("Document does not exist");
  }
});

The security rules should allows users to read/write their own data so you can add the document. Try:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId}/{data=**} {
        allow read, write: if request.auth.uid == userId;
    }
  }
}
Related