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

基于Djstripe:确保订阅付款成功后再向客户确认订阅生效

如何在Django+Djstripe中确保Stripe订阅扣款成功后再确认给客户?

问题场景

我们在Django站点中使用Djstripe创建Stripe订阅,现有代码如下:

# Create the Stripe subscription
stripe_subscription = stripe.Subscription.create(
    customer=customer_id,
    items=[{'price': plan_id}],
    expand=['latest_invoice.payment_intent'],
    metadata=metadata,
)

# Sync subscription from Stripe
subscription = Subscription.sync_from_stripe_data(stripe_subscription)

Stripe的订阅创建流程为:

  1. 创建订阅(返回200状态码)
  2. 生成用于扣费的支付意向(Payment Intent)
  3. 尝试自动扣款
  4. 若扣款失败,订阅状态被设为incomplete

当前逻辑是收到步骤1的200响应后就默认付款成功,继续后续操作,但实际会出现扣款失败的情况,导致客户被错误告知订阅成功。需要实现仅当扣款实际成功时,才向客户确认订阅创建成功。


解决方案

1. 即时校验支付意向状态

由于创建订阅时已经通过expand=['latest_invoice.payment_intent']获取了关联的支付意向,可直接从返回的订阅对象中检查支付状态:

修改代码,增加状态判断逻辑:

# 创建Stripe订阅
stripe_subscription = stripe.Subscription.create(
    customer=customer_id,
    items=[{'price': plan_id}],
    expand=['latest_invoice.payment_intent'],
    metadata=metadata,
)

# 提取支付意向对象
payment_intent = stripe_subscription.latest_invoice.payment_intent

# 判断支付状态
if payment_intent.status == 'succeeded':
    # 扣款成功,同步订阅并执行后续操作(如通知客户)
    subscription = Subscription.sync_from_stripe_data(stripe_subscription)
    # 这里添加通知客户订阅成功的逻辑,比如发送邮件、更新用户状态等
elif payment_intent.status == 'requires_action':
    # 需要客户完成额外验证(如3DS),返回前端引导客户完成支付
    # 可将payment_intent.client_secret返回给前端,调用Stripe.js完成验证
    return JsonResponse({'client_secret': payment_intent.client_secret, 'status': 'requires_action'})
else:
    # 扣款失败,处理失败逻辑(如告知客户支付失败,取消订阅等)
    # 可选:主动取消incomplete状态的订阅
    stripe.Subscription.cancel(stripe_subscription.id)
    # 这里添加通知客户支付失败的逻辑

2. 依赖Stripe Webhook处理异步支付结果

部分支付场景(如3DS验证、延迟扣款)无法即时得到结果,必须通过Webhook监听Stripe的事件来确认最终支付状态:

需监听的关键事件:

  • invoice.paid:发票支付成功,代表订阅扣费完成
  • payment_intent.succeeded:支付意向执行成功
  • invoice.payment_failed:发票支付失败,订阅会进入incomplete或past_due状态

Djstripe Webhook处理示例:

from django.http import HttpResponse
from djstripe import webhooks
from djstripe.models import Subscription

@webhooks.handler("invoice.paid")
def handle_invoice_paid(event):
    invoice = event.data.object
    subscription_id = invoice.subscription
    # 同步订阅状态到本地
    subscription = Subscription.sync_from_stripe_id(subscription_id)
    # 执行订阅成功的后续操作:通知客户、激活用户权限等
    # ...

@webhooks.handler("invoice.payment_failed")
def handle_invoice_payment_failed(event):
    invoice = event.data.object
    subscription_id = invoice.subscription
    # 处理支付失败逻辑:通知客户、取消订阅或引导重新支付
    # ...

3. 补充注意事项

  • 确保Stripe Webhook已正确配置,且签名验证开启,防止伪造事件
  • 对于requires_action的支付,前端需集成Stripe Elements完成客户验证,验证完成后Stripe会触发对应的Webhook事件
  • 定期清理incomplete状态的订阅,避免无效数据积累

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 21:50:43