To accept Paystack payments in DRF, create an APIView that receives email and amount via a serializer, initializes a transaction with the Paystack API, and returns the authorization URL as JSON. Your SPA or mobile frontend redirects to Paystack or opens the inline popup. A separate APIView verifies the payment.
Install DRF and requests if not already installed:
pip install djangorestframework requests python-decouple
Add 'rest_framework' to INSTALLED_APPS in settings.py. Configure your Paystack keys as shown in the Django guide.
# payments/serializers.py
from rest_framework import serializers
class InitializePaymentSerializer(serializers.Serializer):
email = serializers.EmailField()
amount = serializers.DecimalField(max_digits=10, decimal_places=2, min_value=1)
class VerifyPaymentSerializer(serializers.Serializer):
reference = serializers.CharField(max_length=100)
Get weekly developer tips
Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.
No spam. Unsubscribe anytime.
# payments/views.py
import uuid
import requests as http_requests
from django.conf import settings
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializers import InitializePaymentSerializer
from .models import Order
class InitializePaymentView(APIView):
def post(self, request):
serializer = InitializePaymentSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
email = serializer.validated_data['email']
amount = serializer.validated_data['amount']
reference = 'order_' + uuid.uuid4().hex[:12]
# Save order to database
order = Order.objects.create(
email=email,
amount=int(amount * 100),
reference=reference,
)
# Call Paystack
response = http_requests.post(
'https://api.paystack.co/transaction/initialize',
json={
'email': email,
'amount': order.amount,
'reference': reference,
'callback_url': request.build_absolute_uri('/api/payments/callback/'),
},
headers={
'Authorization': 'Bearer ' + settings.PAYSTACK_SECRET_KEY,
'Content-Type': 'application/json',
},
)
result = response.json()
if not result.get('status'):
return Response(
{'error': result.get('message', 'Initialization failed')},
status=status.HTTP_400_BAD_REQUEST,
)
return Response({
'authorization_url': result['data']['authorization_url'],
'access_code': result['data']['access_code'],
'reference': result['data']['reference'],
})
# payments/views.py (continued)
from django.utils import timezone
class VerifyPaymentView(APIView):
def get(self, request):
reference = request.query_params.get('reference')
if not reference:
return Response(
{'error': 'Missing reference'},
status=status.HTTP_400_BAD_REQUEST,
)
# Call Paystack verify
response = http_requests.get(
'https://api.paystack.co/transaction/verify/' + reference,
headers={
'Authorization': 'Bearer ' + settings.PAYSTACK_SECRET_KEY,
},
)
result = response.json()
if not result.get('status') or result['data']['status'] != 'success':
return Response(
{'error': 'Payment not successful'},
status=status.HTTP_400_BAD_REQUEST,
)
# Look up and validate order
try:
order = Order.objects.get(reference=reference)
except Order.DoesNotExist:
return Response(
{'error': 'Order not found'},
status=status.HTTP_404_NOT_FOUND,
)
if result['data']['amount'] != order.amount:
return Response(
{'error': 'Amount mismatch'},
status=status.HTTP_400_BAD_REQUEST,
)
# Idempotent fulfillment
updated = Order.objects.filter(
reference=reference, paid=False
).update(paid=True, paid_at=timezone.now())
return Response({
'success': True,
'already_fulfilled': updated == 0,
'amount': order.amount / 100,
'currency': order.currency,
})
# payments/urls.py
from django.urls import path
from .views import InitializePaymentView, VerifyPaymentView
urlpatterns = [
path('initialize/', InitializePaymentView.as_view(), name='initialize_payment'),
path('verify/', VerifyPaymentView.as_view(), name='verify_payment'),
]
# project/urls.py
from django.urls import path, include
urlpatterns = [
path('api/payments/', include('payments.urls')),
]
Your React, Vue, or mobile frontend calls the API:
// Frontend (React/Vue/etc.)
async function initializePayment(email, amount) {
var res = await fetch('/api/payments/initialize/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Token ' + authToken,
},
body: JSON.stringify({ email: email, amount: amount }),
});
var data = await res.json();
if (data.authorization_url) {
// Redirect checkout
window.location.href = data.authorization_url;
}
}
For inline popup, use the access_code with Paystack Inline.js. For redirect checkout, use the authorization_url.
KES 2,999
The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.
Start Paystack Course