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 ?