如何实现Stripe Connect多商家结账并正确分账至对应关联账户
多商家购物车的Stripe Connect实现方案
要实现跨商家商品的购物车支付,你不能直接在单个Checkout Session的payment_intent_data.transfer_data里指定多个目标账户(Stripe限制单个Payment Intent只能关联一笔转账)。正确的做法是先将全款收至平台账户,支付完成后通过Webhook触发分账,向不同商家的关联账户发起转账,同时利用transfer_group关联所有转账与原支付,避免丢失资金来源信息。
步骤1:修改Checkout Session创建逻辑
移除原代码中payment_intent_data.transfer_data的配置,转而在metadata中记录每个商家的分账明细(关联账户ID、应得金额、对应商品信息),同时指定transfer_group(用订单ID或Checkout Session ID即可),方便后续关联转账与原支付。
export const checkoutSessionMultiMerchant = functions.https.onCall(async (data, context) => { // 假设data中包含: // line_items: 购物车商品列表 // merchantSplits: 分账明细数组,格式如[{connectId: 'acct_xxx', amount: 1000, itemIds: ['item_1', 'item_2']}] const orderId = `order_${Date.now()}`; // 生成唯一订单ID const session = await stripe.checkout.sessions.create({ line_items: data.line_items, mode: "payment", success_url: "***", cancel_url: "***", payment_intent_data: { // 不指定transfer_data,全款先进入平台账户 metadata: { orderId, // 将分账明细转为JSON字符串存储(Stripe metadata仅支持字符串) merchantSplits: JSON.stringify(data.merchantSplits), }, // 指定transfer_group,后续转账时关联此值 transfer_group: orderId, }, }); return session; });
步骤2:配置Stripe Webhook处理分账
监听Stripe的checkout.session.completed事件,当支付成功后,从事件中提取分账明细,向每个商家的关联账户发起转账。同时在转账的metadata中记录对应商品ID,解决你提到的“资金对应商品来源丢失”问题。
export const stripeWebhook = functions.https.onRequest(async (req, res) => { const sig = req.headers["stripe-signature"]; const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET; let event; try { event = stripe.webhooks.constructEvent( req.rawBody, sig, webhookSecret ); } catch (err) { res.status(400).send(`Webhook Error: ${err.message}`); return; } // 处理支付完成事件 if (event.type === "checkout.session.completed") { const session = event.data.object; const paymentIntentId = session.payment_intent; const merchantSplits = JSON.parse(session.metadata.merchantSplits); const transferGroup = session.payment_intent_data.transfer_group; // 遍历分账明细,创建转账 for (const split of merchantSplits) { await stripe.transfers.create({ amount: split.amount, // 单位:分(如1000=10美元) currency: "usd", // 根据你的业务调整币种 destination: split.connectId, transfer_group: transferGroup, // 关联到原支付的transfer_group metadata: { orderId: session.metadata.orderId, itemIds: split.itemIds.join(","), // 记录对应商品ID,方便追踪 }, source_transaction: paymentIntentId, // 指定资金来源为该支付Intent }); } } res.json({ received: true }); });
关键注意事项
- Transfer Group的作用:通过
transfer_group将所有转账与原Payment Intent绑定,在Stripe控制台中可通过该分组查看同一订单下的所有转账,解决你之前丢失资金来源的问题。 - 手续费计算:你可以选择两种方式收取平台手续费:
- 从每个商家的应得金额中扣除后再转账(如商家应得1000分,扣100分手续费,转账900分)
- 先将全款收至平台,转账时只转商家应得部分,平台留存剩余金额作为手续费
- Webhook签名验证:必须配置Stripe Webhook Secret并验证签名,避免恶意请求。
- 错误处理:建议在转账逻辑中添加重试机制(如遇到网络错误时重试),并记录转账状态到Firebase数据库,方便后续对账与异常处理。
为什么之前的方案不可行
payment_intent_data.transfer_data仅支持单个目标账户,无法设置数组;- 直接使用Transfer Groups而不通过Webhook触发,会错过支付成功的时机,且无法关联商品信息;
- Destination Charges模式需要为每个商家单独创建Charge,无法适配同一购物车的一笔支付场景。
内容的提问来源于stack exchange,提问作者CurlyHead
相关产品推荐
相关产品推荐

