如何在 Stripe 中实现商品变体(如尺码)与库存控制的完整方案

6次阅读

如何在 Stripe 中实现商品变体(如尺码)与库存控制的完整方案

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)功能。所有库存状态(总库存、已售、待支付锁定量)必须在你自己的数据库中维护。关键流程如下:

  1. 添加至购物车时:检查实时可用库存(available_stock >= quantity);
  2. 创建 Checkout Session 前:对库存执行「预占」(soft reserve),例如:
    // 使用数据库事务确保原子性 await prisma.$transaction([   prisma.productVariant.update({     where: { id: "v_tshirt_m" },     data: { reservedStock: { increment: quantity } },   }),   prisma.cartItem.create({ /* ... */ }), ]);
  3. 支付成功后(Webhook checkout.session.completed):将 reservedStock 转为 soldStock,availableStock -= quantity;
  4. 支付失败或会话过期(Webhook checkout.session.expired):释放 reservedStock;
  5. 手动取消订单:同样需回滚库存。

? 重要提醒:务必通过 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 设计哲学的实现路径。

text=ZqhQzanResources