Payment Provider Integration Guide¶
This guide walks you through integrating a payment provider with Sawabona.
Choosing a Payment Provider¶
Sawabona supports 7 payment providers. Choose based on your region and requirements:
| Provider | Best For | Regions | Currencies |
|---|---|---|---|
| Stripe | Global, high volume | Worldwide | 135+ |
| Adyen | Enterprise, multi-currency | Worldwide | 250+ |
| Flutterwave | African markets | Africa | 30+ |
| PayStack | African startups | Africa | 10+ |
| MercadoPago | Latin America | LATAM | 20+ |
| PagSeguro | Brazil focus | Brazil | BRL, USD |
| Braintree | PayPal integration | Worldwide | 130+ |
Step 1: Create Provider Account¶
Stripe¶
- Go to https://dashboard.stripe.com
- Sign up or log in
- Navigate to Developers → API Keys
- Copy your Secret Key (starts with
sk_test_orsk_live_) - Copy your Webhook Signing Secret (starts with
whsec_)
Paddle¶
- Create a free self-serve sandbox account at https://sandbox-login.paddle.com/signup
- Generate an API key (Developer Tools → Authentication)
- Create a Notification destination (Developer Tools → Notifications) pointing at
https://your-domain.com/api/v1/webhooks/paddleand copy its secret (pdl_ntfset_…)
Other Providers¶
Follow similar steps for Flutterwave and PayStack. Each provider's dashboard has an API credentials section.
Step 2: Configure Environment Variables¶
Create a .env file in your Sawabona directory:
# Database
SAWABONA_DATABASE__URL=postgresql://user:password@localhost/sawabona
# Encryption key for API secrets (32 bytes, standard or URL-safe base64)
SAWABONA_ENCRYPTION_KEY=<base64-encoded-32-byte-key>
# Stripe (auto-seeded into DB on startup)
SAWABONA_STRIPE_SECRET_KEY=sk_test_your_key_here
SAWABONA_STRIPE_WEBHOOK_SECRET=whsec_your_secret_here
# Other providers (Paddle, Flutterwave, PayStack) are configured via the
# admin API (PUT /api/v1/admin/payments/providers/{provider}) once enabled.
Optional: override the provider API base URL¶
Each provider crate ships with the canonical production URL as a compiled-in
default (e.g. https://api.stripe.com). You can override it per deployment
without code changes — useful for staging gateways, regional endpoints, or a
mock server in CI:
SAWABONA_PAYMENT__STRIPE__BASE_URL=https://api-staging.example.com
SAWABONA_PAYMENT__PAYSTACK__BASE_URL=...
SAWABONA_PAYMENT__FLUTTERWAVE__BASE_URL=...
SAWABONA_PAYMENT__PADDLE__BASE_URL=https://sandbox-api.paddle.com
When unset (or empty), the provider falls back to its production default URL.
Step 3: Register Payment Provider¶
Default Build: Stripe Only¶
Only the StripeProviderFactory is registered at server startup in sawabona-api/src/lib.rs. If SAWABONA_STRIPE_SECRET_KEY is set and stripe_config is empty, the API encrypts and seeds the config into the database automatically.
Registering Additional Providers¶
Providers are opt-in via cargo features. Build sawabona-api with the providers
you run — e.g. --features stripe,paddle or --features all-providers — and set
SAWABONA_PAYMENT_PROVIDERS (comma-separated, e.g. stripe,paddle) to register
them at startup. A name in the env var that isn't compiled in is rejected with a
clear error (no silent skip).
Each provider factory crate lives in sawabona-payments/ (payment-paddle,
payment-flutterwave, payment-paystack). Configure each
enabled provider's credentials via the admin API
(PUT /api/v1/admin/payments/providers/{provider}).
Stripe Product Mapping¶
To link Stripe prices to Sawabona products (required for automatic license creation from webhooks):
INSERT INTO stripe_product_mappings (id, product_id, stripe_price_id, created_at)
VALUES (gen_random_uuid(), '<sawabona-product-uuid>', 'price_xxx', NOW());
Step 4: Configure Webhooks¶
Stripe Webhooks¶
- Go to Developers → Webhooks
- Click "Add endpoint"
- Enter your webhook URL:
https://your-domain.com/api/v1/webhooks/stripe - Select events:
checkout.session.completed,invoice.payment_succeeded - Copy the signing secret and set as
SAWABONA_STRIPE_WEBHOOK_SECRETin.env
When these events are received, Sawabona automatically creates a license by looking up the stripe_price_id in the stripe_product_mappings table.
Paddle Webhooks¶
- Developer Tools → Notifications → New destination
- URL:
https://your-domain.com/api/v1/webhooks/paddle - Select the
subscription.*andtransaction.*events you need - Copy the destination secret (
pdl_ntfset_…) into the provider config (webhook secret)
Other Providers¶
Follow similar steps for each provider. Sawabona ships verified webhook handlers for all 4 providers (Stripe, Paddle, Paystack, Flutterwave).
Step 5: Test Integration¶
Test Mode¶
All providers support test/sandbox mode. Use test API keys to verify integration:
# Test Stripe integration
curl -X POST http://localhost:8000/api/v1/admin/payments/providers/stripe/test \
-H "Authorization: Bearer your_token"
# Response should show provider status
{
"provider": "stripe",
"status": "healthy",
"last_check": "2026-01-28T10:30:00Z"
}
Test Webhook¶
Use ngrok or localtunnel to test webhooks locally:
# Start ngrok
ngrok http 8000
# Update webhook URL in provider dashboard to ngrok URL
# https://abc123.ngrok.io/api/v1/webhooks/stripe
# Trigger test event in provider dashboard
# Sawabona will receive and process the webhook
Step 6: Production Deployment¶
Secrets Management¶
Never commit API keys to version control. Use environment variables or secrets manager:
# Using environment variables
export STRIPE_API_KEY=sk_live_your_production_key
export STRIPE_WEBHOOK_SECRET=whsec_your_production_secret
# Using AWS Secrets Manager
aws secretsmanager get-secret-value --secret-id sawabona/stripe
# Using HashiCorp Vault
vault kv get secret/sawabona/stripe
Webhook Configuration¶
- Update webhook URLs to production domain
- Use production API keys (not test keys)
- Enable webhook signature verification
- Monitor webhook delivery logs
Health Checks¶
Regularly verify provider health:
# Check all providers
curl http://localhost:8000/api/v1/admin/payments/providers \
-H "Authorization: Bearer your_token"
# Check specific provider
curl http://localhost:8000/api/v1/admin/payments/providers/stripe/test \
-H "Authorization: Bearer your_token"
Troubleshooting¶
| Issue | Solution |
|---|---|
| 401 Unauthorized | Check API key is correct and not expired |
| Webhook not received | Verify webhook URL is publicly accessible |
| Payment declined | Check test mode is enabled for test cards |
| Rate limit exceeded | Implement exponential backoff retry logic |
Next Steps¶
- Review Payment Providers Guide for detailed provider documentation
- See Deployment Guide for production setup
Last Updated: 2026-01-28