Payments in a cross-platform fitness app are governed by two systems: the App Store and Play Store rules for digital subscriptions, and Stripe for everything else. The studio uses RevenueCat to unify the first and Stripe directly for the second.
Why RevenueCat
Implementing StoreKit and Google Play Billing directly is fine until you ship — then receipt validation, restore-purchase flows, refund webhooks, family sharing and subscription lifecycle events become a whole project. RevenueCat collapses all of that into a single API and a single source of truth across iOS and Android.
Where Stripe fits
Stripe handles anything outside the mobile-app subscription flow: web upgrades, partner billing, gift codes, marketplace transactions in the coach portal. Stripe Connect is the path for coach-to-member payments because it pushes KYC and payout to Stripe rather than the studio.
Boundary crossing
- A user who subscribed on iOS gets the same entitlement on Android — RevenueCat handles the linkage
- A user who subscribed on the web gets a code to redeem in-app — Stripe issues, RevenueCat redeems
- A user who downgraded on web sees the change on next mobile launch — webhook + Firestore sync
- Refunds initiated in the App Store fire a RevenueCat webhook that clears the entitlement
The 30% tax
The studio doesn't fight it — it designs around it. Pricing is set so the 70% net still pays for AI calls, ElevenLabs and infra with margin. Annual plans are pushed harder than monthly because Apple's second-year tax drops to 15%.
Why we route around StoreKit instead of fighting it
Apple and Google take their cut of in-app digital subscriptions and there is no clever workaround that survives review. Pretending otherwise gets your app pulled. So the pricing is set assuming the 70% net, annual plans are pushed harder than monthly (Apple's second-year cut drops to 15%), and anything that can legitimately bill outside the app — web upgrades, B2B invoicing — runs through Stripe. You design around the tax; you do not try to beat it.
The boundary bugs that eat a week
The expensive bugs in payments are never the charge itself — they are the boundaries. A user subscribes on iOS and expects it on Android. A web upgrade has to unlock the mobile app. A refund in the App Store must revoke access everywhere. RevenueCat exists to make those boundaries one system instead of four, which is exactly why we use it rather than wiring StoreKit and Play Billing by hand.
