SDK-SPEC-PYTHON — Python SDK Specification¶
Status: Draft
Owner: Platform Engineering
Package: simpaisa
Runtime: Python 3.11+
Last Updated: 2026-04-03
1. Overview¶
Official Python SDK for the Simpaisa Payment Gateway. Provides synchronous and asynchronous access to Pay-Ins, Pay-Outs, Remittances, and Cards across PK, BD, NP, and IQ corridors. Handles 270M+ annual transactions at $1B+ volume. Published to PyPI as simpaisa.
2. Package Structure¶
simpaisa/
├── simpaisa/
│ ├── __init__.py # Public API re-exports
│ ├── client.py # SimPaisaClient (sync) and AsyncSimPaisaClient
│ ├── config.py # Configuration dataclass
│ ├── payin/
│ │ ├── __init__.py
│ │ ├── client.py # PayIn operations (initiate, verify, status, list)
│ │ └── models.py # Pydantic models for pay-in
│ ├── payout/
│ │ ├── __init__.py
│ │ ├── client.py # PayOut operations (initiate, status, batch, cancel)
│ │ └── models.py
│ ├── remittance/
│ │ ├── __init__.py
│ │ ├── client.py # Remittance operations (quote, initiate, status, beneficiaries)
│ │ └── models.py
│ ├── cards/
│ │ ├── __init__.py
│ │ ├── client.py # Cards operations (pay, capture, void, refund, tokenise)
│ │ └── models.py
│ ├── webhooks/
│ │ ├── __init__.py
│ │ ├── verifier.py # WebhookVerifier (HMAC-SHA256)
│ │ └── models.py
│ ├── auth/
│ │ ├── __init__.py
│ │ └── rsa_provider.py # RSAAuthProvider — PEM loading, request signing
│ ├── errors.py # SimPaisaError hierarchy
│ ├── retry.py # RetryPolicy with exponential backoff
│ ├── idempotency.py # IdempotencyKeyGenerator (UUID v7)
│ └── _generated/
│ └── models.py # Auto-generated from OpenAPI via datamodel-code-generator
├── tests/
├── pyproject.toml
└── py.typed # PEP 561 marker
3. Exported Modules¶
Top-level simpaisa package SHALL export:
SimPaisaClient— synchronous client (uses httpx)AsyncSimPaisaClient— async client (uses httpx.AsyncClient)PayIn,PayOut,Remittance,Cards— product modulesWebhookVerifier— HMAC-SHA256 signature verificationRSAAuthProvider— RSA request signingIdempotencyKeyGenerator— UUID v7 key generationSimPaisaErrorand subclasses
4. Authentication — RSAAuthProvider¶
- Load merchant private key from PEM file path or string
- Sign request body with RSA-SHA256 using the
cryptographylibrary - Attach
X-Simpaisa-Signatureheader to each outbound request - Attach
X-Simpaisa-Merchant-Idheader - Support key rotation via list of key paths
from simpaisa.auth import RSAAuthProvider
auth = RSAAuthProvider(
merchant_id="MCH-001",
private_key_path="./keys/merchant.pem",
)
5. Async Support¶
AsyncSimPaisaClientprovides identical API surface usingasync/await- Built on
httpx.AsyncClientwith connection pooling - Context manager support:
async with AsyncSimPaisaClient(...) as client: - Synchronous client uses
httpx.Client(not asyncio wrapper)
async with AsyncSimPaisaClient(config=config) as client:
result = await client.payin.initiate(request)
6. WebhookVerifier¶
- Verify
X-Simpaisa-Webhook-Signatureusing HMAC-SHA256 (hmacstdlib) - Constructor accepts webhook secret
verify(payload: bytes, signature: str) -> bool- Replay protection: validate
X-Simpaisa-Webhook-Timestampwithin tolerance (default 300s) - Raise
WebhookVerificationErroron failure
7. RetryPolicy¶
- Exponential backoff with jitter (base 200ms, max 30s)
- Configurable max retries (default 3)
- Retry on: 429, 502, 503, 504, connection errors
- Never retry: 400, 401, 403, 404, 409, 422
- Respect
Retry-Afterheader on_retrycallback for observability
8. Error Handling¶
SimPaisaError (base)
├── AuthenticationError — 401/403 responses
├── ValidationError — 400/422 with field-level details
├── RateLimitError — 429 with retry_after
├── TimeoutError — request/connection timeout
├── IdempotencyError — conflicting idempotency key
├── NetworkError — connection/DNS failures
└── WebhookVerificationError — signature mismatch
All errors include: code, message, status_code, request_id, retryable.
9. Typed Models (Pydantic)¶
- All request and response models SHALL be Pydantic v2
BaseModelsubclasses - Auto-generated from canonical OpenAPI 3.1 spec via
datamodel-code-generator - Strict mode enabled: no coercion of incompatible types
- Custom validators for currency codes, MSISDN formats, corridor-specific rules
- Models placed in
_generated/models.py, re-exported with friendly names
10. Configuration¶
from simpaisa import SimPaisaClient, Config
client = SimPaisaClient(
config=Config(
environment="sandbox", # "sandbox" | "production"
merchant_id="MCH-001",
private_key_path="./keys/merchant.pem",
timeout=30.0, # seconds, default 30
retries=3, # default 3
logger=custom_logger, # optional, logging-compatible
)
)
11. Example Usage¶
from simpaisa import SimPaisaClient, Config
client = SimPaisaClient(config=Config(
environment="sandbox",
merchant_id="MCH-001",
private_key_path="./keys/merchant.pem",
))
# Pay-In
result = client.payin.initiate(
amount=5000,
currency="PKR",
channel="EASYPAISA",
customer_msisdn="03001234567",
callback_url="https://merchant.com/webhook",
)
# Pay-Out
payout = client.payout.initiate(
amount=10000,
currency="BDT",
beneficiary_account="1234567890",
beneficiary_bank="BRAC",
)
# Webhook verification
from simpaisa.webhooks import WebhookVerifier
verifier = WebhookVerifier(secret="whsec_...")
is_valid = verifier.verify(raw_body, signature_header)
12. Build and Publish¶
- Build system: Hatch (PEP 517/518)
- Test runner: pytest + pytest-asyncio
- Linting: Ruff (linting + formatting)
- Type checking: mypy (strict mode)
- CI: Bitbucket Pipelines — lint → typecheck → test → build → publish
- Publish: PyPI with trusted publisher (OIDC)
- Versioning: Semantic versioning;
__version__in__init__.py
13. Compatibility¶
- Python 3.11, 3.12, 3.13
- PEP 561 compliant (
py.typedmarker) - Dependencies:
httpx,cryptography,pydantic>=2.0 - No framework coupling (works with Django, Flask, FastAPI, or standalone)
14. Testing Requirements¶
- Unit tests for every public method (>90% coverage)
- Integration tests against sandbox environment
- Contract tests validating against OpenAPI spec
- Async and sync paths both tested
- Webhook verification round-trip tests
- Retry behaviour tests with simulated failures (respx for mocking)
15. Documentation¶
- Docstrings on all public classes and methods (Google style)
- Auto-generated reference via Sphinx + autodoc
- README with quickstart, authentication, and corridor-specific examples
- CHANGELOG following Keep a Changelog format
- Type stubs bundled (no separate stubs package)