Overview
CrediBill is a production-grade billing infrastructure for SaaS applications using African payment providers. It handles subscription billing, payment orchestration, and real-time webhook delivery while maintaining multi-tenant isolation and security.Key Capabilities
- Multi-Tenant Architecture: Each SaaS app maintains isolated payment provider credentials
- 4 African Payment Providers: Flutterwave, PawaPay, Pesapal, DPO
- Automated Billing Cycles: Cron-based trial expirations, recurring payments, and retries
- Production-Grade Security: HMAC signature verification, replay attack prevention, encrypted credentials
- Real-Time Webhooks: Bi-directional webhook delivery with retry logic
- Comprehensive Logging: Full audit trail of all payment events
Architecture
Multi-Tenant Design
- Configures their own payment provider credentials
- Maintains encrypted credential storage
- Receives isolated webhook events
- Has payment transactions flow directly to their provider account
Payment Lifecycle
1. Trial to Paid Conversion
Trigger: Customer’s trial period expires Flow:convex/cronHandlers.ts:processTrialExpirations()convex/payments.ts:initiateSubscriptionPayment()convex/paymentsNode.ts: Provider-specific adapters
2. Recurring Payments
Trigger: Subscription renewal date reached Flow:convex/cronHandlers.ts:processRecurringPayments()convex/payments.ts:processRecurringPayment()
3. Payment Confirmation (Webhook)
Trigger: Payment provider sends webhook confirmation Flow:convex/http.ts: Webhook route handlersconvex/webhookActions.ts: Event handlersconvex/webhookQueries.ts: Transaction lookupsconvex/webhookMutations.ts: Status updatesconvex/outgoingWebhooks.ts: SaaS app notifications
4. Failed Payment Handling
Trigger: Payment fails or webhook indicates failure Flow:convex/cronHandlers.ts:retryFailedPayments()convex/webhookMutations.ts:updateTransactionFromWebhook()
Database Schema
Payment Providers
Payment Transactions
Webhook Logs (Incoming)
Outgoing Webhooks
Security Features
Webhook Signature Verification
All incoming webhooks must be verified using HMAC-SHA256:- Timing-safe comparison: Prevents attackers from determining signature validity through response timing
- Timestamp validation: Reject webhooks older than 5 minutes (prevent replay attacks)
- Signature verification: Ensures webhook originated from provider, not attacker
Credential Encryption
All stored provider credentials use AES-256-GCM encryption:- Per-app encryption: Each app has isolated encryption keys
- AES-256-GCM: Authenticated encryption prevents tampering
- No central key storage: Master key in environment variables
Race Condition Protection
Critical updates use atomic transactions:Cron Jobs Schedule
Next Steps
- Payment Providers - Configure each provider
- Webhooks - Handle incoming webhooks
- Integration Guide - Integrate CrediBill
- Security Best Practices - Production security