Payment Provider Integration

secure.checkout.best features an extensible payment provider framework that allows multiple payment methods per store, with support for adding new providers.

Overview

The payment provider framework supports:

Available Providers

Stripe Active

Credit/debit card payments via Stripe. Supports refunds, webhooks, and client-side card elements.

CapabilitySupported
RefundsYes
Partial RefundsYes
WebhooksYes
CurrenciesUSD, EUR, GBP, CAD, AUD
Manual Payment Active

Check or money order payments. Orders are placed with "awaiting payment" status until merchant confirms receipt.

CapabilitySupported
RefundsNo (manual process)
WebhooksNo
CurrenciesUSD
Cryptocurrency Coming Soon

Bitcoin, Ethereum, and USDC payments via Coinbase Commerce or BitPay. Automatic currency conversion with real-time pricing.

API Endpoints

List Available Providers

GET /api/v1/payments/providers

Returns all registered payment providers with their capabilities and required credentials.

{
  "providers": [
    {
      "key": "stripe",
      "name": "Credit/Debit Card",
      "description": "Pay securely with your credit or debit card via Stripe",
      "capabilities": {
        "supports_redirect": false,
        "supports_webhook": true,
        "supports_refund": true,
        "requires_client_side": true,
        "supported_currencies": ["usd", "eur", "gbp", "cad", "aud"]
      },
      "required_credentials": [
        {"key": "publishable_key", "label": "Stripe Publishable Key", "required": true},
        {"key": "secret_key", "label": "Stripe Secret Key", "required": true, "encrypted": true}
      ]
    },
    {
      "key": "manual",
      "name": "Check / Money Order",
      "description": "Pay by check or money order mailed to the merchant",
      "capabilities": {
        "supports_redirect": false,
        "supports_webhook": false,
        "supports_refund": false,
        "requires_client_side": false,
        "supported_currencies": ["usd"]
      }
    }
  ]
}

Get Store Payment Options

GET /api/v1/payments/store/{store_id}/options

Returns the enabled payment options for a specific store, ordered by priority.

{
  "payment_options": [
    {"key": "stripe", "name": "Credit/Debit Card", "description": "...", "priority": 0},
    {"key": "manual", "name": "Check / Money Order", "description": "...", "priority": 10}
  ]
}

Create Payment Intent

POST /api/v1/payments/create-intent

Initiates a payment for an order using the specified provider.

// Request
{
  "order_id": "uuid-of-order",
  "provider": "stripe"  // optional, defaults to "stripe"
}

// Response (Stripe)
{
  "provider": "stripe",
  "amount": 4000,
  "currency": "usd",
  "client_secret": "pi_xxx_secret_xxx",
  "payment_intent_id": "pi_xxx",
  "publishable_key": "pk_live_xxx"
}

// Response (Manual)
{
  "provider": "manual",
  "amount": 4000,
  "currency": "usd",
  "payment_instructions": "Make checks payable to..."
}

Provider Configuration

Payment providers are configured per-store via the Merchant Portal or Internal API.

Database Model

PaymentProviderConfig:
  - store_id: UUID (foreign key to stores)
  - provider_key: string ("stripe", "manual", etc.)
  - is_enabled: boolean
  - priority: integer (lower = shown first)
  - credentials_json: encrypted JSONB
  - settings_json: JSONB
Backward Compatibility: Stores without explicit PaymentProviderConfig records will automatically use legacy store fields (stripe_secret_key_encrypted, manual_payment_enabled) for payment configuration.

Adding New Providers

New payment providers can be added by implementing the PaymentProvider interface:

from src.services.payment_providers import PaymentProvider, register_provider

@register_provider
class MyProvider(PaymentProvider):
    provider_key = "my_provider"
    display_name = "My Payment Method"
    description = "Description shown to customers"
    
    @classmethod
    def get_capabilities(cls):
        return ProviderCapabilities(
            supports_redirect=True,
            supports_webhook=True,
            supports_refund=False,
            supported_currencies=['usd']
        )
    
    @classmethod
    def get_required_credentials(cls):
        return [
            {"key": "api_key", "label": "API Key", "required": True, "encrypted": True}
        ]
    
    def initiate_payment(self, order_id, amount_cents, currency, ...):
        # Implement payment initiation
        return PaymentResult(success=True, status=PaymentStatus.PENDING, ...)
    
    def confirm_payment(self, order_id, external_reference, ...):
        # Implement payment confirmation
        return PaymentResult(success=True, status=PaymentStatus.SUCCEEDED, ...)

Once registered, the provider is automatically available via API endpoints and can be enabled for stores.

Roadmap

ProviderStatusTarget
StripeLive-
Manual PaymentLive-
Coinbase CommercePlannedQ1 2025
BitPayPlannedQ1 2025
PayPalConsideringTBD