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
| Job | Frequency | Time (UTC) | Purpose |
|---|---|---|---|
| Trial Expirations | Daily | 2:00 AM | Convert expired trials to paid |
| Recurring Payments | Daily | 3:00 AM | Process subscription renewals |
| Failed Payment Retries | Daily | 4:00 AM | Retry failed transactions |
| Cleanup Expired | Daily | 5:00 AM | Mark old pending as failed |
| Webhook Retries | Every 5 min | - | Retry failed outgoing webhooks |
Next Steps
- Payment Providers - Configure each provider
- Webhooks - Handle incoming webhooks
- Integration Guide - Integrate CrediBill
- Security Best Practices - Production security