what we will be building
Recently I added a subscription model to one of my projects,
New users are welcomed by an ‘upgrade’ button next to their user button. Clicking this will redirect them to a Stripe Checkout page, like so:
Creating a Checkout Session
If you do not have a Django project setup please checkout Django’s guide on getting started
Let’s create another endpoint for this:
def customer_portal(request):
stripe.api_key = '<stripe-api-key>'
try:
session = stripe.billing_portal.Session.create(
customer=request.user.customer.source_id,
return_url=settings.CLIENT_URL + '/settings',
)
except Exception as e:
return JsonResponse({'error': str(e)}, status=400)
return JsonResponse({'url': session.url}, status=201)
Make sure to enable the portal in your stripe settings
Make sure your application takes advantage of these new values in your production environment.
Congratiulations you now have a working subscription in your project!
Final notes
You are now ready to go, but there are some potential edge cases you want to consider handeling.
Canceled subscriptions that are still active
When a user cancels their subscription they still have access till the end of the subscription period, you might want to inform the user of this. Stripe provides us with some additional values, which we can add to our models.
First we update our models:
class Subscription(models.Model):
# ...
cancel_at_period_end = models.BooleanField(default=False)
cancel_at = models.DateTimeField(blank=True, null=True)
cancel_at_period_end indicates that our subscription will expire at the end of the billing period and cancel_at indicates at what date this will happen.
in our services we should also handle this to ensure these values are updated accordingly:
def handle_subscription_updated(event):
# ...
subscription.cancel_at_period_end = stripe_subscription.cancel_at_period_end
subscription.cancel_at = datetime.fromtimestamp(
stripe_subscription.cancel_at) if stripe_subscription.cancel_at else None
# ...
Next in our frontend we can handle it as such, where we render an alert if cancel_at_period_end:
subscription.cancel_at_period_end && (
<Alert>
<AlertCircleIcon className="h-4 w-4" />
<AlertTitle>Your subscription has been canceled</AlertTitle>
<AlertDescription>
You can continue using our services till the end if your current billing period. Your subscription
will end on {format(new Date(subscription.cancel_at), 'MMMM dd, yyyy')}
</AlertDescription>
</Alert>
)
Which should look something like this:
To see this example in action or if you are simply in need of a resume go checkout my latest project over at CV Forge!
SOCIAL SHARE CARD GENERATOR