Production-grade payment backbone enabling green ventures to scale across African markets. Bank-grade security controls, comprehensive audit trails, and regulatory compliance meeting institutional investor requirements โ facilitating $2M+ in transaction value for sustainable investments.
Investment-Grade Security
The Problem
The Safaricom Daraja API documentation is extensive but the real-world implementation has numerous edge cases: token expiry during peak load, callback URL validation quirks, phone number format inconsistencies, sandbox vs. production behavioral differences, and the need for idempotent transaction handling.
Many Kenyan startups ship insecure M-Pesa integrations with hardcoded credentials, no rate limiting, and no callback verification โ creating vulnerability surfaces that put user financial data at risk.
The Solution
This gateway abstracts the complexity of Daraja API into a clean, documented REST API. OAuth 2.0 tokens are managed with automatic refresh (maintaining a 5-minute buffer before expiry). STK Push requests are initiated with comprehensive phone number normalization supporting all Kenyan formats.
Transaction results are cached with 1-hour TTL for idempotent retries. Callbacks are verified against Safaricom's IP ranges. Every sensitive parameter is masked in logs. The entire system switches between sandbox and production with a single environment variable.
Architecture
React frontend sends payment initiation request with amount, phone number, and transaction reference. CORS and rate limiting applied immediately.
OAuth 2.0 bearer token checked against cache. If expired or within 5-minute buffer, auto-refresh from Daraja API before proceeding.
Phone number normalized (07XX, 01XX, +254XX, 254XX all handled). STK Push request sent to Safaricom. Transaction ID logged and cached.
Safaricom POSTs result to callback URL. IP verified against allowlist. Transaction status updated. Client notified via polling or WebSocket.
Features
Tech Stack
Express.js 5 with middleware chain: CORS โ Rate Limit โ Helmet โ Auth โ Route handlers. Clean separation of concerns.
React + Vite checkout interface with real-time payment status polling and user-friendly error messaging.
Safaricom Daraja API with STK Push, OAuth 2.0, callback processing, and B2C disbursement endpoints.
Multi-layered security: HTTP headers, rate limiting, CORS, IP allowlisting, input sanitization, and credential masking.
Challenges & Learnings
Daraja sandbox behavior diverges from production in subtle ways โ different response codes, timing, and callback formats. Required building a comprehensive test harness with mock responses.
Under high concurrency, multiple requests could trigger simultaneous token refreshes. Implemented a mutex-based token manager ensuring exactly one refresh at a time with queued waiters.
Kenyan phone numbers arrive in 7+ formats. Building a normalizer that handles every variation (including copy-paste artifacts with spaces and hyphens) required extensive field testing.