# Monetization (web Stripe + native RevenueCat) ## Channels | Runtime | Checkout / manage | Ledger | |---------|-------------------|--------| | Web (`!isNativePlatform`) | Stripe Checkout + Customer Portal via `/finance/...` | Stripe webhooks | | Native Capacitor | RevenueCat IAP (`@revenuecat/purchases-capacitor`) | RevenueCat webhooks → same invoice/payment tables | FE displays whatever `/finance/invoices/` (and subscription) returns after refresh. Provider badge uses `provider` + `revenuecat_store`. ## App user id RevenueCat `appUserID` = Django user pk as string. 1. Prefer `id` from `/user/get/` (serializer returns all model fields). 2. Else JWT `user_id` claim (`SIMPLE_JWT.USER_ID_CLAIM`). Backend webhook resolver accepts numeric pk (or email fallback). ## Mobile env keys In `.env.mobile`: - `REACT_APP_REVENUECAT_APPLE_API_KEY` - `REACT_APP_REVENUECAT_GOOGLE_API_KEY` - `REACT_APP_REVENUECAT_OFFERING_ID` (optional) Package identifiers in the RC dashboard should include plan slugs (e.g. `founders`) so `purchasePlan(planSlug)` can match packages/products. Optional backend `REVENUECAT_PRODUCT_PLAN_MAP` maps product id → plan slug. ## Auth hooks - `Purchases.configure` once on native (first purchase / logIn). - `logIn(appUserID)` after SignIn / SignUp / AuthCallback / AccountContext load. - `logOut` on Header2 sign-out and Delete account. ## Related - Issue #100 (FE) + companion backend RevenueCat webhook PR - [`ANDROID.md`](ANDROID.md) / [`IOS.md`](IOS.md) for store builds