使用Stripe时出现TypeError:无法读取undefined的map属性
问题修复:单个商品结账显示所有商品+TypeError报错
问题根源
TypeError: Cannot read properties of undefined (reading 'map'):
- 服务器端Stripe会话创建的字段名拼写错误,
line_item应为复数line_items - 未对
req.body.items做空值判断,前端未正确传值时会触发map调用失败 - 错误将Stripe的
priceId赋值给unit_amount(unit_amount需传入金额分数值,而非price ID)
- 服务器端Stripe会话创建的字段名拼写错误,
结账显示所有商品:
- 前端
checkout.js硬编码了所有商品ID到请求体,未仅传递选中的单个商品
- 前端
修复步骤及代码修改
1. 修正server.js代码
// require("dotenv").config() // This is your test secret API key. const stripe = require('stripe')('sk_test_XXXXXXX') const express = require('express') const app = express() app.use(express.static('public')) app.use(express.json()) const YOUR_DOMAIN = 'http://localhost:4242'; const storeItems = new Map([ [1, { priceId: 'price_XXXXXX', name: "Black Sweatsuit"}], [2, { priceId: 'price_XXXXXX', name: "Grey Sweatsuit"}] , [3, { priceId: 'price_XXXXXX', name: "Red Sweatsuit"}], [4, { priceId: 'price_XXXXXX', name: "Blue Sweatsuit"}], [5, { priceId: 'price_XXXXXX', name: "Black T-Shirt"}], [6, { priceId: 'price_XXXXXX', name: "Blue T-Shirt"}], [7, { priceId: 'price_XXXXXX', name: "Purple T-Shirt"}], ]) app.post('/create-checkout-session', async (req, res) => { try { // 空值判断,避免map调用失败 const items = req.body.items || []; if (items.length === 0) { return res.status(400).json({ error: '未选择任何商品' }); } const session = await stripe.checkout.sessions.create({ payment_method_types: ['card'], mode: 'payment', // 修正字段名为line_items(复数) line_items: items.map(item => { const storeItem = storeItems.get(item.id) if (!storeItem) { throw new Error(`商品ID ${item.id} 不存在`); } // 直接使用Stripe已创建的price ID return { price: storeItem.priceId, quantity: item.quantity || 1 } }), success_url:`${YOUR_DOMAIN}/success.html`, cancel_url: `${YOUR_DOMAIN}/cancel.html`, automatic_tax: {enabled: true}, }) res.json({ url: session.url}) } catch (e) { res.status(500).json({ error: e.message }) } }) app.listen(4242, () => console.log('Running on port 4242'));
2. 修正checkout.js代码(支持单个商品选择)
先修改shop.html中的商品按钮,为每个按钮添加data-id属性:
<!-- 单个商品购买按钮示例 --> <button class="checkout-button" data-id="1">购买 Black Sweatsuit</button> <button class="checkout-button" data-id="2">购买 Grey Sweatsuit</button> <!-- 其他商品按钮同理 -->
再修改checkout.js:
// 给所有结账按钮绑定点击事件 document.querySelectorAll(".checkout-button").forEach(button => { button.addEventListener("click", () => { // 获取当前按钮对应的商品ID const productId = parseInt(button.dataset.id); fetch('/create-checkout-session', { method: 'POST', headers: { "Content-Type": "application/json" }, body: JSON.stringify({ // 仅传递选中的单个商品 items: [{ id: productId, quantity: 1 }] }), }) .then(res => { if (res.ok) return res.json() return res.json().then(json => Promise.reject(json)) }) .then(({ url }) => { window.location = url }) .catch(e => { console.error(e.error) }) }) })
关键修复点说明
- 字段名修正:Stripe Checkout会话要求商品列表字段为
line_items,单数字段会导致API无法识别 - 空值处理:增加
req.body.items的空值判断,避免undefined调用map方法 - 商品传递逻辑:通过按钮
data-id获取选中商品ID,仅传递单个商品数据 - Price ID使用:直接调用Stripe后台创建的
priceId,避免错误赋值unit_amount
内容的提问来源于stack exchange,提问作者user16147870
相关产品推荐
相关产品推荐

