OTP Generation, Redis Storage, SMS Sending, and Verification with African Talking API in Django and DRF
Tags: redis, django, otp, api
Published: 2023-09-20 15:42:58

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:

```bash
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:

```bash
pip install redis africastalking djangorestframework
```

**3. Configure Django Settings:**
Add the following configurations to your project's settings:

```python
# 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:

```python
# 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`:

```python
# 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:

```bash
python manage.py migrate
```

**7. Run the Development Server:**
Start the Django development server:

```bash
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:
```bash
curl -X POST http://localhost:8000/send-otp/ -d "phone_number=RECIPIENT_PHONE_NUMBER"
```

Verifying OTP:
```bash
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.