Metadata-Version: 2.4
Name: daraja-sdk
Version: 0.1.0
Summary: Typed, async-first Python SDK for M-Pesa (Safaricom Daraja API)
License: MIT
Keywords: mpesa,daraja,safaricom,payments,kenya
Author: daraja-sdk contributors
Requires-Python: >=3.10
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Provides-Extra: all
Provides-Extra: django
Provides-Extra: fastapi
Requires-Dist: django (>=4.2) ; extra == "django" or extra == "all"
Requires-Dist: fastapi (>=0.110) ; extra == "fastapi" or extra == "all"
Requires-Dist: httpx[http2] (>=0.27)
Requires-Dist: pydantic (>=2.0) ; extra == "fastapi" or extra == "all"
Description-Content-Type: text/markdown

# daraja-sdk

A typed, async-first Python SDK for the M-Pesa Safaricom Daraja API.

## Installation

```bash
pip install daraja-sdk
```

With Django support:

```bash
pip install daraja-sdk[django]
```

With FastAPI support:

```bash
pip install daraja-sdk[fastapi]
```

## Quick start

```python
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)
```

## Django

Add to `INSTALLED_APPS` and configure in `settings.py`:

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

```python
from django.urls import include, path

urlpatterns = [
    path("mpesa/", include("daraja_sdk.urls", namespace="daraja_sdk")),
]
```

Listen for successful payments via the signal:

```python
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)
```

## FastAPI

```python
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"])
```

## License

MIT

