Stripe Subscriptions: How to find renewals that might fail due to an expiring credit card?

Category: Development

You need to know which renewals for a subscriptions of your customers could potentially fail, because the credit card is about to expire? Here is a handy python script.

Introduction

Stripe's subscriptions model is great, when it comes to automatic card updates: It tries to update the card, if it's about to expire. You can read more about this feature at Stripe documentation.

Sometimes Stripe can not automatically update the credit card of a customer and you'd like to know:

  • Which subscriptions are going to be renewed and the assigned credit card is going to be expire at that moment in future?

With the following python script, you can list the subscriptions which are going to be renewed in the next 90 days and the credit card will be expired at that date.

Setup

The setup is the same as in my other Stripe article, which talks about the general status of credit cards assigned to subscriptions.

Python Script

Create a python script with a filename you'd like (e.g. 'check_renewals.py'):

check_renewals.py
import os import stripe import pendulum from dotenv import load_dotenv if os.environ.get("PY_ENV") == "production": load_dotenv(".env.production") else: load_dotenv() from rich.console import Console from rich.table import Table from rich.progress import Progress from rich import box stripe.api_key = os.environ.get("STRIPE_KEY") # how many days to look into the future for upcoming renewals days_in_the_future = 90 # items to retrieve default_limit = 30 now = pendulum.now() now_timestamp = pendulum.now().int_timestamp subscriptions = stripe.Subscription.search( limit=default_limit, query='status:"active" OR status:"past_due"', expand=["total_count", "data.customer", "data.customer.invoice_settings.default_payment_method"] ) total_count = subscriptions.total_count print(f"Subscriptions: {total_count}") table = Table(title=f"Upcoming Subscription renewals within {days_in_the_future} days", box=box.MINIMAL, title_style="bold blue", header_style="blue") table.add_column("Subscription", no_wrap=True) table.add_column("Customer", no_wrap=True) table.add_column("Email", no_wrap=True) table.add_column("Renews at (days)", no_wrap=True) table.add_column("Card exp", no_wrap=True) table.add_column("Status", justify="center") console = Console() with Progress(console=console) as progress: task = progress.add_task("Getting data", total=total_count) # for subscription in subscriptions: for subscription in subscriptions.auto_paging_iter(): has_default_card = False card_text = "-" card_expires_at = now_timestamp status_dots = "" progress.update(task, advance=1) customer = subscription.customer current_period_end = pendulum.from_timestamp(subscription.current_period_end) diff_days = current_period_end.diff(now).in_days() if diff_days <= days_in_the_future: default_card = customer.invoice_settings.default_payment_method if default_card: has_default_card = True card_expires_at = pendulum.datetime( default_card.card.exp_year, default_card.card.exp_month, 1, 0, 0, 0 ).end_of("month").timestamp() card_text = ( f"{default_card.card.last4}, {default_card.card.exp_month:02d}" f" / {default_card.card.exp_year}" ) if card_expires_at < subscription.current_period_end: status_dots = "[red not dim]⬤ [/]" else: status_dots = "[green dim]⬤ [/]" table.add_row( subscription.id, customer.id, customer.email, current_period_end.format("YY-MM-DD") + f" ({diff_days})", card_text, status_dots ) console.print(table)

When you run the script with the following command ...

PY_ENV=production pipenv run python check_renewals.py

... you will get an output which shows all subscriptions, which are going to be renewed in the upcoming 90 days. If the credit card is still valid at this date, a green status is displayed, otherwise a red one.

I use this script from time to time to have an overview and manually check, if the automatic credit card of Stripe is going to work. It comes in handy to inform your customers that the renewal could not work, because the credit card is going to be expire.

I hope this script helps you and if you've any comment or you need support with your Stripe implementation, just drop me an email.