Express API中req.body为undefined的Stripe支付集成问题
问题产生原因
- 前端
fetch请求传参错误:fetch的body字段不支持直接传入JavaScript普通对象,直接传入时对象会被默认转成[object Object]字符串,不符合application/json的格式要求,Express的JSON解析中间件无法正确解析,导致req.body为空。 - 后端取参字段不匹配:前端传入的金额字段名为
totalAmount,但后端代码读取的是req.body.amount,即使请求体正常解析也无法拿到对应金额值。 - 后端逻辑缺陷:当前创建Stripe PaymentIntent时金额是硬编码的5000,没有使用前端传入的动态金额,不符合业务预期。
修复方案
前端代码修复
调用fetch时,必须将请求体对象通过JSON.stringify序列化为JSON字符串再传入,修正后的代码如下:
let data={totalAmount:amount, name:'XYZ_Name'} fetch('http://10.0.2.2:3500/create-payment-intent', { method: 'POST', headers: { "Content-Type": "application/json" }, body: JSON.stringify(data), // 序列化JS对象为JSON字符串 })
注意:React Native环境下的fetch和浏览器端fetch行为一致,body仅接受字符串、FormData、Blob等结构化类型,直接传普通对象无法被正确识别。
后端代码修复
- 修正取参逻辑,读取和前端一致的
totalAmount字段 - 替换硬编码的支付金额,使用前端传入的数值,注意Stripe接口要求金额为对应货币的最小单位(如英镑需转换为便士,即传入金额为实际英镑数*100)
- 增加基础参数校验和错误捕获,避免服务异常崩溃
修正后的接口代码如下:
const app = express(); // 中间件注册顺序正确,无需调整 app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.post('/create-payment-intent', async (req,res)=>{ try { console.log('接收到的请求参数', req.body); const { totalAmount } = req.body; // 校验金额合法性 if (!totalAmount || isNaN(Number(totalAmount)) || Number(totalAmount) <= 0) { return res.status(400).send({ error: '支付金额不合法' }); } // 转换为Stripe要求的最小货币单位(英镑为便士) const stripeAmount = Math.round(Number(totalAmount) * 100); const paymentIntent = await stripe.paymentIntents.create({ amount: stripeAmount, currency:'gbp', }); res.send({ clientSecret: paymentIntent.client_secret, paymentIntent, }) } catch (error) { console.log('创建支付意向失败:', error); res.status(500).send({ error: error.message }); } }) app.listen(3500,()=>{console.log('API Running!')});
验证要点
- 修改完成后重启Express后端服务,重新触发前端支付请求
- 观察后端控制台日志,确认可以正常打印出包含
totalAmount、name字段的请求体对象 - 核对Stripe后台生成的PaymentIntent金额,确认和前端传入的金额一致
- 若仍无法收到参数,检查安卓模拟器网络权限、本地3500端口是否被防火墙拦截
内容的提问来源于stack exchange,提问作者Syed Bilal Haider
相关产品推荐
相关产品推荐

