In this tutorial, we will learn how to integrate a payment system in Django. We will be using Stripe as our payment gateway, but the process is similar for other payment gateways such as PayPal and Braintree. Integrating a payment system is essential for any e-commerce platform, and Django makes it relatively easy to do so with the help of third-party packages and a bit of customization. Let's get started!
Prerequisites
- Basic knowledge of Django and Python
- Django project set up and running
- Stripe account and API keys
Step 1: Install Required Packages
To integrate Stripe with our Django project, we need to install the following packages:
pip install stripepip install django-stripe-payments
The first package is the official Stripe Python library, and the second package, django-stripe-payments, is a Django package that simplifies the integration process.
Step 2: Configure Django Settings
Next, we need to add the Stripe API keys and configure the django-stripe-payments package in our Django settings.py file:
# settings.py# Stripe API keysSTRIPE_PUBLIC_KEY = 'your_stripe_public_key'STRIPE_PRIVATE_KEY = 'your_stripe_private_key'# django-stripe-payments configurationINSTALLED_APPS = [ # ... 'djstripe', # ...]DJSTRIPE_WEBHOOK_SECRET = 'your_stripe_webhook_secret'DJSTRIPE_USE_NATIVE_JSONFIELD = True
Replace 'your_stripe_public_key', 'your_stripe_private_key', and 'your_stripe_webhook_secret' with the corresponding values from your Stripe dashboard.
Step 3: Create a Payment Model
We need a model to store the payment information. Let's create a Payment model in our app's models.py file:
# models.pyfrom django.db import modelsfrom djstripe.models import StripeModelclass Payment(StripeModel): amount = models.DecimalField(max_digits=10, decimal_places=2) description = models.CharField(max_length=100) paid = models.BooleanField(default=False) user = models.ForeignKey(User, on_delete=models.CASCADE) def __str__(self): return f'{self.user.username} - {self.description}'
Here, we inherit from StripeModel, which is provided by django-stripe-payments and contains useful fields and methods for working with Stripe objects.
Step 4: Create a Payment Form
Now, let's create a form to collect the necessary payment information from the user. Create a new file called forms.py in your app directory and add the following code:
# forms.pyfrom django import formsfrom .models import Paymentclass PaymentForm(forms.ModelForm): class Meta: model = Payment fields = ('amount', 'description',) widgets = { 'amount': forms.NumberInput(attrs={'class': 'form-control'}), 'description': forms.TextInput(attrs={'class': 'form-control'}), }
Step 5: Create Payment Views
Next, let's create the views to handle the payment process. We will need two views: one to display the payment form and another to process the payment. Add the following code to your views.py file:
# views.pyfrom django.shortcuts import render, redirectfrom django.contrib import messagesfrom .forms import PaymentFormfrom .models import Paymentimport stripedef payment(request): form = PaymentForm(request.POST or None) if request.method == "POST": if form.is_valid(): payment = form.save(commit=False) payment.user = request.user payment.save() # Create a Stripe PaymentIntent stripe.api_key = settings.STRIPE_PRIVATE_KEY intent = stripe.PaymentIntent.create( amount=int(payment.amount * 100), currency='usd', metadata={'payment_id': payment.id} ) # Redirect to the payment processing view return redirect('process_payment', intent.client_secret) context = {'form': form} return render(request, 'payment.html', context)def process_payment(request, client_secret): if request.method == "POST": stripe.api_key = settings.STRIPE_PRIVATE_KEY intent = stripe.PaymentIntent.confirm(client_secret) if intent.status == 'succeeded': # Update the Payment model payment_id = intent.metadata['payment_id'] payment = Payment.objects.get(id=payment_id) payment.paid = True payment.save() messages.success(request, 'Payment successful!') return redirect('success') context = {'client_secret': client_secret} return render(request, 'process_payment.html', context)
In the payment view, we create a new Payment object and a Stripe PaymentIntent. We then redirect the user to the process_payment view, where the actual payment processing takes place using the Stripe JavaScript library.
Step 6: Create Payment Templates
Create two new templates, payment.html and process_payment.html, and add the following code:
<!-- payment.html -->{% extends 'base.html' %}{% block content %} <h2>Make a Payment</h2> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit" class="btn btn-primary">Pay</button> </form>{% endblock %}<!-- process_payment.html -->{% extends 'base.html' %}{% block content %}<h2>Processing Payment...</h2><p>Please wait while we process your payment.</p> {% load static %} <script src="https://js.stripe.com/v3/"></script> <script src="{% static 'js/payment.js' %}"></script> <script> processPayment('{{ client_secret }}'); </script>{% endblock %}
The process_payment template includes the Stripe JavaScript library and a custom JavaScript file called payment.js, which we will create in the next step.
Step 7: Add Payment JavaScript
Create a new file called payment.js in your app's static/js directory and add the following code:
// payment.jsasync function processPayment(clientSecret) { const stripe = Stripe('your_stripe_public_key'); const result = await stripe.confirmCardPayment(clientSecret, { payment_method: { card: await stripe.createToken('card', { number: '4242424242424242', exp_month: '12', exp_year: '2030', cvc: '123', }), }, }); if (result.error) { // Error handling console.error(result.error.message); } else { // Payment succeeded window.location.href = '/success/'; }}
Replace 'your_stripe_public_key' with your actual Stripe public key. This script processes the payment using the Stripe API and redirects the user to a success page if the payment is successful.
Step 8: Update URLs
Finally, add the new views to your app's urls.py file:
# urls.pyfrom django.urls import pathfrom . import viewsurlpatterns = [ # ... path('payment/', views.payment, name='payment'), path('process_payment/<str:client_secret>/', views.process_payment, name='process_payment'), # ...]
Conclusion
In this tutorial, we learned how to integrate a payment system in Django using Stripe. Integrating a payment system is crucial for e-commerce platforms, and Django makes it relatively easy with the help of third-party packages and customization. You can also hire remote Python developers to help with the integration process and customize it according to your needs.