Flutter Stripe网页端支付出现CORS错误,求解决方案
解决Flutter网页端Stripe支付的CORS报错问题
核心原因
浏览器的同源策略限制了跨域请求,你的Firebase Cloud Functions未返回正确的CORS响应头,导致网页端请求被拦截。而Android/iOS端不受浏览器同源策略约束,因此能正常运行支付功能。
具体修复方案
1. 为Cloud Functions添加CORS配置
有两种方式实现,任选其一即可:
方式一:手动添加CORS响应头
修改index.js,在函数开头处理预检请求并添加CORS头:
const functions = require("firebase-functions"); const stripe = require("stripe")("sk_..."); exports.stripePaymentIntentRequest = functions.https.onRequest(async (req, res) => { // 配置CORS头(生产环境建议替换为你的网页域名,如https://your-app.web.app) res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.set('Access-Control-Allow-Headers', 'Content-Type'); // 处理浏览器OPTIONS预检请求 if (req.method === 'OPTIONS') { res.status(204).send(''); return; } try { let customerId; const customerList = await stripe.customers.list({ email: req.body.email, limit: 1 }); if (customerList.data.length !== 0) { customerId = customerList.data[0].id; } else { const customer = await stripe.customers.create({ email: req.body.email }); // 修复原代码错误:Stripe返回的customer是直接对象,无需.data.id customerId = customer.id; } const ephemeralKey = await stripe.ephemeralKeys.create( { customer: customerId }, { apiVersion: '2020-08-27' } ); const paymentIntent = await stripe.paymentIntents.create({ amount: parseInt(req.body.amount), currency: 'eur', customer: customerId, }); res.status(200).send({ paymentIntent: paymentIntent.client_secret, ephemeralKey: ephemeralKey.secret, customer: customerId, success: true, }); } catch (error) { // 404状态码不合适,改用400表示请求/服务异常 res.status(400).send({ success: false, error: error.message }); } });
方式二:使用cors库简化配置
先安装依赖:
npm install cors
再修改代码:
const functions = require("firebase-functions"); const stripe = require("stripe")("sk_..."); // 允许所有来源,生产环境可配置具体域名如{origin: "https://your-app.web.app"} const cors = require("cors")({ origin: true }); exports.stripePaymentIntentRequest = functions.https.onRequest(async (req, res) => { // 通过cors中间件处理跨域 cors(req, res, async () => { try { let customerId; const customerList = await stripe.customers.list({ email: req.body.email, limit: 1 }); if (customerList.data.length !== 0) { customerId = customerList.data[0].id; } else { const customer = await stripe.customers.create({ email: req.body.email }); customerId = customer.id; } const ephemeralKey = await stripe.ephemeralKeys.create( { customer: customerId }, { apiVersion: '2020-08-27' } ); const paymentIntent = await stripe.paymentIntents.create({ amount: parseInt(req.body.amount), currency: 'eur', customer: customerId, }); res.status(200).send({ paymentIntent: paymentIntent.client_secret, ephemeralKey: ephemeralKey.secret, customer: customerId, success: true, }); } catch (error) { res.status(400).send({ success: false, error: error.message }); } }); });
2. 修复原代码中的潜在错误
原代码中customerId = customer.data.id是错误的,Stripe的customers.create接口直接返回客户对象,应改为customer.id,这个错误可能导致隐藏的运行异常。
3. 重新部署Cloud Functions
执行命令更新部署:
firebase deploy --only functions
生产环境安全优化
- 不要用
*作为Access-Control-Allow-Origin,替换为你的Flutter网页端实际域名 - 将Stripe密钥存储在Firebase环境变量中,避免硬编码:
代码中用firebase functions:config:set stripe.secret="sk_..."functions.config().stripe.secret获取密钥。
内容的提问来源于stack exchange,提问作者mvasco
相关产品推荐
相关产品推荐

