Whop × Flite

Integration Guide

Whop runs alongside Stripe in production — no rip-and-replace. Your Next.js 14 frontend, Express API, MongoDB, JWT auth, and all non-payment routes stay untouched. Platform treasury model preserved — fees stay calculated in-app. One env var controls the rollout.

Stripe PaymentIntents → Whop Checkout Stripe Connect → Whop Companies Stripe Elements → Whop Redirect/Embed Next.js 14 + Express stays No new dependencies Razorpay INR stays

Start Here — Drop This Into Your Repo

This file gives Cursor and Claude full context about your Whop migration. Every file path in backend-code/ and next-frontend/, schema change, and JavaScript code example — ready to implement.

Save as CLAUDE.md in your project root. Open Cursor. Say “implement the Whop migration.”

Implement the Whop integration for Flite. Read CLAUDE.md for full context. This is a Platform Treasury model — all payments collect to the platform, then distribute via transfers. Key changes: (1) Add backend-code/services/whop.service.js HTTP client using existing axios. (2) Add backend-code/controlles/whop.controller.js webhook handler with HMAC verification + idempotency + metadata-driven routing (same pattern as existing Stripe webhooks). (3) Add getPaymentProvider(organization) to backend-code/constants/constants.js for provider routing. (4) In order.controller.js, add Whop checkout session path behind provider check. After payment succeeds, calculate host share via existing transparentFeeCalculation() in utils/helper.js, then create Whop transfer to host's connected company. (5) Add whop_company_id + whop_verification_status + payment_provider to Organization and Vendor schemas. (6) Add whop_payment_id to Order schema. (7) Register POST /api/whop-webhook in server.js with raw body parser. (8) In next-frontend, handle Whop checkout URL redirect/iframe in CheckoutFlowPopup.jsx and PaymentForm components (replaces Stripe Elements). Deploy with PAYMENT_PROVIDER=stripe (default), test on one org, then roll out.

Rollout Strategy

Whop runs alongside Stripe in production. No staging needed, no new dependencies. Routing is controlled by an env var with per-Organization override. The platform treasury model is preserved — fees calculated in-app, not via Stripe application_fee_amount.

PAYMENT_PROVIDER env var defaults to "stripe". Per-org override: Organization.payment_provider === "whop". All routing lives in getPaymentProvider() in backend-code/constants/constants.js — one check, not scattered across 80+ files.
1

Build

Whop service client, webhook controller, Mongoose schema additions, both checkout paths. Stripe stays default. Deploy with zero behavior change.

2

Internal Test

Set payment_provider: "whop" on your own Organization. Buy test tickets with real money. Verify webhooks, ledger entries, and outbound partner webhooks.

3

Small Cohort

Enable Whop for 5–10 trusted host organizations. Verify payout timing, conversion tracking, and multi-currency behavior.

4

Full Rollout

Flip PAYMENT_PROVIDER=whop globally. Stripe path stays in code as fallback until you’re confident.

Money Flows

Platform Treasury model: all payments collect to Flite’s Whop account, then fees are calculated in-app via transparentFeeCalculation() and host share is transferred out. Razorpay INR stays in phase 1.

Ticket Purchase (Platform Treasury)

Frontend CheckoutFlowPopup
Backend Whop Checkout
Platform Collects Payment
Webhook Transfer to Host

Replaces stripe.paymentIntents.create in backend-code/controlles/stripe.controller.js + Stripe Elements in next-frontend/src/components/PaymentForm/. Fees stay calculated in-app via utils/helper.js. Host share transferred after webhook.

Host Onboarding & Payouts

Organization Registers
Backend Whop Company
KYC Whop Onboarding
Payouts Auto Payout

Replaces stripe.accounts.create + stripe.accountLinks.create in backend-code/controlles/stripe.controller.js and vendor.controller.js. Frontend onboarding UI in next-frontend/src/page/vendonConnects/.

Ad Spend + Message Blasts

Host Buys Ad/Blast
Backend Whop Checkout
Platform Flite Revenue

Replaces PaymentIntents in backend-code/controlles/adsController.js and bandWidthController.js. Metadata routing (adSpend, blastSpend) preserved in Whop webhook handler.

Refunds

Admin Initiates Refund
API Whop Refund
Webhook Ledger Updated

Replaces 3 stripe.refunds.create call sites. Supports full and partial refunds. refundWithoutFee org flag respected.

Your Code → Whop

How your existing Mongoose schemas map to Whop. All backend files in backend-code/.

Your SchemaFileWhop EntityNew Fields
Organization backend-code/models/organizationModel.js Company (connected) whop_company_id, whop_verification_status, payment_provider
Vendor backend-code/models/vendorModel.js Company (connected) whop_company_id, whop_verification_status
Order backend-code/models/orderModel.js Payment whop_payment_id, whop_checkout_session_id, whop_refund_id
OverallPayout backend-code/models/OverallPayout.js Payout whop_payout_id, whop_transfer_id
VendorPayout backend-code/models/vendorPayoutModel.js Payout whop_payout_id, whop_transfer_id
Transaction backend-code/models/transactionsModel.js Payment / Transfer / Payout whop_payment_id, whop_transfer_id, whop_payout_id
User backend-code/models/user.js Customer (by email) No changes — matched via checkout metadata
EventRequest backend-code/models/eventRequestModel.js (unchanged) Promoter commissions tracked in Transaction
CustomFee backend-code/models/customFeeModel.js (unchanged) Fee calculation stays in utils/helper.js

What Changes

Side-by-side: the Stripe calls you have today vs. the Whop equivalents.

Stripe (Today) — 80+ files, ~180 calls

  • paymentIntents.create — tickets, ads, blasts, reservations
  • accounts.create (Express) — host/vendor onboarding
  • accountLinks.create — KYC link
  • transfers.create — platform → host
  • payouts.create — host → bank
  • refunds.create — full + partial
  • Stripe Elements — 10+ frontend files
  • 5 per-currency Stripe instances

