在Firebase Firestore get().then()内调用云函数报CORS及500错误如何解决
问题修复方案
根因说明
你看到的CORS报错是次生问题:云函数运行时触发了500内部错误,错误响应默认不会携带CORS头,才会触发浏览器跨域拦截。核心问题出在云函数代码的多处错误,前端代码仅存在一处不影响核心运行的变量声明问题。
问题点及修复方法
- 云函数拼写错误:前端传递的商品数量字段名为
quantity,云函数内两处拼写为quanity,导致读取到的数量值为undefined,触发Stripe参数校验失败。 - 云函数Firestore调用错误:
admin初始化后需要先调用admin.firestore()获取Firestore实例才能操作集合,直接调用admin.collection()会抛出方法未定义错误。 - 云函数异步循环逻辑错误:
forEach不会等待内部异步操作执行完成,会直接执行后续的Stripe会话创建代码,此时lineItems仍为空数组,不符合Stripe的参数要求,需要替换为for...of循环或者用Promise.all包裹所有异步操作。 - 前端变量未声明问题(非核心错误,建议修复):前端代码中
size变量赋值前未声明作用域,可能触发全局变量污染问题,建议添加let声明。
修复后代码示例
云函数代码
const functions = require("firebase-functions"); const admin = require("firebase-admin"); const stripe = require("stripe")(functions.config().stripe.secret_key); // 提前初始化,不要放在请求处理逻辑里 admin.initializeApp(); const db = admin.firestore(); // 提前获取Firestore实例 exports.createStripeCheckout = functions.region("europe-west3").https.onCall(async (data, context) => { const lineItems = []; console.log("dataItems: ", data.items); // 替换forEach为for...of支持异步等待 for (const prodData of data.items) { console.log("prodData: ", prodData); const productID = prodData.productID; const size = prodData.size; const color = prodData.color; const quantity = prodData.quantity; // 修复拼写错误 const collec = productID.charAt(0) == "0" ? "women" : "men"; let name, price, type, description; // 用提前初始化的db实例调用集合 const qdata = await db.collection(collec).doc(productID).get(); name = qdata.data().name; price = qdata.data().price * 100; type = (productID.charAt(0) == "0" ? "Women's" : "Men's") + qdata.data().type; description = `${type} - ${size} - ${color}`; const obj = { price_data: { currency: "eur", product_data: { name: name, description: description, }, unit_amount: price, }, adjustable_quantity: { enabled: true, maximum: 5, minimum: 1, }, quantity: quantity, // 修复拼写错误 }; console.log("obj", obj); lineItems.push(obj); } console.log("lineitems: ", lineItems); const session = await stripe.checkout.sessions.create({ payment_method_types: ["card", "sepa_debit"], shipping_rates: ["<<string hidden by me>>"], shipping_address_collection: { allowed_countries: ["RO"], }, mode: "payment", success_url: "http://localhost:5500/success", cancel_url: "http://localhost:5500/cancel", line_items: lineItems, }); return { id: session.id, }; });
前端修复后的对应代码片段
// 仅修改size变量声明部分,其他逻辑不变 let size = sizeSelect.options[sizeSelect.selectedIndex].value;
修复后重新部署云函数,即可在Firestore的get().then()回调内正常调用云函数,同时保证items变量已经完成数据赋值。
内容的提问来源于stack exchange,提问作者Alexandru Grecu
相关产品推荐
相关产品推荐

