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

如何在Stripe中复用已保存客户实现无UI一次性额外扣费?

基于Stripe实现无UI重复扣费的问题与官方解决方案

场景

  • 首次带UI支付:用户通过前端使用常规Checkout Session流程,Stripe展示卡片表单,完成支付后保存customer_id。
  • 无UI额外扣费:首次支付后,前端提供「额外购买」按钮,无需用户再次输入卡片信息或查看Stripe表单,点击即可完成一次性扣费。

遇到的问题

  • 创建Stripe客户时payment_method为空,创建新PaymentIntent扣费需指定payment_method。
  • 查询客户的PaymentMethod列表为空或null,无法获取有效PaymentMethod ID。
  • 复用首次扣费的PaymentMethod ID时,Stripe报错:You cannot use a PaymentMethod that was already used。
  • 不确定是操作有误,还是无法在不重新获取卡片信息的情况下再次扣费。
  • 如何将卡片或PaymentMethod与客户关联,以便后续仅通过后端完成无UI扣费?

问题根源

  1. 常规Checkout Session默认不会将支付方式(PaymentMethod)附加到客户账户,仅用于单次支付,支付完成后该PaymentMethod无法重复使用。
  2. 未配置setup_future_usage参数,Stripe不会自动保存支付方式供后续无会话(off-session)扣费使用。
  3. 检索Checkout Session时未展开关联的payment_intent和payment_method字段,导致无法获取已保存的有效PaymentMethod ID。

官方推荐解决方案

步骤1:修改首次Checkout Session创建逻辑

添加payment_intent_data配置,明确告知Stripe保存支付方式到客户账户,用于后续无会话扣费:

@api_view(['POST'])
def create_payment(request):
    session = StripeSingleton().checkout.Session.create(
        success_url=f'{settings.STRIPE_SUCCESS_URL}?session_id={{CHECKOUT_SESSION_ID}}',
        line_items=[{'price': 'price_XXXX', 'quantity': 1}],
        mode='payment',
        # 关键配置:保存支付方式到客户,支持后续无会话扣费
        payment_intent_data={
            'setup_future_usage': 'off_session',
            'description': 'Initial payment with saved payment method',
        },
    )
    return Response({'success_url': session['url']}, status=200)

步骤2:验证支付并获取已保存的PaymentMethod

检索Checkout Session时展开关联字段,获取已附加到客户的PaymentMethod ID并保存:

@api_view(['GET'])
def validate_payment(request):
    session_id = request.GET.get('session_id')
    # 展开关联的payment_intent和payment_method,获取有效支付方式ID
    session = StripeSingleton().checkout.Session.retrieve(
        session_id,
        expand=['payment_intent', 'payment_intent.payment_method']
    )
    customer_id = session.customer
    payment_method_id = session.payment_intent.payment_method
    
    # 将customer_id和payment_method_id存入数据库,供后续扣费使用
    # 示例:YourModel.objects.create(customer_id=customer_id, payment_method_id=payment_method_id)
    
    return Response({'customer_id': customer_id, 'payment_method_id': payment_method_id}, status=200)

步骤3:无UI额外扣费的正确实现

使用已保存到客户的PaymentMethod(或直接使用客户的默认支付方式)创建PaymentIntent:

# 方案1:自动使用客户的默认支付方式(无需指定payment_method)
payment_intent = stripe.PaymentIntent.create(
    amount=2000,  # 20比索,单位为分
    currency='mxn',
    customer=customer_id,
    off_session=True,
    confirm=True,
    description="Extra advice - one-off charge",
)

# 方案2:指定已保存的PaymentMethod ID
payment_intent = stripe.PaymentIntent.create(
    amount=2000,
    currency='mxn',
    customer=customer_id,
    payment_method=payment_method_id,  # 这里使用已附加到客户的PaymentMethod ID
    off_session=True,
    confirm=True,
    description="Extra advice - one-off charge",
)

关键注意事项

  • setup_future_usage: 'off_session'是实现重复扣费的核心,必须在首次支付时配置。
  • 已附加到客户的PaymentMethod可以重复使用,不会触发You cannot use a PaymentMethod that was already used错误。
  • 若后续需要管理客户的支付方式(如新增、删除),可调用Stripe的PaymentMethod.list(customer=customer_id)接口获取所有已保存的支付方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:32:47