Reusable Django payment infrastructure with idempotency and webhook support
Project description
payment_infra
A reusable Django package for payment orchestration with clean architecture, idempotency, provider abstraction, and webhook handling.
Features
- Provider abstraction (
paystack,stripe,monnify) through a shared interface. - Idempotent payment initialization flow to avoid duplicate charges.
- Service-layer orchestration (
PaymentService,WebhookService) for testable business logic. - Django REST API endpoints for charge, verify, and webhook processing.
- Extensible architecture for adding new providers without changing API/service boundaries.
Package Architecture
payment_infra/
├── api/ # DRF serializers, views, and URL routes
├── application/ # Use-cases/services + provider/repository interfaces
├── domain/ # Core entities and domain models
├── infrastructure/
│ ├── idempotency/ # Idempotency persistence and locking
│ ├── providers/ # Gateway adapters (Paystack/Stripe/Monnify)
│ ├── repositories/ # Data access adapters
│ └── tasks/ # Async task hooks (Celery)
└── migrations/ # Django migrations
Installation
From package index
pip install payment_infra
For local development
git clone https://github.com/0FFSIDE1/payment_infra.git
cd payment_infra
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Quick Start in a Django Project
1) Add apps
INSTALLED_APPS = [
# ...
"rest_framework",
"payment_infra",
]
2) Include URLs
from django.urls import include, path
urlpatterns = [
# ...
path("payments/", include("payment_infra.api.urls")),
]
3) Configure provider settings
Set DJANGO_PAYMENTS_PROVIDER to one of:
paystackstripemonnify
Provider-specific settings:
Paystack
PAYSTACK_SECRET_KEYPAYSTACK_PUBLIC_KEYPAYSTACK_BASE_URL(optional)PAYSTACK_CALLBACK_URL
Stripe
STRIPE_SECRET_KEYSTRIPE_PUBLIC_KEYSTRIPE_BASE_URL(optional, defaults tohttps://api.stripe.com/v1)STRIPE_WEBHOOK_SECRET
Monnify
MONNIFY_API_KEYMONNIFY_SECRET_KEYMONNIFY_CONTRACT_CODEMONNIFY_PUBLIC_KEY(optional)MONNIFY_BASE_URL(optional)
Common runtime settings:
DJANGO_SECRET_KEYREDIS_URLCACHE_BACKEND
4) Run migrations
python manage.py migrate
API Usage
With URLs mounted at /payments/:
POST /payments/charge/GET /payments/verify/<reference>/POST /payments/webhooks/
Example: initialize charge
curl -X POST http://localhost:8000/payments/charge/ \
-H "Content-Type: application/json" \
-d '{
"email": "customer@example.com",
"amount": "1000.00",
"currency": "NGN",
"idempotency_key": "trx-20260411103000-abc123",
"callback_url": "https://example.com/payment/callback"
}'
Example: verify payment
curl -X GET "http://localhost:8000/payments/verify/<reference>/"
Programmatic Usage
from decimal import Decimal
from payment_infra.infrastructure.providers.registry import get_payment_service
service = get_payment_service()
result = service.process_payment(
email="customer@example.com",
amount=Decimal("1000.00"),
currency="NGN",
idempotency_key="trx-20260411103000-abc123",
metadata={"callback_url": "https://example.com/payment/callback"},
)
Testing
Run all tests:
pytest
Run only non-integration tests:
pytest -m "not integration"
Security Notes
- Always use HTTPS callback/webhook URLs in production.
- Keep provider secret keys in environment variables (never commit them).
- Verify webhook signatures before processing events.
- Use unique idempotency keys per client request to prevent duplicate processing.
Contributing
- Create a feature branch.
- Add/modify tests for changes.
- Run
pytestlocally. - Open a pull request.
License
MIT — see LICENSE.
Project details
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 payment_infra-1.0.6.tar.gz.
File metadata
- Download URL: payment_infra-1.0.6.tar.gz
- Upload date:
- Size: 20.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5573b30bbcaa035a51b9160cb680facc07b265888f0d5feaf2bf5c438ba0fad4
|
|
| MD5 |
36eb3f73bc91e706c726297beca18887
|
|
| BLAKE2b-256 |
5aa95b5f051f29f0ab837b72ed0071a840f426d3cfbab8a4d8843b619639493f
|
Provenance
The following attestation bundles were made for payment_infra-1.0.6.tar.gz:
Publisher:
cd.yml on 0FFSIDE1/payment_infra
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
payment_infra-1.0.6.tar.gz -
Subject digest:
5573b30bbcaa035a51b9160cb680facc07b265888f0d5feaf2bf5c438ba0fad4 - Sigstore transparency entry: 1279545702
- Sigstore integration time:
-
Permalink:
0FFSIDE1/payment_infra@b0460e7c1086a89a8e7ee33722563744c4db0ae4 -
Branch / Tag:
refs/tags/v1.0.6 - Owner: https://github.com/0FFSIDE1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cd.yml@b0460e7c1086a89a8e7ee33722563744c4db0ae4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file payment_infra-1.0.6-py3-none-any.whl.
File metadata
- Download URL: payment_infra-1.0.6-py3-none-any.whl
- Upload date:
- Size: 28.7 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 |
c155f34ae5c9850e20576c5fea4cf183c4c37232029e603bea5d177581e0a8a6
|
|
| MD5 |
e92ab76da4b172874ccc4e2e9b54bd58
|
|
| BLAKE2b-256 |
e1ff4ffd15cdcd4958020ddc801ceaad634154e53bef56b7faf36c169ada18d4
|
Provenance
The following attestation bundles were made for payment_infra-1.0.6-py3-none-any.whl:
Publisher:
cd.yml on 0FFSIDE1/payment_infra
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
payment_infra-1.0.6-py3-none-any.whl -
Subject digest:
c155f34ae5c9850e20576c5fea4cf183c4c37232029e603bea5d177581e0a8a6 - Sigstore transparency entry: 1279545734
- Sigstore integration time:
-
Permalink:
0FFSIDE1/payment_infra@b0460e7c1086a89a8e7ee33722563744c4db0ae4 -
Branch / Tag:
refs/tags/v1.0.6 - Owner: https://github.com/0FFSIDE1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
cd.yml@b0460e7c1086a89a8e7ee33722563744c4db0ae4 -
Trigger Event:
push
-
Statement type: