Stripe Subscription Integration

Stripe Subscription Integration

I want to add a few more steps to this tutorial in this blog post. You can think of this blog post as a continuation of the tutorial link I gave.

Showing Subscription Page to User

After the user subscribes to your system, he may want to cancel/upgrade/downgrade the subscription or he may want to see the details of his subscription. At this point, we need to provide a button to the user that redirects to the Stripe subscription detail page so he can do whatever he wants. The code part of returning Stripe billing portal of the user is very simple and you will understand it when you look at the code below. I won’t talk anymore and show the code and move on to the next section.

    def get_billing_portal_url(self, user, storage: AbstractStorage):
        Get billing portal url
        :param user: User
        :param storage: AbstractStorage
        :return: url
        customer = self._get_customer(user, storage)  # get customer info from db
        if customer.stripe_customer_id:
            session = stripe.billing_portal.Session.create(
            return session.url
        return None

Handling Subscription Changes/Updates

There are 4 different cases:

  • User cancels his subscription
  • The user’s subscription is automatically renewed by recurring/monthly payment automatically via Stripe – so you may need to update the subscription dates in your system
  • In the case of recurring payments, the process may end up in failure or success, you need to handle them separately. In case of failure, you may need to downgrade or remove the subscription of the user in your system.

I won’t write detailed code here, I will just give you the necessary event types with descriptions and you will understand what you need to do in your system. You can handle these events in your system accordingly:

  • invoice.payment_succeeded: Sent each time an invoice payment succeeds, which would typically indicate a successful renewal of the subscription.
  • invoice.payment_failed: Sent if Stripe attempts to charge the customer’s payment method for a subscription but fails.
  • customer.subscription.updated: Sent when a subscription changes (e.g., upgrading or downgrading a plan).
  • customer.subscription.deleted: Sent when a subscription is cancelled.

You can handle these events just as checkout.session.completed like this:

if event["type"] == "checkout.session.completed":
elif event['type'] == 'invoice.payment_succeeded':
elif event['type'] == 'invoice.payment_failed'
elif event['type'] == 'customer.subscription.deleted':