invertase / stripe-firebase-extensions

Repository of Firebase Extensions built by Stripe.
https://firebase.google.com/products/extensions
Apache License 2.0
437 stars 171 forks source link

getStripePayments -> ERROR FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore #614

Closed NylasDev closed 6 months ago

NylasDev commented 8 months ago

Issue with implementation of getStripePayments:

The problem is: Console Error ERROR FirebaseError: Expected first argument to collection() to be a CollectionReference, a DocumentReference or FirebaseFirestore

Description of issue:

I am trying to implement this extension. I am creating accounts using firebase and it's google authentication provider.

I have implemented my auth service that works through firebase. I created a shop service that I wish to use to create a subscription.

Each time I try any sort of approach to connect to Firestore and get the collections I get the error above.

I also implemented the webhook from stripe and the restricted API. This seems to work partially. When I look in Firestore DB I only see the new products I create copied over.

When I create a new user it does not create a "customer" with the session UID, as I expect although I don't know if this is an issue or it's because I am not getting to that point to trigger those cloud functions.

This is my app.config.ts

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { getAuth, provideAuth } from '@angular/fire/auth';
import { getFirestore, provideFirestore } from '@angular/fire/firestore';
import { initializeApp, provideFirebaseApp } from '@angular/fire/app';

import { provideClientHydration } from '@angular/platform-browser';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';

const firebaseConfig = {
  apiKey: "x",
  authDomain: "x",
  projectId: "x",
  storageBucket: "x",
  messagingSenderId: "x",
  appId: "x",
  measurementId: "x"
};

export const appConfig: ApplicationConfig = {
  providers: [
    importProvidersFrom(
    provideFirebaseApp(() => initializeApp(firebaseConfig))),
                        importProvidersFrom(provideAuth(() => getAuth())),
                        importProvidersFrom(provideFirestore(() => getFirestore())),
    provideRouter(routes),
    provideClientHydration()
  ]
};

To Reproduce

This is my AuthenticationService

import {Auth, authState, getAuth, GoogleAuthProvider, signInWithPopup} from '@angular/fire/auth';
import { Injectable } from '@angular/core';
import {Router} from "@angular/router";

@Injectable({
  providedIn: 'root'
})
export class AuthenticationService {
  loggedIn: boolean = false;

  constructor(private auth: Auth, private router: Router)
  {

  }
  authState = getAuth();

  isLoggedIn(): Promise<boolean> {
    return new Promise((resolve, reject) => {
      this.authState.onAuthStateChanged((user) => {
        if (user) {
          resolve(true);
        } else {
          resolve(false);
        }
      });
    });
  }
  async loginWithGoogle() {
    const provider = new GoogleAuthProvider();
    try {
     // await setPersistence(this.auth, browserSessionPersistence);
      await signInWithPopup(this.auth, provider);
      console.log( 'Sign in successful');
      await this.router.navigate(['dashboard']);
    } catch (error: any) {
      console.error(error);
      if (error.code) {
        console.log(`${error.code}: ${error.message}`);
      } else {
        console.log('There was a problem signing in. Please try again.');
      }
    }
  }
  getGoogleUserData(): { displayName: string | null, photoURL: string | null } {
    const user = this.authState.currentUser;
    if (user !== null) {
      console.log("Sign-in provider: " + user.providerId);
      console.log("  Provider-specific UID: " + user.uid);
      console.log("  Name: " + user.displayName);
      console.log("  Email: " + user.email);
      console.log("  Photo URL: " + user.photoURL);
      const displayName = user.displayName || null;
      const photoURL = user.photoURL || null;
      return { displayName, photoURL };
    } else {
      return { displayName: null, photoURL: null };
    }
  }

  logout(): Promise<void> {
    // Sign out the user to remove the local session
    return this.auth.signOut().then(()=>{this.router.navigate(['/'])});
  }
}

This is my ShopService where the error occurs, it is the same for any request that involves getStripePayments

import { Injectable } from '@angular/core';
import {getApp} from "@angular/fire/app";
import {createCheckoutSession, getProducts, getStripePayments} from "@invertase/firestore-stripe-payments";
import {Auth} from "@angular/fire/auth";
import {Router} from "@angular/router";

@Injectable({
  providedIn: 'root'
})
export class ShopService {

  constructor(private auth: Auth, private router: Router) { }

  app = getApp();
  payments = getStripePayments(this.app, {
    productsCollection: "products",
    customersCollection: "customers",
  });
  async startSubscriptionCheckout(priceId: string, successUrl?: string, cancelUrl?: string) {
    debugger;
    const session = await createCheckoutSession(this.payments, {
      price: priceId,
      success_url: successUrl || window.location.origin,
      cancel_url: cancelUrl || window.location.origin,
    });
    window.location.assign(session.url);
  }

  async listProducts(includePrices: boolean = false, activeOnly: boolean = true, filters?: any[], limit?: number) {
    debugger;

    return await getProducts(this.payments, {
      includePrices,
      activeOnly,
      where: filters,
      limit
    });
  }
}

