Migrate collab payments from Stripe to Whop. Both providers run side-by-side in production — no rip-and-replace, no new infrastructure. Payouts via Dots stay untouched.
This file gives Cursor and Claude full context about your Whop migration. Every file path, schema change, and code example — ready to implement.
Save as CLAUDE.md in your project root. Open Cursor. Say “implement the Whop migration.”
Whop runs alongside Stripe in production. No staging environment needed, no new dependencies. Routing is controlled by an env var with per-client override using your existing Firestore documents.
PAYMENT_PROVIDER env var defaults to "stripe". Per-client override: set paymentProvider: "whop" on the client’s Firestore document. All routing lives in services/payments/payment_router.py — one check, not scattered across files.Whop payment service, webhook controller, Firestore field additions. Stripe stays default. Deploy with zero behavior change.
Set paymentProvider: "whop" on FoodFluence’s own client document. Test with real money internally.
Enable Whop for 5–10 trusted clients. Verify webhook parity, payment confirmation timing, and Firestore consistency.
Flip PAYMENT_PROVIDER=whop in App Engine config. Stripe path stays in code as fallback until you’re confident.
Two core flows being migrated: saving a payment method (card) and charging for collaborations.
How your Firestore collections and payment modules map to Whop. New fields are added alongside existing Stripe fields.
| Your Collection | File | Whop Entity | New Fields |
|---|---|---|---|
clients |
services/firebase/firestore_service.py |
Member | whopMemberId, whopPaymentMethodId, paymentProvider |
clientDashboardAdmin |
services/firebase/firestore_service.py |
Member | whopMemberId |
collabs |
services/payments/stripe_payments.py |
Payment | whopPaymentId, paymentProvider |
influencerCampaigns |
services/firebase/firestore_service.py |
Payment Method | whopPaymentMethodId |
Side-by-side: the Stripe calls you have today vs. the Whop equivalents.
stripe.SetupIntent.create()stripe.PaymentMethod.list()stripe.PaymentMethod.attach()stripe.Customer.create()stripe.Customer.modify()stripe.PaymentIntent.create(off_session=True)stripe.Webhook.construct_event()checkout_configurations.create(mode="setup")payment_methods.list(member_id=...)payments.create(payment_method_id=...)standardwebhooks.Webhook.verify()POST /create-setup-intentPOST /save-payment-methodPOST /get-payment-methodsPOST /charge-for-collabPOST /bill-for-additional-collabPOST /stripe-webhookis_whop()is_whop()is_whop()is_whop()is_whop()POST /whop-webhook (NEW, alongside Stripe)Your existing Stripe event handlers map to these Whop events. Both webhook endpoints run simultaneously.
| Stripe Event | Whop Event | What Happens |
|---|---|---|
payment_intent.succeeded |
payment.succeeded |
Update collab with whopPaymentId and chargedAt |
payment_intent.payment_failed |
payment.failed |
Log failure, alert ops team |
setup_intent.succeeded |
setup_intent.succeeded |
Store whopMemberId + whopPaymentMethodId on client |
customer.subscription.created |
— | Not migrated (subscriptions out of scope) |
invoice.payment_succeeded |
— | Not migrated (subscriptions out of scope) |
/stripe-webhook continues handling subscription events. /whop-webhook handles Whop payment and setup events. Never remove the Stripe route.Where Whop fits in the FoodFluence stack. Orange is new, green stays unchanged. Both providers coexist.
Brand (Frontend)
|
v
Flask API (app.py)
|
v
payment_router.py ─── is_whop(client_doc)?
| |
| |
no (default) yes
| |
v v
stripe_payments.py whop_payments.py
| |
v v
Stripe API Whop API
| |
v v
/stripe-webhook /whop-webhook
| |
v v
stripe_webhook_ whop_webhook_
handler.py handler.py
| |
+────────┬───────────────+
v
Firestore (clients, collabs, campaigns)
|
Dots Payouts (unchanged)
One week to first live dollar. Stripe stays live the entire time.
Most of your stack is unchanged. Whop replaces only the Stripe pay-in layer for collab charges.