Django中使用Stripe实现三方支付分账的问题求助
Django + Stripe 分账问题:资金不足&卖家未收款的解决方案
核心问题分析
- 当前代码在循环中创建了两个独立的Checkout Session,每个都要求买家支付全额
total_charges。实际场景中买家只会完成一次支付,导致第二个Session对应的Transfer因无资金来源触发insufficient funds错误。 - 卖家未收款是因为买家大概率只完成了推荐人对应的Session支付,卖家的Session未被触发支付,自然没有转账。
最优解决方案:使用Stripe Connect 分账模式
针对三部分拆分需求(平台手续费、卖家收款、推荐人收款),推荐采用Separate Charges and Transfers模式:买家支付全额到平台账户,支付成功后,平台通过异步事件分别向卖家和推荐人发起转账。这种模式避免了重复创建支付会话的问题,且流程更可靠。
修正后的前端支付代码
if buyer_address.state.lower() in ['alabama', 'al']: taxes = int(round(float(price * 0.08))) else: taxes = 0 # 补充其他州的默认税值 shipping_charges = courier.price total_charges = price + taxes # 重新计算分账金额:确保总和等于total_charges seller_amount = int(total_charges * 0.8) # 对应原逻辑中平台抽20%后的卖家所得 referral_amount = int(total_charges * 0.004) # 原逻辑中推荐人拿平台手续费的2%,即总金额的0.4% admin_amount = total_charges - seller_amount - referral_amount stripe.api_key = "sk_test_EI5Kddsg2MCELde0vbX2cDGw" my_domain = "your-domain.com" # 替换为实际业务域名 try: # 仅创建一个Checkout Session,收取全额款项 session = stripe.checkout.Session.create( success_url=f"{my_domain}/payment_success/{auction_id}/{courier_id}?mode={mode}&session_id={{CHECKOUT_SESSION_ID}}", cancel_url=f"{my_domain}/payment_failed/{auction_id}/{courier_id}?mode={mode}", payment_method_types=['card'], mode='payment', line_items=[{ 'price_data': { 'currency': 'usd', 'product_data': { 'name': 'NailSent Nails', }, 'unit_amount': total_charges, # 单位:分 }, 'quantity': 1, }], payment_intent_data={ 'transfer_group': f"auction_{auction_id}" # 分组标识,用于关联后续转账 } ) # 跳转到Stripe支付页面 return redirect(session.url, code=303) except stripe.error.StripeError as e: return HttpResponse(f"Error: {e}")
关键补充:Webhook异步处理转账
必须通过Stripe Webhook监听支付成功事件,在事件触发时执行转账(同步创建转账易因网络问题失败,Webhook更可靠):
# views.py 中的Webhook处理视图 import stripe from django.http import HttpResponse from django.views.decorators.http import require_POST from django.views.decorators.csrf import csrf_exempt @csrf_exempt @require_POST def stripe_webhook(request): stripe.api_key = "sk_test_EI5Kddsg2MCELde0vbX2cDGw" endpoint_secret = "your_webhook_secret" # 从Stripe Dashboard获取签名密钥 payload = request.body sig_header = request.META.get('HTTP_STRIPE_SIGNATURE') event = None try: event = stripe.Webhook.construct_event( payload, sig_header, endpoint_secret ) except (ValueError, stripe.error.SignatureVerificationError): return HttpResponse(status=400) # 处理支付成功事件 if event['type'] == 'payment_intent.succeeded': payment_intent = event['data']['object'] transfer_group = payment_intent['transfer_group'] # 从分组标识解析拍卖ID,从数据库读取对应分账金额 auction_id = transfer_group.split('_')[1] # 替换为实际数据库查询逻辑,获取该订单的seller_amount和referral_amount seller_amount = ... referral_amount = ... # 转账给卖家 stripe.Transfer.create( amount=seller_amount, currency='usd', destination='acct_1OoODQIbLDChIvG2', transfer_group=transfer_group, ) # 转账给推荐人 stripe.Transfer.create( amount=referral_amount, currency='usd', destination='acct_1OrzPRI5g3KKKWKv', transfer_group=transfer_group, ) return HttpResponse(status=200)
额外注意事项
- 金额校验:确保
seller_amount + referral_amount + admin_amount严格等于total_charges,避免分账金额总和超出收款总额。 - 账户状态:卖家和推荐人的Connected Account必须完成Stripe入驻流程(onboarding),否则转账会失败。
- Webhook配置:在Stripe Dashboard中配置Webhook端点,启用
payment_intent.succeeded事件,并使用签名密钥验证事件真实性。 - 测试验证:使用Stripe测试卡号(如
4242 4242 4242 4242)在测试环境中验证分账流程,确认资金流向正确。
内容的提问来源于stack exchange,提问作者Tejinder Singh
相关产品推荐
相关产品推荐

