我一直致力于在 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);
});
}
我已经坚持了一段时间......任何帮助都将不胜感激。
答案 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
块中的错误应如何处理。