为什么.map()首次输出数组正常,第二次返回undefined致Stripe报错?
问题描述
开发Next.js对接Stripe支付的API接口时遇到以下问题:
- 执行
bodyItems?.map()生成renderCartItems数组时,首次能输出符合Stripe要求的结构,第二次执行返回undefined - 第二次请求触发Stripe报错:
The line_items parameter is required in payment mode. - 接口会被执行两次,开启React严格模式后该现象仍存在
控制台日志输出:
[ { name: 'sped', qty: 1, price: 5000, img: { _type: 'image', asset: [Object] }, ogprice: 5000 } ] [ { price_data: { currency: 'usd', product_data: [Object], unit_amount: 5000 }, quantity: 1 } ] mapped undefined undefined mapped
相关API路由代码:
export default async function handler(req, res) { if (req.method === 'POST') { try { const bodyItems = req.body.items; console.log(bodyItems) const renderCartItems = bodyItems?.map( singleProduct => { return { price_data: { currency: 'usd', product_data: { name: singleProduct.name }, unit_amount: singleProduct.price }, quantity: singleProduct.qty, } }) console.log(renderCartItems, "mapped") // Create Checkout Sessions from body params. const session = await stripe.checkout.sessions.create({ line_items: renderCartItems, mode: 'payment', success_url: `http://localhost:3000/done`, cancel_url: `http://localhost:3000`, }); console.log(session.url) res.redirect(303, session.url); } catch (err) { res.status(err.statusCode || 500).json(err.message); } } else { res.setHeader('Allow', 'POST'); res.status(405).end('Method Not Allowed'); } }
解决方案
1. 排查前端重复请求来源
接口被调用两次的核心原因大概率在前端:
- 检查提交按钮是否未做防抖处理,导致重复点击触发请求
- 确认表单提交是否同时触发默认行为和自定义请求(未执行
event.preventDefault()阻止默认提交) - 排查组件渲染逻辑,是否因状态频繁变化导致重复发起POST请求
2. 给API接口加请求合法性校验
在处理Stripe会话创建前,先校验请求体的有效性,直接拦截无效请求:
export default async function handler(req, res) { if (req.method === 'POST') { try { const bodyItems = req.body.items; console.log(bodyItems) // 新增校验:确保items存在且为非空数组 if (!bodyItems || !Array.isArray(bodyItems) || bodyItems.length === 0) { return res.status(400).json({ error: "请求体中缺少有效商品列表" }); } const renderCartItems = bodyItems.map( singleProduct => { return { price_data: { currency: 'usd', product_data: { name: singleProduct.name }, unit_amount: singleProduct.price }, quantity: singleProduct.qty, } }) console.log(renderCartItems, "mapped") const session = await stripe.checkout.sessions.create({ line_items: renderCartItems, mode: 'payment', success_url: `http://localhost:3000/done`, cancel_url: `http://localhost:3000`, }); console.log(session.url) res.redirect(303, session.url); } catch (err) { res.status(err.statusCode || 500).json(err.message); } } else { res.setHeader('Allow', 'POST'); res.status(405).end('Method Not Allowed'); } }
3. 给renderCartItems加空值兜底
即使校验环节遗漏,通过兜底避免传递undefined给Stripe:
const renderCartItems = (bodyItems?.map(singleProduct => ({ price_data: { currency: 'usd', product_data: { name: singleProduct.name }, unit_amount: singleProduct.price }, quantity: singleProduct.qty, }))) || [];
4. 临时关闭React严格模式辅助排查
开发环境下React严格模式会重复执行组件的某些生命周期,可能间接引发重复请求。可以临时关闭next.config.js或app/layout.js中的严格模式,确认是否是严格模式触发的前端重复渲染导致的问题。
内容的提问来源于stack exchange,提问作者Johnny
相关产品推荐
相关产品推荐

