Angular集成Stripe支付遭遇CORS跨域问题求助
Angular+Node.js集成Stripe支付时的CORS错误解决
Access to XMLHttpRequest at 'https://checkout.stripe.com/c/pay/cs_test_a1GABMpi' (redirected from 'http://localhost:5000/create-checkout-session') from origin 'http://localhost:4200' 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.
问题场景
在Angular前端和Node.js后端集成Stripe支付时出现上述CORS错误,以下是前后端代码:
后端(Node.js)
const express = require('express'); const dotenv = require('dotenv'); const cors = require('cors'); const colors = require('colors'); const connectDB = require('./config/db'); const morgan = require('morgan'); const errorHandler = require('./middleware/error'); dotenv.config({ path: './config/config.env' }); const stripe = require('stripe')(process.env.STRIPE_API_KEY); connectDB(); const app = express(); app.use(express.json()); app.use(express.static('public')); app.use( cors({ origin: '*', }) ); app.post('/create-checkout-session', async (req, res) => { console.log(process.env.STRIPE_API_KEY); const session = await stripe.checkout.sessions.create({ line_items: [ { price: process.env.STRIPE_PRICE, quantity: 1, }, ], mode: 'payment', success_url: `https://google.com`, cancel_url: `https://google.com`, automatic_tax: { enabled: true }, }); res.redirect(303, session.url); }); const PORT = process.env.PORT || 5000; const server = app.listen(PORT, () => { console.log( `Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.yellow.bold ); });
前端(Angular)
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root', }) export class PaymentService { constructor(private http: HttpClient) {} startPayment() { const headers = new HttpHeaders({ 'Content-Type': 'text/html', }); this.http .post('http://localhost:5000/create-checkout-session', {}, { headers }) .subscribe((res) => console.log(res)); } }
问题分析
- 后端重定向逻辑错误:后端用
res.redirect直接跳转到Stripe的结账URL,但前端是通过XMLHttpRequest(Angular HttpClient)发起的请求,重定向后会请求Stripe的域名,而Stripe服务器没有配置允许http://localhost:4200的CORS权限,导致报错。 - 前端请求头设置错误:手动设置
Content-Type: text/html,但后端用express.json()解析JSON格式的请求,这个头会导致后端无法正确处理请求,同时也不符合接口的实际需求。
解决方案
修改后端代码
将接口改为返回Stripe会话URL的JSON响应,而非直接重定向:
app.post('/create-checkout-session', async (req, res) => { console.log(process.env.STRIPE_API_KEY); try { const session = await stripe.checkout.sessions.create({ line_items: [ { price: process.env.STRIPE_PRICE, quantity: 1, }, ], mode: 'payment', success_url: `http://localhost:4200/success`, // 替换为你的前端成功页面 cancel_url: `http://localhost:4200/cancel`, // 替换为你的前端取消页面 automatic_tax: { enabled: true }, }); // 返回会话URL给前端,由前端跳转 res.json({ url: session.url }); } catch (error) { // 捕获错误并返回给前端 res.status(500).json({ error: error.message }); } });
修改前端代码
移除错误的请求头,获取后端返回的URL后直接跳转至Stripe结账页面:
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root', }) export class PaymentService { constructor(private http: HttpClient) {} startPayment() { this.http .post<{ url: string }>('http://localhost:5000/create-checkout-session', {}) .subscribe({ next: (res) => { // 跳转到Stripe的结账页面 window.location.href = res.url; }, error: (err) => { console.error('创建支付会话失败:', err); }, }); } }
额外优化建议
- CORS配置收紧:将后端的
cors({origin: '*'})改为指定允许的域名,比如origin: 'http://localhost:4200',生产环境替换为你的正式域名,提升安全性。 - 错误处理:前后端都增加错误捕获逻辑,便于排查问题。
内容的提问来源于stack exchange,提问作者Bartłomiej Wydrzycki
相关产品推荐
相关产品推荐

