Products Solutions 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 to 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



  • A Django project (Django version>= 2.2)
  • Python version >= 3.6
  • Ready to use Stripe account

Installation



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



You can find webhook endpoints Developers > Webhooks  in Stripe Dashboard. After we create a webhook endpoint in 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", "<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



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

Name” field is required. I created a recurring plan with 3 days of free trial.


We run 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



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 in 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 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



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 Stripe Checkout method, when implementing a SaaS application API, we should create a Stripe session which has some customer information about 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 “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:



Stripe has lots of features with fantastic documentation. I suggest that you read through it before using Stripe.

 

Author: Berat Nakip

Date Published: Jul 2, 2020