你如何成功地将发布请求发送到 firebase 函数

时间:2021-05-08 00:24:56

标签: firebase google-cloud-firestore google-cloud-functions stripe-payments angular-httpclient

我一直致力于在 Firebase 托管函数中实现 Stripe 处理,但似乎无法使其正常工作。每当我从浏览器发送请求进行测试时,我都会收到以下错误消息:

Access to XMLHttpRequest at 'https://firestore.googleapis.com/google.firestore.v1.Firestore/Write/channel?database=projects%app-name-a4da5%2Fdatabases%2F(default)&VER=8&RID=73206&CVER=22&X-HTTP-Session-Id=gsessionid&%24httpHeaders=Authorization%3ABearer%2tokent=1' from origin 'http://localhost:8100' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
zone-evergreen.js:2952 POST https://firestore.googleapis.com/google.firestore.v1.Firestore/Write/channel?database=projects%app-name-a4da5%2Fdatabases%2F(default)&VER=8&RID=7206&CVER=22&X-HTTP-Session-Id=gsessionid&%24httpHeaders=Authorization%3ABearer%token=1 net::ERR_FAILED

Unchecked runtime.lastError: The message port closed before a response was received.

我知道该功能有效,因为如果我通过邮递员向 firebase 功能发送请求,我会收到 200。此外,如果我在本地提供 firebase 服务并将帖子从浏览器发送到我的 localhost firebase 服务器,它也会成功。但是当我从浏览器向 firebase 函数发送 post 请求时,它不起作用。

我试过在另一篇文章中添加 application/json 标头。

    let header = new HttpHeaders();

    header = header.append('Content-Type', 'application/json');

    console.log('token', token);
    this.http
      .post(this.firebaseURL,
         {
        amount: 100,
        currency: 'usd',
        token
      },
      {
        headers: header
      })
      .subscribe(data => {
        console.log('data', data);
      });
  }

这是 firebase 函数:

exports.payWithStripe = functions.https.onRequest((request, response) => {
    // tslint:disable-next-line:max-line-length

    console.log('exports.payWithStripe = functions.https.onRequest', request);

        // Set your secret key: remember to change this to your live secret key in production
        // See your keys here: https://dashboard.stripe.com/account/apikeys

        // eslint-disable-next-line promise/catch-or-return
    stripe.charges.create({
            amount: request.body.amount,
            currency: request.body.currency,
            source: request.body.token,
        }).then((charge: any) => {
                // asynchronously called
                console.log('then after charges', charge);
                response.send(charge);
            })
            .catch((err: any) => {
                console.log('error from charges', err);
            });
    });

这是用于 PWA。

同样,如果我从浏览器进行离子服务和测试,如果我在本地提供 firebase 并将帖子发送到本地 firebase,但如果我尝试将帖子发送到后端的 firebase 函数,则失败。

如果我通过邮递员发送请求,它可以在本地和 firebase 中使用。

另一件有效的事情也是从前端向 Stripe 请求令牌,如下所示:

      this.stripe.createSource(this.cardDetails).then(result => {
        if (result.error) {
          const errorElement = document.getElementById('card-errors');
          errorElement.textContent = result.error.message;
        } else {
          console.log('results', result.source);
          this.makePayment(result.source.id);
        }
      });

除了从带有测试卡的浏览器向 firebase 函数发出后端请求外,一切正常。

我不确定我的邮递员请求与我在代码中构建的请求有何不同。我的邮递员请求只有 Content-Type = application/json

同样,如果我从浏览器发送请求并在本地提供 firebase 服务,它只是不会将帖子发送到后端。

我也试过这个:

  makePayment(token) {

    let header = new HttpHeaders();

    header = header.append('Content-Type', 'text/plain');
    const body =         {
      amount: 100,
      currency: 'usd',
      token
    };

    const postBody = JSON.stringify(body);
    console.log('token', token);
    this.http
      .post(this.firebaseURL,
        postBody,
      {
        headers: header
      })
      .subscribe(data => {
        console.log('data', data);
      });
  }

我已经坚持了一段时间......任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:2)

如 HTTPS Cloud Functions doc 中所述,您需要将代码封装在如下块中:

return cors(req, res, () => {
  // ...
});

因此,对于您的 CF,以下内容应该有效(未经测试):

// ...
const cors = require('cors')({ origin: true });
// ...

exports.payWithStripe = functions.https.onRequest((request, response) => {

    console.log('exports.payWithStripe = functions.https.onRequest', request);
    
    return cors(request, response, () => {

        stripe.charges.create({
            amount: request.body.amount,
            currency: request.body.currency,
            source: request.body.token,
        }).then((charge: any) => {
            // asynchronously called
            console.log('then after charges', charge);
            response.send(charge);
        })
        .catch((err: any) => {
            console.log('error from charges', err);

            // !!!! Here you need to send back a response, as follows !!!
            response.status(500).send(err);   // <=  see addition here !!!
        });
        
    });

});

此外,请参阅 catch 块中的错误应如何处理。

相关问题