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:
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_unknownso the subscription is reconciled before cancellation proceeds.