To implement OTP generation, storage in Redis, sending an SMS, and OTP verification using the African Talking API in a Django Rest Framework (DRF) application, follow these steps:
1. Create a Django Project and App:
If you haven't already, create a Django project and a DRF app:
django-admin startproject project_name
cd project_name
python manage.py startapp otp_api
2. Install Required Packages:
Install the necessary packages for Redis, the African Talking API, and Django Rest Framework:
pip install redis africastalking djangorestframework
3. Configure Django Settings:
Add the following configurations to your project's settings:
# project_name/settings.py
INSTALLED_APPS = [
# ...
'rest_framework',
'otp_api',
]
# Redis configuration
REDIS_HOST = 'localhost' # Replace with your Redis server host
REDIS_PORT = 6379 # Replace with your Redis server port
REDIS_DB = 0 # Replace with your Redis database number
# African Talking API configuration
AFRICASTALKING_API_USERNAME = 'YOUR_API_USERNAME'
AFRICASTALKING_API_KEY = 'YOUR_API_KEY'
4. Create OTP Generation and SMS Sending Logic:
Inside your otp_api app, create views and serializers for OTP generation, SMS sending, and OTP verification.
Here's an example of what these views might look like:
# otp_api/views.py
import random
import redis
from django.conf import settings
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.serializers import Serializer, CharField
from africastalking.Africastalking import initialize
from africastalking.SMS import send
# Initialize Redis client
redis_client = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DB)
# Initialize African Talking API
initialize(settings.AFRICASTALKING_API_USERNAME, settings.AFRICASTALKING_API_KEY)
class GenerateOTPSerializer(Serializer):
phone_number = CharField()
class VerifyOTPSerializer(Serializer):
phone_number = CharField()
otp = CharField()
class SendOTP(APIView):
def post(self, request):
serializer = GenerateOTPSerializer(data=request.data)
if serializer.is_valid():
phone_number = serializer.validated_data['phone_number']
otp = str(random.randint(1000, 9999))
redis_client.setex(phone_number, 300, otp)
# Send OTP via SMS
message = f'Your OTP is: {otp}'
recipients = [phone_number]
try:
send(message, recipients)
return Response({'message': 'OTP sent successfully.'}, status=status.HTTP_200_OK)
except Exception as e:
return Response({'error': f'Failed to send OTP: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class VerifyOTP(APIView):
def post(self, request):
serializer = VerifyOTPSerializer(data=request.data)
if serializer.is_valid():
phone_number = serializer.validated_data['phone_number']
otp = serializer.validated_data['otp']
# Check if OTP exists in Redis
stored_otp = redis_client.get(phone_number)
if stored_otp and stored_otp.decode('utf-8') == otp:
# OTP is valid
return Response({'message': 'OTP verified successfully.'}, status=status.HTTP_200_OK)
else:
# OTP is invalid
return Response({'error': 'Invalid OTP.'}, status=status.HTTP_400_BAD_REQUEST)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
5. Configure URLs:
Add URL patterns for the views in your app's urls.py:
# otp_api/urls.py
from django.urls import path
from .views import SendOTP, VerifyOTP
urlpatterns = [
path('send-otp/', SendOTP.as_view(), name='send-otp'),
path('verify-otp/', VerifyOTP.as_view(), name='verify-otp'),
]
6. Run Migrations:
Apply migrations to create the necessary database tables for DRF:
python manage.py migrate
7. Run the Development Server:
Start the Django development server:
python manage.py runserver
8. Testing:
You can now send POST requests to /send-otp/ to generate and send an OTP via SMS and /verify-otp/ to verify the OTP. Make sure to replace http://localhost:8000/ with your actual server URL.
Here's an example of how to test the endpoints using curl:
Sending OTP:
curl -X POST http://localhost:8000/send-otp/ -d "phone_number=RECIPIENT_PHONE_NUMBER"
Verifying OTP:
curl -X POST http://localhost:8000/verify-otp/ -d "phone_number=RECIPIENT_PHONE_NUMBER" -d "otp=1234"
Replace RECIPIENT_PHONE_NUMBER with the recipient's phone number and adjust the endpoints according to your project's URL configuration.
Remember to handle exceptions and errors more robustly in a production environment and implement proper authentication and validation for your API endpoints.
Top comments (2)
This is a really clean implementation, especially the Redis expiration part. One thing I ran into building OTP systems is that delivery itself isn’t always the main issue, timing is. Even if everything is correct on the backend, the SMS layer can still break the flow. I’ve seen cases where one OTP arrives almost instantly and another takes much longer, while both are technically “delivered”. At that point the system looks fine, but the user still fails verification because the code arrives too late. Curious if you’ve seen any timing inconsistencies in practice, especially across different regions or under load?
I recommand using OTPShield API on RapidAPI