Stripe Subscription Update with Django and React

I have developed backend implementation for Stripe API calls to handle the following requests :

urlpatterns = [
    path('subscription', SubscriptionCreate.as_view(), name="create_subscription"),
    path('add_payment_method', PaymentIntentCreate.as_view(), name="add_payment_method"),
    path('delete_payment_method', PaymentIntentDelete.as_view(), name="add_payment_method"),
    path('customer', CustomerView.as_view(), name="customerview"),
    path('webhook', stripe_webhook, name="stripe_webhook")
]

Here below are my models in Django backend to handle information regarding products and the customer :

class Product(models.Model):
    class Plan(models.IntegerChoices):
        FREE         = 0, _('Free')
        BASIC        = 1, _('Basic')
        PREMIUM      = 2, _('Premium')
        ENTENPRISE   = 3, _('Enterprise')
    plan = models.PositiveSmallIntegerField(choices=Plan.choices, null=False, blank=False, default=Plan.FREE)
    stripe_plan_id = models.CharField(max_length=40)

class Customer(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    stripe_customer_id = models.CharField(max_length=40, default="")
    product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
    
    stripe_subscription_id = models.CharField(max_length=40, default="")
    clientsecret = models.CharField(max_length=80, default="")
    active = models.BooleanField(default=True)

Also I have a post_save function that is triggered by "User Creation in Django" which also creates a Stripe Customer associated with each user and a subscription with a FREE plan that does not require payment / card information :

post_save.connect(post_save_customer_create, sender=settings.AUTH_USER_MODEL)
stripe_subscription = stripe.Subscription.create(
    customer=customer.stripe_customer_id,
    items=[{"price": customer.product.stripe_plan_id},],
    payment_behavior='default_incomplete',
    payment_settings={'save_default_payment_method': 'on_subscription'},
    expand=['latest_invoice.payment_intent'],
)

However, when the user wants to upgrade their subscription from Free to Paid models (Basic, Premium, Enterprise) then payment method / card information is required.

In this case I want the subscription get into a "Incomplete" state until the payment is confirmed by Stripe.

I use the following Subscription update strategy :

if (selected_product.plan == 0 and customer.product.plan != selected_product.plan) or (selected_product.plan > 0 and stripe_customer.invoice_settings.default_payment_method != None and customer.product.plan != selected_product.plan):
       new_subscription = stripe.Subscription.modify(
           stripe_subscription.id,
           items=[
                  {"id": stripe_subscription['items']['data'][0].id, "price": selected_product.stripe_plan_id },
                 ],
           payment_behavior='default_incomplete',
           payment_settings={'save_default_payment_method': 'on_subscription'},
           expand=['latest_invoice.payment_intent'],
       )

How can I get the subscription into an incomplete / inactive state and check if the payment has been done ?

How can I provide frontend a link or the mechanism to authenticate the purchase, so I can make sure that the subscription is correctly achieved ?

Back to Top