OpenMates Docs Open Chat

Payment Processing

Payment Processing Stripe-based credit purchases with a chargeback-prevention tier system, EU consumer law compliance, and planned SEPA/Paddle support. Why T...

[T:documentation.sender_name]

Payment Processing

Stripe-based credit purchases with a chargeback-prevention tier system, EU consumer law compliance, and planned SEPA/Paddle support.

Why This Exists

OpenMates uses a credit-based billing model. Users purchase credits via card payments, which are consumed by AI model usage and other API calls. The tier system limits chargeback exposure for new users while allowing trusted users higher limits.

How It Works

sequenceDiagram
    participant U as User / Client
    participant S as Server
    participant ST as Stripe
    participant D as Directus

    U->>S: POST /payments/create-order<br/>(tier, currency)
    S->>S: Check tier limit + monthly spend
    S->>ST: Create PaymentIntent
    ST-->>S: client_secret
    S-->>U: client_secret

    U->>ST: Stripe.js card input + 3D Secure
    ST-->>U: Payment confirmed

    ST->>S: Webhook: payment_intent.succeeded
    S->>S: Decrypt credit balance<br/>+ add credits
    S->>D: Update user record
    S-->>U: WebSocket: balance update

Payment Flow

  1. User selects credit tier and currency (EUR, USD, JPY).
  2. Client creates a Stripe PaymentIntent via POST /v1/payments/create-order.
  3. Stripe.js handles card input and 3D Secure if required.
  4. On success, Stripe sends payment_intent.succeeded webhook.
  5. Backend extracts order details from metadata, decrypts and adds credits, updates cache, broadcasts balance via WebSocket.

Chargeback Prevention

Email + 2FA required: Users must confirm email and set up 2FA (TOTP or passkey) during signup before purchasing – filters automated scam attempts.

Tier system (O(1) cached lookup):

Tier Monthly Limit Requirement
Tier 0 No card 2+ chargebacks (SEPA only)
Tier 1 75 EUR Default for new users, or after 1 chargeback
Tier 2 150 EUR 3 consecutive months without chargeback
Tier 3 300 EUR 6 consecutive months without chargeback
Tier 4 500 EUR 12 consecutive months without chargeback
  • First chargeback: reset to Tier 1, reset consecutive months counter.
  • Second chargeback: reset to Tier 0 (card payments blocked, SEPA only).
  • Monthly spending counter resets at start of each calendar month.
  • USD/JPY purchases converted to EUR for limit checking.
  • SEPA transfers are not subject to tier limits.

EU Consumer Law Compliance

  • Explicit consent checkbox (unchecked by default) for immediate digital service execution at checkout.
  • Consent logged with timestamp and hashed IP for compliance.
  • Purchase confirmation email + invoice PDF include withdrawal waiver notice (durable medium).
  • Once credits used, withdrawal right expires (legally protected).
  • Gift cards cannot be refunded once redeemed.
  • Unused credits refundable within 14 days.

Receipt Email Decryption

  • User-initiated payments: encrypted_email_address decrypted with client-provided email_encryption_key.
  • Auto top-up payments: No client key available; uses encrypted_email_auto_topup (Vault-transit encrypted server-side when user enables auto top-up).

SEPA Bank Transfer

Available to all users regardless of payment tier (tier system only limits card payments).

  • Provider: Revolut Business API — webhooks detect incoming transfers.
  • Reference format: OM-{account_id}-{order_id_short} (shown to user, must be included in transfer).
  • Flow: User selects bank transfer → backend creates pending order in Directus + Redis → shows IBAN/BIC/reference → user transfers from their bank → Revolut webhook (TransactionCreated) fires → match by reference → validate amount (±€0.50 tolerance) → apply credits → send invoice email.
  • Order persistence: pending_bank_transfers Directus collection (7-day TTL), Redis cache for fast webhook matching.
  • Expiry: Celery beat task runs every 6 hours, expires pending orders past 7-day deadline.
  • Amount tolerance: ±€0.50 to absorb intermediary bank fees. Outside tolerance → flagged for admin review.
  • Support contributions: Separate endpoint, same flow but no credits granted — dispatches support receipt email.
  • Webhook verification: HMAC-SHA256 via Revolut-Signature + Revolut-Request-Timestamp headers, 5-minute replay protection.
  • Vault secrets: kv/data/providers/revolut_business{env}_webhook_secret, iban, bic, bank_name.

Edge Cases

  • Tier 0 users receive clear error message directing them to SEPA transfer.
  • Tier data cached on user record for O(1) lookup – no expensive invoice queries per purchase.
  • Currency conversion uses current rates; limits checked in EUR equivalent.
  • Auto Top-Up – monthly subscriptions and planned low-balance triggers
  • Signup & Auth – email confirmation and 2FA setup flow
  • Privacy Policy: shared/docs/privacy_policy.yml