Django Stripe Integration using dj-stripe

I had the opportunity to examine dj-stripe while researching which payment libraries are used in Django projects. If you are going to integrate a payment system into your project, you may want to have features such as subscription management or single-unit purchases. Especially subscription management is quite essential and time-consuming subject for SaaS projects. dj-stripe takes care of this.
Prerequisites
Before starting the implementation of dj-stripe, make sure that you have fulfilled the requirements below:
- A Django project (Django version>= 2.2)
- Python version >= 3.6
- Ready to use Stripe account
Installation
First of all, we should install dj-stripe with pip:
pip install dj-stripe
Then we add djstripe to INSTALLED_APPS:
INSTALLED_APPS=(
...
"djstripe",
...
)
and add to urls.py:
path("stripe/", include("djstripe.urls", namespace="djstripe"))
Stripe Settings
Webhooks
We need to add our webhook address to Stripe. Our webhook address should be like [https://domain.com/stripe/webhook].
You can find webhook endpoints Developers > Webhooks in Stripe Dashboard. After creating a webhook endpoint in the Stripe dashboard, we get our webhook secret key, which starts with whsec_.

API Keys

We take our Stripe public and secret keys from Developers > API Keys then add them to our .env file. Our settings.py file should be like:
STRIPE_LIVE_PUBLIC_KEY = os.environ.get("STRIPE_LIVE_PUBLIC_KEY", "<your publishable key>")
STRIPE_LIVE_SECRET_KEY = os.environ.get("STRIPE_LIVE_SECRET_KEY", "<your secret key>")
STRIPE_TEST_PUBLIC_KEY = os.environ.get("STRIPE_TEST_PUBLIC_KEY", "<your publishable key>")
STRIPE_TEST_SECRET_KEY = os.environ.get("STRIPE_TEST_SECRET_KEY", "<your secret key>")
STRIPE_LIVE_MODE = False
DJSTRIPE_WEBHOOK_SECRET = "whsec_xxx"
dj-stripe will use your test keys while STRIPE_LIVE_MODE is False.
Plans
Let’s create a plan. We click the Product button on the sidebar.

“Name” field is required. I created a recurring plan with three days of a free trial.
We run the below commands to create dj-stripe tables, initialize existing customers on Stripe and migrate created plans from Stripe to our dj-stripe tables:
python manage.py migratepython manage.py djstripe_init_customerspython manage.py djstripe_sync_plans_from_stripe
Events
I need to talk about Stripe events as well. Stripe has various event types. You should specify which events you want to listen to from API.
You may send an email to the customer when checkout fails, or you may want to remind your customer that the subscription will end in x days. In these cases, you will choose the events you want to listen to on the Stripe dashboard, and you should implement a listener method for each.
We choose our events on the Developer > Webhooks page.

Let’s create an endpoint for customer deleted event:
from djstripeimport webhooksfrom django.core.mail import send_mail@webhooks.handler("customer.deleted")
def customer_deleted_event_listener(event, **kwargs):
send_mail(
'Subscription Deleted',
'See ya! 👋',
'from@example.com',
['to@example.com'],
fail_silently=False,
)
We can find customer information inside the event variable.
Checkout
I prefer “Stripe Checkout,” which means customers will pay on the stripe.com domain. However, you can implement it on your client application as well.
Checkout creates a secure, Stripe-hosted payment page that lets you collect payments quickly. It works across devices and is designed to increase your conversion.
For more information >> https://stripe.com/docs/payments/checkout
In the Stripe Checkout method, when implementing a SaaS application API, we should create a Stripe session which has some customer information about the checkout step (e.g., plan name, customer id)
customer = Customer.objects.get(subscriber=request.user) stripe.api_key = STRIPE_SECRET_KEY session = stripe.checkout.Session.create( customer=customer.id, payment_method_types=['card'], subscription_data={ 'items': [{ 'plan': request.data["plan"], }], }, success_url='http://example.com/success', cancel_url='http://example.com/cancelled', ) data = { "session_id": session.id }return JsonResponse(data, status=200)
After creating session_id, we deliver it to our client application.
We should import Stripe.js before implementing checkout steps on the client.
We add the below code line to our .html file:
<script src="https://js.stripe.com/v3/"></script>
We initialize a stripe object:
var stripe = Stripe(YOUR_PUBLIC_KEY);
When a customer clicks the “Subscribe Now” button, it should run the piece of code below:
stripe.redirectToCheckout({ sessionId: this.state.session_id }) .then(function(result) { // If `redirectToCheckout` fails due to a browser or network // error, display the localized error message to your customer // using `result.error.message`. var displayError = document.getElementById('error-message'); displayError.textContent = result.error.message;});
When a customer clicks the button, they see the below page:

P.S: If you use Stripe test keys, the page is displayed in test mode. You can test your checkout step with test card numbers.
- Default U.S. card —
4242 4242 4242 4242
- Authenticate with 3D Secure —
4000 0000 0000 3220
Conclusion:
We’ve created a successful Stripe integration using the dj-stripe project. I tried to keep this blog post as simple as possible for quick implementation and understandability.
Stripe has lots of features with excellent documentation. I suggest that you read through it before using Stripe.
Author: Berat Nakip
Date Published: Jul 2, 2020