Expected behavior

Get a some form of result from firestore.

Actual result

Error in console, does not seem to be configuring the instance correctly.

Additional context

First time implementing in this standalone mode of angular, might be implementing something wrong.

NylasDev commented 8 months ago

A console.log of the app instance in shop.service.ts

Firebase app instance: FirebaseAppImpl {
  _isDeleted: false,
  _options: {
    apiKey: 'x',
    authDomain: 'x',
    projectId: 'x',
    storageBucket: 'x',
    messagingSenderId: 'x',
    appId: 'x',
    measurementId: 'x'
  },
  _config: { name: '[DEFAULT]', automaticDataCollectionEnabled: false },
  _name: '[DEFAULT]',
  _automaticDataCollectionEnabled: false,
  _container: ComponentContainer {
    name: '[DEFAULT]',
    providers: Map(20) {
      'platform-logger' => [Provider],
      'heartbeat' => [Provider],
      'fire-core-version' => [Provider],
      'fire-core-esm2017-version' => [Provider],
      'fire-js-version' => [Provider],
      'fire-js-all-app-version' => [Provider],
      'auth' => [Provider],
      'auth-internal' => [Provider],
      'fire-auth-node-version' => [Provider],
      'fire-auth-esm2017-version' => [Provider],
      'firestore' => [Provider],
      'fire-fst-node-version' => [Provider],
      'fire-fst-esm2017-version' => [Provider],
      'angularfire-core-version' => [Provider],
      'angularfire-app-version' => [Provider],
      'angular-server-version' => [Provider],
      'angularfire-auth-version' => [Provider],
      'angularfire-fst-version' => [Provider],
      'app' => [Provider],
      'app-check-internal' => [Provider]
    }
  }
}
NylasDev commented 8 months ago

package.json

{
  "name": "dungeon-maker-ai-frontend",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "serve:ssr:dungeon-maker-ai-frontend": "node dist/dungeon-maker-ai-frontend/server/server.mjs"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^17.2.0",
    "@angular/common": "^17.2.0",
    "@angular/compiler": "^17.2.0",
    "@angular/core": "^17.2.0",
    "@angular/fire": "^17.0.1",
    "@angular/forms": "^17.2.0",
    "@angular/platform-browser": "^17.2.0",
    "@angular/platform-browser-dynamic": "^17.2.0",
    "@angular/platform-server": "^17.2.0",
    "@angular/router": "^17.2.0",
    "@angular/ssr": "^17.2.1",
    "@invertase/firestore-stripe-payments": "^0.0.7",
    "@ng-bootstrap/ng-bootstrap": "^16.0.0",
    "@popperjs/core": "^2.11.8",
    "bootstrap": "^5.3.2",
    "bootstrap-icons": "^1.11.3",
    "express": "^4.18.2",
    "ngx-bootstrap": "^12.0.0",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.14.3"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^17.2.1",
    "@angular/cli": "^17.2.1",
    "@angular/compiler-cli": "^17.2.0",
    "@angular/localize": "^17.2.0",
    "@types/express": "^4.17.17",
    "@types/jasmine": "~5.1.0",
    "@types/node": "^18.18.0",
    "jasmine-core": "~5.1.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "typescript": "~5.3.2"
  }
}
joelshotton commented 8 months ago

I'm having this same issue trying to use this SDK in a react app!

connorbrc commented 7 months ago

did you ever figure this out? running into same problem.

NylasDev commented 7 months ago

Not really, just implemented it directly.

On Tue, Apr 9, 2024 at 4:04 AM connorbrc @.***> wrote:

did you ever figure this out? running into same problem.

— Reply to this email directly, view it on GitHub https://github.com/invertase/stripe-firebase-extensions/issues/614#issuecomment-2043954085, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGIJRULK4NFXGJAB7GKHST3Y4M5DJAVCNFSM6AAAAABEHIFZG6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANBTHE2TIMBYGU . You are receiving this because you authored the thread.Message ID: @.***>

tolypash commented 5 months ago

I have the same issue! Perhaps it's a Node JS thing?

DougieBoi227 commented 3 months ago

Same issue using angular-fire. Anyone figure this out yet?

nomadts commented 1 month ago

I am having the same issue. How did you overcome this issue? Is there an alternative to that?

DougieBoi227 commented 1 month ago

I am having the same issue. How did you overcome this issue? Is there an alternative to that? The problem is when using angular fire, the wires get crossed.

Not a great solution but I ended going into the node modules and fixing it myself. For example in node_modules/@invertase/firestore-stripe-payments/lib/payment.js I changed all the getFirestores (and everything with it) to be imported from "@angular/fire/firestore". I had to go through all the main js files in there and do that.

All is working now but not sure I want something this flaky especially when dealing with payments. May be better to ditch the whole extension and implement stripe from scratch unfortunately.