使用 AngularFire 在 Firebase 函数中调用 onCall 函数会导致 404 错误,同时返回预期结果

发布于 2025-01-11 23:47:24 字数 3746 浏览 4 评论 0原文

我使用 Firebase 创建了一些 onCall 云函数。这些函数通过 API 与 Stripe 交互。当我使用 AngularFire,或更具体地说,AngularFireFunctions 来调用这些云函数时,我在 Chrome 开发者控制台中收到错误消息 A bad HTTP response code (404) was returned when fetching the script.。然而,收到预期结果没有任何问题,Firebase 控制台显示 200 响应,没有错误消息或警告。该项目完全托管在 Firebase 上。

404 错误也不会在控制台中显示它连接到的文件,而此类错误通常在该控制台中显示。

更新

我还认为,仪表板中的 Stripe 开发人员日志没有反映任何错误,但在检查时调用成功,这是相关的。

我还尝试删除云函数中对 Stripe 的调用,只返回一个字符串 return 'The customer ID is:'+ ${data.customerId}+'。谢谢。' 并且仍然收到相同的错误消息。

我也尝试过这个解决方案, https://github.com/angular/angularfire /issues/1933#issuecomment-432910986 将以下代码放置在 app.module.ts 中,但是,我无法找到位置FunctionsRegionToken 将被定义为能够导入它。

providers: [
  { provide: FunctionsRegionToken, useValue: 'us-central1' }
]

虽然,我不确定将区域更改为当前调用函数的同一区域会产生什么影响。

当您浏览开发者控制台的Network选项卡并访问调用该函数的页面时,您会看到有东西正在尝试调用http://localhost:4200/firebase- messages-sw.js 不存在。对此文件的调用量和控制台中的错误相互吻合,这使我相信它们是相关的。

更新结束

我尝试添加 CORS< /code> 到我的云函数(并在 onRequest 函数中使用它),我尝试重写我的云函数,甚至尝试更改调用 onCall 的客户端函数,但无济于事。消除错误的唯一方法是删除对函数的调用,因此我将其范围缩小到 AngularFireFunctions 的范围。

我正在使用的内容和版本

Angular V13
Firebase 9.6.7
Angular Fire 7.2.1
Node 16.13.1

接下来是我的代码,分为几个部分。

云功能

const cors = require('cors')({origin: true});
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
const FieldValue = require('firebase-admin').firestore.FieldValue;
admin.initializeApp();
const firebaseApp = admin.app();
const firebaseDB = firebaseApp.firestore();
const Stripe = require('stripe');
const stripe = Stripe(functions.config().stripe.key);

export const retrieveCustomer = functions.https.onCall( async(data) => {
    if(data.customerId) {
        const customer = await stripe.customers.retrieve(data.customerId);
        if(customer) {
            return customer;
        } else {
            throw new functions.https.HttpsError('unknown', 'An unknown error occurred, please try again.'); 
        }
    } else {
        throw new functions.https.HttpsError('invalid-argument', 'A customer ID must be provided.');
    }
});

Angular 服务

import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/compat/firestore';
import { AngularFireFunctions } from '@angular/fire/compat/functions';

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

  constructor( private aff: AngularFireFunctions, private afs: AngularFirestore ) { }

  RetrieveCustomer(customerId:string) {
    const callable = this.aff.httpsCallable('retrieveCustomer');
    return callable({
      customerId: customerId
    });
  }

}

Angular 组件

import { Component, OnInit, AfterContentInit } from '@angular/core';
import { BillingService } from 'src/app/shared/services/billing/billing.service';

@Component({
  selector: 'app-billing-settings',
  templateUrl: './billing-settings.component.html',
  styleUrls: ['./billing-settings.component.css']
})
export class BillingSettingsComponent implements OnInit, AfterContentInit {

  public stripeCustomer!: any;

  constructor( private billingService: BillingService ) { }

  ngOnInit(): void {
    
  }

