Integrating Paystack payments in Django
Django and Paystack Integrating
Table of contents
Introduction
Paystack is a payment gateway that helps individuals and businesses in Africa accept payments from anywhere in the world. In this guide, I will show you how to use Paystack as a third-party API to handle payments on your Django website.
Prerequisites
To follow this guide, you need:
A good understanding of Python
Basic knowledge of Django
Basic knowledge of HTML
Familiarity with the Python requests library
A Paystack account
Project Setup
CCreate a folder, start a virtual environment, and set up the basic project
Create a virtual environment using python -m venv env
on Windows. Use virtualenv env
on Mac/Linux.
Activate the virtual environment with .\env\Scripts\activate
on Windows or source env/bin/activate
on Mac/Linux.
Install Django using pip install django
. This will install the latest version of Django, but you can use any version you prefer. It's best to use the latest version for all your projects.
Create a project and install apps
Start the project with django-admin startproject core .
core is the project name, and the dot means the project starts in the current folder.
The next step is to create two apps: one for user authentication and another for handling all payment-related code.
python manage.py startapp users
python manage.py startapp payments
Add the newly installed apps in settings.py
Also add paystack secret and public keys in settings.py
Where to find them on paystack
Navigate into both Apps folders created and add a new file called urls.py
and add the following code
from django.urls import path
urlpatterns = [
]
Include these urls in main url file core.urls
Your file should look like this
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('users/', include("users.urls")),
path('payments/', include("payments.urls")),
]
Creating models
Next step is to create a wallet model to keep track of funds deposited by a user and a payment model to describe what a payment is.
In payments.model
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
import secrets
from .paystack import Paystack
# Create your models here.
class UserWallet(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
created_at = models.DateTimeField(default=timezone.now, null=True)
def __str__(self):
return self.user.__str__()
class Payment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
amount = models.PositiveIntegerField()
ref = models.CharField(max_length=200)
email = models.EmailField()
verified = models.BooleanField(default=False)
date_created = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('-date_created',)
def __str__(self):
return f"Payment for {user}: {self.amount}"
def save(self, *args, **kwargs):
while not self.ref:
ref = secrets.token_urlsafe(50)
object_with_similar_ref = Payment.objects.filter(ref=ref)
if not object_with_similar_ref:
self.ref = ref
super().save(*args, **kwargs)
We will need another helper class to handle payment verification, so in the payments folder create a file called paystack.py
paste this block of code in the file
from django.conf import settings
import requests
class Paystack:
PAYSTACK_SK = settings.PAYSTACK_SECRET_KEY
base_url = "https://api.paystack.co/"
def verify_payment(self, ref, *args, **kwargs):
path = f'transaction/verify/{ref}'
headers = {
"Authorization": f"Bearer {self.PAYSTACK_SK}",
"Content-Type": "application/json",
}
url = self.base_url + path
response = requests.get(url, headers=headers)
if response.status_code == 200:
response_data = response.json()
return response_data['status'], response_data['data']
response_data = response.json()
return response_data['status'], response_data['message']
you will need to install requests for this so do a quick pip install requests
with that we can now add a verify payment property on our payment model
def amount_value(self):
return int(self.amount) * 100
def verify_payment(self):
paystack = Paystack()
status, result = paystack.verify_payment(self.ref, self.amount)
if status:
if result['amount'] / 100 == self.amount:
self.verified = True
self.save()
if self.verified:
return True
return False
Your model should look like this:
from django.db import models
# Create your models here.
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
import secrets
from .paystack import Paystack
# Create your models here.
class UserWallet(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
currency = models.CharField(max_length=50, default='NGN')
created_at = models.DateTimeField(default=timezone.now, null=True)
def __str__(self):
return self.user.__str__()
class Payment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
amount = models.PositiveIntegerField()
ref = models.CharField(max_length=200)
email = models.EmailField()
verified = models.BooleanField(default=False)
date_created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-date_created',)
def __str__(self):
return f"Payment: {self.amount}"
def save(self, *args, **kwargs):
while not self.ref:
ref = secrets.token_urlsafe(50)
object_with_similar_ref = Payment.objects.filter(ref=ref)
if not object_with_similar_ref:
self.ref = ref
super().save(*args, **kwargs)
def amount_value(self):
return int(self.amount) * 100
def verify_payment(self):
paystack = Paystack()
status, result = paystack.verify_payment(self.ref, self.amount)
if status:
if result['amount'] / 100 == self.amount:
self.verified = True
self.save()
if self.verified:
return True
return False
To be continued.