
stripe 的 custom_fields 不适用于商品变体选择和库存管理;正确做法是为每个变体创建独立的 product/price,并在应用层实现库存校验、预占与同步机制。
stripe 的 custom_fields 不适用于商品变体选择和库存管理;正确做法是为每个变体创建独立的 product/price,并在应用层实现库存校验、预占与同步机制。
在 Next.js 电商项目中集成 Stripe 时,开发者常误将 custom_fields 视为商品规格(如 T 恤的 S/M/L 尺码)的选择入口。但需明确:Stripe Checkout 的 custom_fields 是用于收集支付后所需的附加元数据(如 Discord 用户名、企业发票号等),而非替代前端商品变体逻辑。它不参与价格计算、不关联库存、不可动态禁用选项,且强制出现在结账页——这直接违背“用户应在商品页完成规格选择”的用户体验原则。
✅ 正确架构:变体即独立商品
应为每个 SKU(Stock Keeping Unit)创建独立的 Stripe Product 和 Price 对象。例如:
| 尺码 | Product ID | Price ID | 单价 |
|---|---|---|---|
| Small | prod_tshirt_s | price_tshirt_s | ¥99 |
| Medium | prod_tshirt_m | price_tshirt_m | ¥99 |
| Large | prod_tshirt_l | price_tshirt_l | ¥99 |
对应代码中,line_items 应显式传入所选变体的 Price ID:
// 前端:用户在商品页选择 "Medium" 后,提交该变体 ID
const selectedVariant = { priceId: "price_tshirt_m", quantity: 2 };
// 后端 API 路由(e.g., /api/create-checkout-session)
const checkoutSession = await stripe.checkout.sessions.create({
mode: "payment",
line_items: [{
price: selectedVariant.priceId,
quantity: selectedVariant.quantity,
}],
success_url: `${origin}/success`,
cancel_url: `${origin}/cart`,
// ⚠️ 移除 custom_fields —— 它在此场景下无意义
});? 库存管理:必须由你的应用完全承担
Stripe 不提供任何原生库存(inventory)功能。所有库存状态(总库存、已售、待支付锁定量)必须在你自己的数据库中维护。关键流程如下:
- 添加至购物车时:检查实时可用库存(available_stock >= quantity);
-
创建 Checkout Session 前:对库存执行「预占」(soft reserve),例如:
// 使用数据库事务确保原子性 await prisma.$transaction([ prisma.productVariant.update({ where: { id: "v_tshirt_m" }, data: { reservedStock: { increment: quantity } }, }), prisma.cartItem.create({ /* ... */ }), ]); - 支付成功后(Webhook checkout.session.completed):将 reservedStock 转为 soldStock,availableStock -= quantity;
- 支付失败或会话过期(Webhook checkout.session.expired):释放 reservedStock;
- 手动取消订单:同样需回滚库存。
? 重要提醒:务必通过 Stripe Webhook 验证事件真实性(使用 stripe.webhooks.constructEvent + 签名验证),绝不可仅依赖客户端回调。
? 补充建议与最佳实践
- 前端体验优化:在商品页动态渲染尺码按钮,并禁用库存为 0 的选项(通过调用 /api/variants?productId=xxx 获取实时库存状态);
- 防止超卖:对库存更新操作加数据库行级锁(如 PostgreSQL SELECT ... FOR UPDATE)或使用带条件的 UPDATE ... WHERE available_stock >= ?;
- 数据一致性兜底:每日运行库存对账脚本,比对 Stripe 支付记录与本地 soldStock;
- 扩展性考虑:若变体维度增多(如尺码 × 颜色 × 材质),可设计 product_variant 表,关联 product 并存储 sku, price_id, stock 字段。
总之,Stripe 是一个强大的支付管道,而非商品目录或库存系统。将变体建模为独立 Price、将库存逻辑完全收归应用层,是当前最健壮、可扩展且符合 Stripe 设计哲学的实现路径。