  ngAfterContentInit(): void {
    this.billingService.RetrieveCustomer('cus_LGRX8TPVF3Xh0w').subscribe((customer:any) => {
      console.log(customer);
    });
  }

}

I have created a few onCall cloud functions using Firebase. These functions interact with Stripe through the API. When I use AngularFire, or more specifically, AngularFireFunctions to call these said cloud functions, I receive the error message A bad HTTP response code (404) was received when fetching the script. in Chrome developer console. Yet, the expected result is received with no problem and the Firebase console displays a 200 response with no error messages or warnings. The project is entirely hosted on Firebase.

The 404 error also does not display a file that it is connected to in the console as such errors typically do within that console.

UPDATE

I also feel it is relevant to include, the Stripe developer logs in the dashboard reflect no errors, but a successfull call upon checking.

I have also tried to remove the call to Stripe in the cloud function and simply only return a string return 'The customer ID is:'+ ${data.customerId}+'. Thank you.' and still received the same error message.

I have also tried this solution, https://github.com/angular/angularfire/issues/1933#issuecomment-432910986 with the following code being placed inside app.module.ts however, am unable to find where FunctionsRegionToken would be defined to be able to import it.

providers: [
  { provide: FunctionsRegionToken, useValue: 'us-central1' }
]

Although, I'm not sure how changing the region to the same region the function is being called from currently would make any difference.

When you explore the Network tab of the developer console and visit the page that calls the function, you see that something is trying to call http://localhost:4200/firebase-messaging-sw.js which doesn't exist. The amount of calls to this file and the errors in the console coincide with each other which leads me to believe they are related.

END OF UPDATE

I have tried to add CORS to my cloud function (and am using it in onRequest functions), I've tried rewriting my cloud function, and even tried changing the client side function that calls the onCall to no avail. The only way to remove the error is to remove the call to the function, thus I've narrowed it down to something with the AngularFireFunctions.

What I am using and the versions

Angular V13
Firebase 9.6.7
Angular Fire 7.2.1
Node 16.13.1

What follows is my code, broken up into sections.

Cloud function

const cors = require('cors')({origin: true});
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
const FieldValue = require('firebase-admin').firestore.FieldValue;
admin.initializeApp();
const firebaseApp = admin.app();
const firebaseDB = firebaseApp.firestore();
const Stripe = require('stripe');
const stripe = Stripe(functions.config().stripe.key);

export const retrieveCustomer = functions.https.onCall( async(data) => {
    if(data.customerId) {
        const customer = await stripe.customers.retrieve(data.customerId);
        if(customer) {
            return customer;
        } else {
            throw new functions.https.HttpsError('unknown', 'An unknown error occurred, please try again.'); 
        }
    } else {
        throw new functions.https.HttpsError('invalid-argument', 'A customer ID must be provided.');
    }
});

Angular Service

import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/compat/firestore';
import { AngularFireFunctions } from '@angular/fire/compat/functions';

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

  constructor( private aff: AngularFireFunctions, private afs: AngularFirestore ) { }

  RetrieveCustomer(customerId:string) {
    const callable = this.aff.httpsCallable('retrieveCustomer');
    return callable({
      customerId: customerId
    });
  }

}

Angular Component

import { Component, OnInit, AfterContentInit } from '@angular/core';
import { BillingService } from 'src/app/shared/services/billing/billing.service';

@Component({
  selector: 'app-billing-settings',
  templateUrl: './billing-settings.component.html',
  styleUrls: ['./billing-settings.component.css']
})
export class BillingSettingsComponent implements OnInit, AfterContentInit {

  public stripeCustomer!: any;

  constructor( private billingService: BillingService ) { }

  ngOnInit(): void {
    
  }

  ngAfterContentInit(): void {
    this.billingService.RetrieveCustomer('cus_LGRX8TPVF3Xh0w').subscribe((customer:any) => {
      console.log(customer);
    });
  }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文