Whop (After)

  • POST /checkout_sessions — all payment contexts
  • POST /companies — host/vendor onboarding
  • POST /companies/{id}/account_links — KYC
  • POST /transfers — platform → host
  • Automatic — Whop pays hosts on schedule
  • POST /payments/{id}/refund — full + partial
  • Redirect/iframe — no Stripe Elements needed
  • 1 API key — multi-currency native

Stripe Webhooks (Today)

  • payment_intent.succeeded
  • payment_intent.amount_capturable_updated
  • payment_intent.payment_failed
  • 5 per-currency endpoints

Whop Webhooks (After)

  • payment.succeeded
  • payment.failed
  • payment.refunded
  • company.created / company.updated
  • payout.completed
  • 1 unified endpoint, all currencies

Webhook Mapping

Your existing Stripe event handlers map to these Whop events. Both webhook endpoints run simultaneously.

Stripe EventWhop EventWhat Happens
payment_intent.succeeded payment.succeeded Mark order complete, create ledger entry, fire outbound webhook, track conversions
payment_intent.payment_failed payment.failed Mark order failed, log error
payment_intent.amount_capturable_updated Hold/capture flow — handle via checkout completion instead
(Stripe Connect account events) company.created Set whop_company_id on Organization
(Stripe Connect status changes) company.updated Update whop_verification_status, gate checkout/payout actions
(Transfer/payout completion) payout.completed Update OverallPayout status, reconcile ledger
Outbound webhooks stay identical. Organizations with webhookUrl configured continue receiving the same payload shape for order.completed events, regardless of whether Stripe or Whop processed the payment.

Architecture

Where Whop fits. Orange is new, green stays unchanged. Both providers coexist.

  next-frontend/ (Vercel)             backend-code/ (AWS Amplify)
  ┌───────────────────────┐     ┌──────────────────────────┐
  │ Next.js 14 (App Router) │     │ Express API (port 5001)    │
  │ CheckoutFlowPopup.jsx   │     │ server.js + 16+ controllers│
  │ PaymentForm/ components │ ──> │ order.controller.js        │
  │ vendonConnects/ (onb.)  │     │ stripe.controller.js       │
  └───────────────────────┘     └───────────┬──────────────┘getPaymentProvider(org)  │
                           ┌───────┴───────┐
                           │                     │
              ┌──────────┴────┐  ┌────┴──────────┐
              │ Stripe (default) │  │ Whop (new)      │
              │ PaymentIntents   │  │ Checkout        │
              │ Connect Express  │  │ Companies       │
              │ Transfers        │  │ Transfers       │
              │ 5 instances/curr │  │ 1 key, all curr │
              └─────────────────┘  └────────────────┘┌───────────────────────┴───┐
              │   MongoDB (~79 models)        │
              │  Organization, Order, Vendor,  │
              │  Transaction, OrderPayout, ... │
              └────────────────────────────┘

  Webhooks (both live):
  POST /api/stripe-webhook-{usd,cad,gbp,sgd,inr}  ← Stripe
  POST /api/whop-webhook                          ← Whop

Host Verification States

Connected organizations go through verification before they can receive payouts. Maps to Whop company verification status.

StateMeaningCan DoBlocked
pending Company created, onboarding not started Create events, sell tickets Receive payouts
kyc_pending KYC submitted, under review Create events, sell tickets Receive payouts
restricted Partially verified, limited capabilities Sell tickets (capped volume) Full payouts
active Fully verified Everything — sell, receive payouts, manage bank Nothing
suspended Account flagged or deactivated View dashboard Sell tickets, receive payouts

Timeline

One week to first live dollar. Stripe stays live the entire time.

Day 1–2
Build
  • Whop service client (axios)
  • Webhook controller + idempotency
  • Mongoose schema additions
  • Both checkout paths
  • Deploy — Stripe still default
Day 3–4
Internal Test
  • Enable Whop on your own org
  • Buy tickets with real money
  • Verify webhook + ledger entries
  • Test outbound partner webhooks
Day 5–6
Small Cohort
  • 5–10 trusted host orgs
  • Multi-currency checkout
  • Payout timing validated
  • Conversion tracking confirmed
Day 7
Full Rollout
  • Flip env var to “whop”
  • Stripe path stays as fallback
  • First live dollar

What Stays the Same

Most of your stack is unchanged. Whop replaces only the payment provider layer.

Next.js 14 (App Router)
Express 4.x backend
MongoDB + Mongoose (79 models)
JWT authentication
TanStack React Query v5
Material UI + Radix + Tailwind
Socket.io real-time
SendGrid email
Twilio / Bandwidth / Telnyx SMS
Firebase push
AWS S3 + Amplify hosting
Stripe Terminal / Tap to Pay
Razorpay INR flows
Fee calc (transparentFeeCalculation)
Payout gating controls
No new npm packages
~ Chargeflow disputes (rewired to Whop events)
~ Partner outbound webhooks (same payload shape)
~ Laylo + Meta CAPI + GA tracking (rewired)
~ OpenAI chatbot (Whop paths added)
Bottom line: Your Next.js 14 frontend, Express API, MongoDB (79 models), JWT auth, React Query, MUI/Radix/Tailwind, real-time, email/SMS/push, Terminal, Razorpay, and all fee calculation logic stay untouched. Stripe stays as the default and fallback. No new npm packages — backend uses existing axios, frontend uses redirect/iframe (no Stripe Elements equivalent needed). New code: backend-code/services/whop.service.js, backend-code/controlles/whop.controller.js, one frontend checkout component, and field additions to existing Mongoose schemas.