使用Stripe API开发支付工具时遇CORS错误及重定向失效问题
遇到的问题
发起前端fetch请求时触发CORS错误:
Access to fetch at 'https://checkout.stripe.com/c/pay/cs_test_a17M3P9xrCIrTMFi9s6BXK3uPIMuCsLMZTNZsGggylcIN41Am2xjHz1OIA#fidkdWxOYHwnPyd1blpxYHZxWjA0S2xjTV1EdnBLRlJMSEthR2d9YGhTZF9tcmpwX2tXajdJcjVdMmZnZEI3U1E8T3I3QTFVRmN8d25OMTxxTk9yc2xrY3d1X1FjTnx8X0lnQEtvcTBVUWNkNTVWVU00cWZWPCcpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBabHFgaCcpJ2BrZGdpYFVpZGZgbWppYWB3dic%2FcXdwYHgl' (redirected from 'http://localhost:5000/api/stripepayement') from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
同时后端的res.redirect(303, session.url)无法正常跳转到Stripe支付页面。
错误原因分析
- CORS错误根源:前端用
fetch发起请求后,服务器返回303重定向到Stripe支付页面,浏览器会自动跟随重定向去请求Stripe的地址。但Stripe的Checkout页面不允许前端跨域请求(未配置Access-Control-Allow-Origin响应头),因此浏览器直接拦截该请求,抛出CORS错误。 - 重定向失效原因:
fetch默认仅处理同域重定向,跨域场景下不会自动跳转页面,而是尝试获取目标地址的内容,这就触发了上述CORS问题,自然无法完成跳转。
解决方案
方案1:后端返回Session URL,前端主动跳转(官方推荐)
这种方式彻底避免跨域问题,是Stripe官方认可的集成方式。
修改后端代码(stripepayement.js)
将res.redirect(303, session.url)改为返回JSON格式的Session URL:
router.post("/", async (req, res) => { const numberofDays = req.body.totalPrice; console.log("Days: ", numberofDays); try { const session = await stripe.checkout.sessions.create({ line_items: [ { price: "price_1Nj0xIAsuNCWIMNdoD6PaVh5", quantity: numberofDays && numberofDays > 0 ? numberofDays : 1, }, ], mode: "payment", success_url: `${YOUR_DOMAIN}?success=true`, cancel_url: `${YOUR_DOMAIN}?canceled=true`, automatic_tax: {enabled: true}, }); console.log("Successfully created session", session); // 返回Session URL给前端,而非直接重定向 res.json({ url: session.url }); } catch (error) { console.error("Erreur lors de la création de la session Stripe:", error); res.status(500).json({error: "Une erreur est survenue lors du paiement."}); } });
修改前端代码(clientPage.js)
在fetch请求成功后,拿到返回的URL,用window.location.href主动跳转到Stripe支付页面:
const handlePayment = async (e) => { e.preventDefault(); try { const response = await fetch("http://localhost:5000/api/stripepayement", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ totalPrice: numberOfDaysTmp, }), }); const data = await response.json(); // 跳转到Stripe支付页面 if (data.url) { window.location.href = data.url; } } catch (error) { console.error("Erreur lors du paiement:", error); } };
方案2:直接通过表单提交到后端接口
如果不想使用fetch,可以直接将表单的提交目标设为后端接口,让浏览器直接处理重定向:
<form action="http://localhost:5000/api/stripepayement" method="POST"> <!-- 隐藏输入框传递天数参数 --> <input type="hidden" name="totalPrice" value={numberOfDaysTmp} /> <button type="submit">发起支付</button> </form>
注意:这种方式需要后端添加表单解析中间件,因为表单默认使用application/x-www-form-urlencoded格式,原代码的bodyParser.json()仅支持JSON格式。在stripepayement.js中添加:
router.use(bodyParser.urlencoded({ extended: true }));
额外注意事项
- 确保Stripe密钥正确(测试环境用测试密钥,生产环境用生产密钥)
- 当前后端的CORS配置(
origin: true)是正确的,会自动允许请求来源,无需修改
内容的提问来源于stack exchange,提问作者Nicolas

