You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Django/Python构建多订阅Stripe支付通道的技术咨询

解决方案:一次性结算混合商品+多频次独立订阅的Stripe实现

核心问题说明

Stripe Checkout不支持在同一个会话中添加不同计费频次的多个订阅(如月付和年付订阅无法共存于一个Checkout Session),因此需要采用自定义支付流程结合批量订阅创建的方案,既能实现一次性结算,又能保证每个订阅独立可取消。

推荐API方案:Setup Intent + Payment Intent + 独立订阅创建

通过以下组合实现需求:

  • Setup Intent:安全收集并保存客户支付方式到客户对象
  • Payment Intent:一次性收取所有商品(单次购买+订阅初始费用)的总金额
  • Subscription API:为每个订阅产品单独创建独立订阅,关联同一支付方式

开发流程大纲(Django/Python)

1. 前置校验

确保已完成:

  • 客户对象的创建/检索(绑定当前Django用户)
  • 所有商品(单次+订阅)的price_id已生成并可用
  • 确认所有金额的货币单位统一(如人民币分、美元分)

2. 前端收集支付方式

  • 在Django模板中引入Stripe.js,初始化Stripe Elements组件用于支付信息输入
  • 后端创建Setup Intent,传递client_secret给前端:
    import stripe
    
    stripe.api_key = "你的Stripe秘钥"
    
    def create_setup_intent(request):
        customer_id = request.user.stripe_customer_id  # 假设已关联
        setup_intent = stripe.SetupIntent.create(
            customer=customer_id,
            payment_method_types=["card"],
        )
        return JsonResponse({"client_secret": setup_intent.client_secret})
    
  • 前端通过Stripe Elements完成支付方式确认,成功后获取payment_method_id并传递给后端

3. 计算一次性结算总金额

  • 单次购买商品金额:通过stripe.Price.retrieve(one_time_price_id).unit_amount获取
  • 每个订阅的初始费用:获取对应price_id的首月/首期金额(含设置费、优惠等)
  • 总金额 = 单次商品金额 + 所有订阅首期费用总和(单位为货币最小单位,如分)

4. 创建并确认Payment Intent收取费用

  • 后端创建并确认Payment Intent,完成一次性扣费:
    def process_payment(request):
        customer_id = request.user.stripe_customer_id
        payment_method_id = request.POST.get("payment_method_id")
        total_amount = 计算好的总金额(如1000表示10元)
    
        payment_intent = stripe.PaymentIntent.create(
            amount=total_amount,
            currency="cn",
            customer=customer_id,
            payment_method=payment_method_id,
            confirm=True,
            return_url=f"{request.scheme}://{request.get_host()}/payment-success/",
        )
    
        if payment_intent.status == "succeeded":
            # 继续创建订阅
            return JsonResponse({"status": "success", "payment_intent_id": payment_intent.id})
        else:
            return JsonResponse({"status": "failed", "error": payment_intent.last_payment_error.message})
    

5. 批量创建独立订阅

支付成功后,为每个订阅产品单独创建Subscription:

def create_subscriptions(request):
    customer_id = request.user.stripe_customer_id
    payment_method_id = request.POST.get("payment_method_id")
    subscription_price_ids = request.POST.getlist("subscription_price_ids")  # 多个订阅的price_id列表

    created_subscriptions = []
    for price_id in subscription_price_ids:
        subscription = stripe.Subscription.create(
            customer=customer_id,
            items=[{"price": price_id}],
            default_payment_method=payment_method_id,
            proration_behavior="create_prorations",  # 根据业务需求调整
        )
        created_subscriptions.append(subscription.id)

    return JsonResponse({"subscriptions": created_subscriptions})

每个订阅为独立对象,后续可单独调用stripe.Subscription.cancel(subscription_id)取消,不影响其他订阅。

6. 订阅管理前端实现

  • 通过stripe.Subscription.list(customer=customer_id)获取客户所有订阅
  • 为每个订阅展示详情(产品名称、频次、金额)及取消按钮
  • 点击取消按钮时,后端调用Stripe API取消对应订阅即可

关键注意事项

  • 错误回滚:若Payment Intent成功但部分订阅创建失败,需处理退款逻辑或重新创建订阅
  • 支付方式默认设置:确保保存的支付方式设为客户默认支付方式,方便后续订阅自动扣费
  • 合规处理:遵循Stripe的PCI合规要求,避免直接处理信用卡信息

内容的提问来源于stack exchange,提问作者Ahima

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:18:18