Revora/Documentation/Stripe Connect
Billing Gateway Security

Stripe Connect Integration

Revora connects directly to your Stripe Billing account via Stripe Connect OAuth. All retention mutations occur directly on your Stripe account with server-enforced idempotency.

Stripe Connect Architecture

When you authorize Revora from Stripe Integration Hub, an OAuth authorization code exchange executes with Stripe (https://connect.stripe.com/oauth/token). The resulting access token is encrypted at rest and linked to your organization in revora_merchants.

AES-256-GCM Token Encryption

In lib/revora/encryption.ts, Revora encrypts all merchant access tokens using authenticated AES-256-GCM encryption with scrypt key derivation. Tokens are stored in Postgres in the strict format:

salt:iv:authTag:ciphertext

The decryption key lives strictly in server environment variables (REVORA_ENCRYPTION_KEY) and is never returned in client API responses or client console logs.

Automated Concession Execution

When a customer accepts a retention offer in the widget, POST /api/v1/sessions/:token/accept-offer executes the billing mutation directly against Stripe:

1. Promotional Discount Coupons (flow.type = "discount")

Revora creates a dedicated coupon via stripe.coupons.create with duration: "repeating" and duration_in_months: duration_months, then attaches it to the subscription via stripe.subscriptions.update(id, { discounts: [{ coupon }] }).

2. Billing Hiatus (flow.type = "pause")

Revora calls stripe.subscriptions.update(id, { pause_collection: { behavior: "void", resumes_at: resumesAt } }). Customer payments cease during the hiatus while service access and account configurations remain preserved.

3. Finalized Cancellation (Decline Retention)

When a subscriber declines all offers, Revora sets cancel_at_period_end: true on Stripe, ensuring customers retain access through their paid period without incurring future recurring charges.

Billing Error Classification (failed vs unknown)

In lib/revora/stripe-errors.ts, Revora strictly classifies errors to prevent false negatives:

  • Definitive Failures (status: "failed"): Card declines (402), resource missing (404), invalid parameter (400), authentication error (401). Recorded as definitive failure; user is notified and may continue cancellation.
  • Ambiguous Network Failures (status: "unknown"): Socket hang-up, ECONNRESET, timeout, provider 5xx, or 429 rate limit. Never claimed as a failure because the mutation may have committed on Stripe's servers. Marked as billing_unknown so the subscription is reconciled before cancellation proceeds.