Skip to content

Provider Setup

Before processing payments, each merchant must configure their provider credentials. Credentials are encrypted at rest using AES-256 (Fernet) and cached in Redis for 15 minutes.

Setting Credentials

PUT /v1/merchant/providers
X-API-Key: sk_live_...

Stripe

{
  "provider": "stripe",
  "stripe": {
    "secret_key": "sk_live_...",
    "webhook_secret": "whsec_..."
  }
}
Field Required Description
secret_key Stripe secret key (sk_live_ or sk_test_)
webhook_secret Stripe webhook signing secret

M-Pesa

{
  "provider": "mpesa",
  "mpesa": {
    "env": "sandbox",
    "consumer_key": "your_consumer_key",
    "consumer_secret": "your_consumer_secret",
    "passkey": "your_passkey",
    "shortcode": "174379",
    "initiator": "apiop37",
    "security_credential": "encrypted_credential...",
    "result_url": "https://yourdomain.com/v1/webhooks/mpesa/transactionstatus/result",
    "timeout_url": "https://yourdomain.com/v1/webhooks/mpesa/transactionstatus/timeout"
  }
}
Field Required Description
consumer_key From Daraja My Apps
consumer_secret From Daraja My Apps
passkey Lipa Na M-Pesa passkey
shortcode Paybill or Till number
env sandbox (default) or live
initiator API user for reversals/status queries
security_credential Encrypted password for initiator
result_url Callback URL for async results
timeout_url Callback URL for timeouts

PayPal

{
  "provider": "paypal",
  "paypal": {
    "env": "sandbox",
    "client_id": "your_client_id",
    "client_secret": "your_client_secret"
  }
}
Field Required Description
client_id PayPal app client ID
client_secret PayPal app secret
env sandbox (default) or live

Response

Sensitive fields are masked — only the last 4 characters are shown:

{
  "success": true,
  "data": {
    "id": "uuid-...",
    "provider": "stripe",
    "is_active": true,
    "config_summary": {
      "secret_key": "****4x7K",
      "webhook_secret": "****test"
    },
    "created_at": "2025-01-01T00:00:00Z",
    "updated_at": "2025-01-01T00:00:00Z"
  }
}

Listing & Deleting

# List all configured providers
GET /v1/merchant/providers

# Remove a provider
DELETE /v1/merchant/providers/stripe

What happens if not configured?

Any payment request to an unconfigured provider returns 422:

{
  "success": false,
  "errors": [{
    "code": "VALIDATION_ERROR",
    "message": "No stripe credentials configured. Set them via PUT /v1/merchant/providers with provider='stripe'."
  }]
}

Security

flowchart LR
    Merchant["Merchant<br/>PUT /v1/merchant/providers"] -->|HTTPS| API["API Server"]
    API -->|"Fernet encrypt"| DB[(PostgreSQL<br/>encrypted blob)]
    API -->|"Fernet encrypt"| Redis[(Redis cache<br/>encrypted, 15min TTL)]

    Payment["Payment Request"] --> Cache{"Redis<br/>cache hit?"}
    Cache -->|Hit| Decrypt["Fernet decrypt"]
    Cache -->|Miss| DBRead["DB read → decrypt → warm cache"]
    Decrypt --> Provider["Provider API call"]
    DBRead --> Provider