A typed, async-first Python SDK for the M-Pesa Safaricom Daraja API.
pip install daraja-sdkWith Django support:
pip install daraja-sdk[django]With FastAPI support:
pip install daraja-sdk[fastapi]from daraja_sdk import MpesaClient
async with MpesaClient(
consumer_key="...",
consumer_secret="...",
shortcode="174379",
passkey="...",
callback_url="https://yourdomain.com/mpesa/stk/callback/",
environment="sandbox",
) as client:
result = await client.stk_push(phone="0712345678", amount=100)
print(result)Add to INSTALLED_APPS and configure in settings.py:
INSTALLED_APPS = [
...
"daraja_sdk",
]
MPESA_CONSUMER_KEY = "..."
MPESA_CONSUMER_SECRET = "..."
MPESA_SHORTCODE = "174379"
MPESA_PASSKEY = "..."
MPESA_CALLBACK_URL = "https://yourdomain.com/mpesa/stk/callback/"
MPESA_ENV = "sandbox"Include the SDK URLs:
from django.urls import include, path
urlpatterns = [
path("mpesa/", include("daraja_sdk.urls", namespace="daraja_sdk")),
]Listen for successful payments via the signal:
from django.dispatch import receiver
from daraja_sdk.signals import payment_received
@receiver(payment_received)
def on_payment(sender, callback, **kwargs):
print(callback.phone, callback.amount, callback.mpesa_receipt_number)from contextlib import asynccontextmanager
from fastapi import FastAPI
import daraja_sdk.fastapi as daraja_fastapi
from daraja_sdk import MpesaClient
from daraja_sdk.fastapi import router
@asynccontextmanager
async def lifespan(app):
daraja_fastapi.set_client(MpesaClient(...))
yield
app = FastAPI(lifespan=lifespan, redirect_slashes=False)
app.include_router(router)
@daraja_fastapi.on_payment_received
async def handle_payment(data: dict) -> None:
print(data["phone"], data["amount"], data["receipt"])MIT