Customers Contact TR

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_.


Screen Shot — https://dashboard.stripe.com/webhooks

API Keys

Screen Shot — https://dashboard.stripe.com/apikeys

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", "")
STRIPE_LIVE_SECRET_KEY = os.environ.get("STRIPE_LIVE_SECRET_KEY", "")
STRIPE_TEST_PUBLIC_KEY = os.environ.get("STRIPE_TEST_PUBLIC_KEY", "")
STRIPE_TEST_SECRET_KEY = os.environ.get("STRIPE_TEST_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.


Screen Shot — https://dashboard.stripe.com/products/create

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 migrate
python manage.py djstripe_init_customers
python 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.


Screen Shot — https://dashboard.stripe.com/webhooks/we_xxx

Let’s create an endpoint for customer deleted event:


from djstripe import webhooks
from 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:




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:


Screen Shot — https://stripe.com/docs/payments/checkout

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