你如何成功发送 post 请求到 firebase 函数

How do you successfully send post request to firebase function

我一直致力于在 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.

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

我试过添加 application/json header 每个 post.

    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 并将 post 发送到本地 firebase,它会工作,但如果我尝试将 post 发送到 firebase,它会失败后端功能。

如果我通过 postman 发送请求,它在本地和 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 函数发出后端请求外,一切正常。

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

同样,如果我从浏览器发送请求并在本地提供 firebase,它可以正常工作,只是不将 post 发送到后端。

我也试过这个:

  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);
      });
  }

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

如 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 块中的错误处理方式。