A production-hardened Django app for Safaricom's Daraja M-PESA API
Project description
mainfinity-django-mpesa
A production-hardened Django app for Safaricom's Daraja M-PESA API.
Extracted from production use in Zaruni and packaged for reuse across any Django project that needs to collect or send money via M-PESA.
Features
- STK Push — trigger the M-PESA PIN prompt on a customer's phone
- C2B — receive paybill/till payments with validation and confirmation callbacks
- B2C — send payouts, salaries, or refunds to phone numbers
- Transaction Status — query stuck payments for reconciliation
- Account Balance — check your M-PESA business account balance
- Reversal — reverse a transaction programmatically
- Idempotent callbacks — Safaricom retries are handled safely; a payment is settled exactly once
- IP allowlist middleware — rejects callbacks from non-Safaricom sources
- Mock client — full test suite runs with zero network access; ships a
MockDarajaClientfor your own tests - Swappable models — subclass the abstract models and add your own fields (orders, users, wallets)
- Django signals — hook into
payment_confirmed,payout_completed, etc. without modifying library code
Requirements
- Python 3.10, 3.11, or 3.12
- Django 4.2 or 5.1
- djangorestframework ≥ 3.14
- requests ≥ 2.31
- Celery ≥ 5.3 (optional — set
USE_CELERY=Falsefor synchronous processing)
Installation
pip install mainfinity-django-mpesa
# With Celery support:
pip install mainfinity-django-mpesa[celery]
Quick start
See the full quickstart guide to go from install to a working STK Push in under 10 minutes.
# 1. Add to INSTALLED_APPS
INSTALLED_APPS = [
...
"django_mpesa",
]
# 2. Configure
MPESA = {
"ENV": "sandbox",
"CONSUMER_KEY": lambda: os.environ["MPESA_CONSUMER_KEY"],
"CONSUMER_SECRET": lambda: os.environ["MPESA_CONSUMER_SECRET"],
"SHORTCODE": "174379",
"PASSKEY": lambda: os.environ["MPESA_PASSKEY"],
"STK_CALLBACK_URL": "https://yourapp.com/mpesa/stk/callback/",
"TRANSACTION_MODEL": "myapp.MpesaTransaction",
"CALLBACK_LOG_MODEL": "myapp.MpesaCallbackLog",
}
# 3. Include URLs
urlpatterns = [
path("mpesa/", include("django_mpesa.urls")),
]
# 4. Initiate a payment
from django_mpesa.services import STKPushService
txn = STKPushService().initiate(
phone_number="254712345678",
amount=100,
account_reference="INV-001",
transaction_desc="Payment",
)
# 5. React to the callback
from django.dispatch import receiver
from django_mpesa.signals import payment_confirmed
@receiver(payment_confirmed)
def on_payment(sender, transaction, **kwargs):
order = transaction.order
order.mark_paid()
Documentation
Full documentation at mainfinity-django-mpesa.readthedocs.io.
Contributing
See CONTRIBUTING.md. All PRs touching tasks.py must include or update the idempotency concurrency test.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mainfinity_django_mpesa-0.1.1.tar.gz.
File metadata
- Download URL: mainfinity_django_mpesa-0.1.1.tar.gz
- Upload date:
- Size: 32.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca53ea5055f16ff8ae0839768f37ce4644ae77901aba09ba4cbef8bbc3f7c298
|
|
| MD5 |
69cdd38658e7e26569141baef11f87fd
|
|
| BLAKE2b-256 |
14675d7c7b46045d6f6dec9a6c7d734d8b38fd2a789a5949deca6c0afffcf7f3
|
Provenance
The following attestation bundles were made for mainfinity_django_mpesa-0.1.1.tar.gz:
Publisher:
publish.yml on Wachiradanito/django-mpesa
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mainfinity_django_mpesa-0.1.1.tar.gz -
Subject digest:
ca53ea5055f16ff8ae0839768f37ce4644ae77901aba09ba4cbef8bbc3f7c298 - Sigstore transparency entry: 2048324692
- Sigstore integration time:
-
Permalink:
Wachiradanito/django-mpesa@1a070d745efd581f4e0f0e7fe674fa56ba88144c -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Wachiradanito
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1a070d745efd581f4e0f0e7fe674fa56ba88144c -
Trigger Event:
push
-
Statement type:
File details
Details for the file mainfinity_django_mpesa-0.1.1-py3-none-any.whl.
File metadata
- Download URL: mainfinity_django_mpesa-0.1.1-py3-none-any.whl
- Upload date:
- Size: 44.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
89d5b8ab0fa4124335f6b1c4b5eec45afa50429fcb1127d10cf3b24b3c712e12
|
|
| MD5 |
69c24d48ba4a5bff16e6e18014c4132e
|
|
| BLAKE2b-256 |
bf3831b68d24cf2cf77cd050a7b930aa1f13429e44d324d12b4bbe4cfd788952
|
Provenance
The following attestation bundles were made for mainfinity_django_mpesa-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on Wachiradanito/django-mpesa
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mainfinity_django_mpesa-0.1.1-py3-none-any.whl -
Subject digest:
89d5b8ab0fa4124335f6b1c4b5eec45afa50429fcb1127d10cf3b24b3c712e12 - Sigstore transparency entry: 2048324702
- Sigstore integration time:
-
Permalink:
Wachiradanito/django-mpesa@1a070d745efd581f4e0f0e7fe674fa56ba88144c -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Wachiradanito
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1a070d745efd581f4e0f0e7fe674fa56ba88144c -
Trigger Event:
push
-
Statement type: