To demonstrate M-Pesa integration in a Django project for selling a product, we will create a simple e-commerce application where users can purchase a product using M-Pesa. Here's a step-by-step guide:
-
Setup Django Project:
First, create a Django project and an app within it. Let's name the project
test_mpesa
and the appproduct
.
django-admin startproject test_mpesa
cd test_mpesa
python manage.py startapp product
-
Define Models:
In the
shop
app, define models for the product and transactions.
# shop/models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
quantity = models.PositiveIntegerField()
def __str__(self):
return self.name
class Transaction(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
phone_number = models.CharField(max_length=15)
amount = models.DecimalField(max_digits=10, decimal_places=2)
checkout_request_id = models.CharField(max_length=100)
status = models.CharField(max_length=20, default='PENDING')
transaction_code = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return f"Transaction for {self.product.name}"
- URLs Configuration: Configure URLs to handle views.
# ecommerce_project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('product.urls')),
]
- Views for Subscription and Callback: Implement views for subscribing to a product and handling M-Pesa callback.
# shop/views.py
from django.shortcuts import render, redirect, reverse, get_object_or_404
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from .models import Product, Transaction
from django_daraja.mpesa.core import MpesaClient
import json
def subscribe(request, product_id):
product = get_object_or_404(Product, pk=product_id)
if request.method == 'POST':
phone_number = request.POST.get('phone_number')
amount = product.price
account_reference = 'Product Payment'
transaction_desc = f'Purchase of {product.name}'
callback_url = request.build_absolute_uri(reverse('mpesa_callback')).replace('http://', 'https://')
mpesa_client = MpesaClient()
try:
response = mpesa_client.stk_push(
phone_number=phone_number,
amount=amount,
account_reference=account_reference,
transaction_desc=transaction_desc,
callback_url=callback_url
)
transaction = Transaction.objects.create(
product=product,
phone_number=phone_number,
amount=amount,
checkout_request_id=response.checkout_request_id,
)
return render(request, 'shop/subscribe_success.html', {'transaction': transaction})
except Exception as e:
return render(request, 'shop/subscribe.html', {'error': str(e)})
return render(request, 'shop/subscribe.html', {'product': product})
@csrf_exempt
def mpesa_callback(request):
if request.method == 'POST':
data = json.loads(request.body.decode('utf-8'))
stk_callback = data.get('Body', {}).get('stkCallback', {})
checkout_request_id = stk_callback.get('CheckoutRequestID')
result_code = stk_callback.get('ResultCode')
transaction = Transaction.objects.get(checkout_request_id=checkout_request_id)
if result_code == 0:
transaction.status = 'COMPLETED'
transaction.transaction_code = stk_callback.get('CallbackMetadata')['Item'][1]['Value']
else:
transaction.status = 'FAILED'
transaction.save()
return HttpResponse('Success', content_type='text/plain')
else:
return HttpResponse('Method Not Allowed', status=405)
Templates:
Create HTML templates for subscription and success pages.URLs Configuration:
Configure URLs to map views.
# shop/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('subscribe/<int:product_id>/', views.subscribe, name='subscribe'),
path('mpesa/callback/', views.mpesa_callback, name='mpesa_callback'),
]
-
Integrate with M-Pesa:
Finally, integrate with M-Pesa by installing the required package (
django-daraja
).
pip install django-daraja
Top comments (1)
Any link to the git repo.?