React中window.location.href失效,Node支付接口重定向遇CORS问题
我用Node做后端、React做前端开发支付功能,后端支付路由能正常生成支付链接并重定向,但前端浏览器没有实际跳转,控制台报出CORS相关错误。
后端支付路由代码
router.post("/", async (req, res, next) => { try { const token = await firstStep(); const order = await secondStep(token); const paymentToken = await thirdStep(order, token); const redirectUrl = `https://accept.paymob.com/api/acceptance/iframes/796922?payment_token=${paymentToken}`; res.redirect(redirectUrl); } catch (error) { next(createError(500, error.message)); } });
前端调用代码
const handlePayment = async () => { dispatch(setOrderCourse(course)); try { const res = await newRequest.post("payments"); window.location.href = res.data; } catch (err) { // console.log(err); } };
浏览器报错信息
从源'http://localhost:3000'访问XMLHttpRequest地址'https://accept.paymob.com/api/acceptance/iframes/796922?payment_token=ZXlKaGJHY2lPaUpJVXpVeE1pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SjFjMlZ5WDJsa0lqb3hOalV5TlRneExDSmhiVzkxYm5SZlkyVnVkSE1pT2pFd01Dd2lZM1Z5Y21WdVkza2lPaUpGUjFBaUxDSnBiblJsWjNKaGRHbHZibDlwWkNJNk5ETXdPREk1TVN3aWIzSmtaWEpmYVdRaU9qRTNNRGd4TkRNMU5pd2lZbWxzYkdsdVoxOWtZWFJoSWpwN0ltWnBjbk4wWDI1aGJXVWlPaUpEYkdsbVptOXlaQ0lzSW14aGMzUmZibUZ0WlNJNklrNXBZMjlzWVhNaUxDSnpkSEpsWlhRaU9pSkZkR2hoYmlCTVlXNWtJaXdpWW5WcGJHUnBibWNpT2lJNE1ESTRJaXdpWm14dmIzSWlPaUkwTWlJc0ltRndZWEowYldWdWRDSTZJamd3TXlJc0ltTnBkSGtpT2lKS1lYTnJiMnh6YTJsaWRYSm5hQ0lzSW5OMFlYUmxJam9pVlhSaGFDSXNJbU52ZFc1MGNua2lPaUpEVWlJc0ltVnRZV2xzSWpvaVkyeGhkV1JsZEhSbE1EbEFaWGhoTG1OdmJTSXNJbkJvYjI1bFgyNTFiV0psY2lJNklpczROaWc0S1RreE16VXlNVEEwT0RjaUxDSndiM04wWVd4ZlkyOWtaU0k2SWpBeE9EazRJaXdpWlhoMGNtRmZaR1Z6WTNKcGNIUnBiMjRpT2lKT1FTSjlMQ0pzYjJOclgyOXlaR1Z5WDNkb1pXNWZjR0ZwWkNJNlptRnNjMlVzSW1WNGRISmhJanA3ZlN3aWMybHVaMnhsWDNCaGVXMWxiblJmWVhSMFpXMXdkQ0k2Wm1Gc2MyVXNJbVY0Y0NJNk1UY3dNalF5TWpFME1Dd2ljRzFyWDJsd0lqb2lNVFUyTGpJd055NDFOaTR4TURBaWZRLmNHVWgxVGJPMThYcm1vREtJcjZpbmc5WWg2NUk4WEYwNTBIdi1POWJ0OHpWNDFGY1Nic3VKZzhvb21ESk5qSEFmZUlWbWpodkF5bTdkYWtBYmc4cUVn'(从'http://localhost:8800/api/payments'重定向)已被CORS策略阻止:当请求的凭据模式为'include'时,响应中的'Access-Control-Allow-Origin'标头值不能为通配符'*'。XMLHttpRequest发起的请求的凭据模式由withCredentials属性控制。
问题原因
后端直接重定向到第三方支付链接,导致前端Ajax请求跟着重定向到第三方域名,但第三方支付平台的CORS配置不允许你的前端域名(且请求带凭证),浏览器因此拦截了请求,前端拿不到响应也就无法执行跳转逻辑。
修复方案
方案1:后端返回支付链接,前端自行跳转
修改后端路由,取消直接重定向,把生成的支付链接作为响应返回给前端:
router.post("/", async (req, res, next) => { try { const token = await firstStep(); const order = await secondStep(token); const paymentToken = await thirdStep(order, token); const redirectUrl = `https://accept.paymob.com/api/acceptance/iframes/796922?payment_token=${paymentToken}`; // 替换重定向为返回链接 res.status(200).json(redirectUrl); } catch (error) { next(createError(500, error.message)); } });
前端代码无需修改,原本的window.location.href = res.data逻辑可以直接使用返回的链接完成跳转。
方案2:前端直接发起页面跳转(跳过Ajax)
如果不需要在跳转前处理后端返回的额外数据,可以直接让前端通过表单提交跳转到后端支付路由,绕过Ajax的CORS限制:
const handlePayment = () => { dispatch(setOrderCourse(course)); // 用表单提交模拟POST请求跳转 const form = document.createElement('form'); form.method = 'POST'; form.action = '/api/payments'; document.body.appendChild(form); form.submit(); };
这种方式是浏览器原生的页面跳转请求,不会触发XMLHttpRequest的CORS校验,后端的重定向会被浏览器直接处理。
额外优化:后端CORS配置
如果你的后端使用了cors中间件,确保配置为指定前端域名而非通配符:
const cors = require('cors'); app.use(cors({ origin: 'http://localhost:3000', // 替换为你的前端实际域名 credentials: true // 若请求需要携带凭证(如cookie)则开启 }));
注:此配置仅针对后端自身接口,第三方支付平台的CORS规则无法修改,核心解决思路仍是避免让Ajax请求直接重定向到第三方域名。
内容的提问来源于stack exchange,提问作者Leo Adel

