## Summary - Mobile access is granted by `POST /api/finance/store/confirm/` after the app finishes a StoreKit or Play Billing purchase. - App Store signed transactions are checked against Apple Root CA G3. Play purchase tokens are checked with the Play Developer API. - The RevenueCat webhook no longer grants a plan. Stripe Checkout and the Stripe webhook stay for the website. - A purchase account token must match the signed-in user, and a transaction already linked to another account is rejected. Access ends when the verified period end passes unless the app confirms again. Client: ai_ml_operations/chat_web_app#122 ## Config - `APPLE_IAP_BUNDLE_ID` (default `ai.hesychia.chat`) - `GOOGLE_PLAY_PACKAGE_NAME` - `GOOGLE_PLAY_SERVICE_ACCOUNT_JSON` (JSON or a file path) - Plan `revenuecat_product_id` or `REVENUECAT_PRODUCT_PLAN_MAP` maps the store product to a plan ## Test plan - [x] `python manage.py test monetization.tests.test_store_purchases monetization.tests.test_revenuecat monetization.tests.test_plans_quotas` - [ ] Confirm an App Store sandbox transaction and a Play license-test purchase against a configured backend - [ ] Confirm a token already linked to another user is rejected - [ ] Confirm `GET /subscription/` returns `store_account_token` and flips a lapsed store sub to canceled Reviewed-on: #79
This commit was merged in pull request #79.
This commit is contained in:
1 parent
bb5c43a4e7
commit
4fc2b87bb4
14 files changed
+1141
-119
No files matched your search
@@ -99,7 +99,9 @@ with `COMPOSE_DATABASE_URL` if needed.
|
||||
| `CAPTCHA_SECRET_KEY` | empty | recommended | |
|
||||
| `ENABLE_ACCOUNT_REGISTRATION` | `false` | optional | Self-serve sign-up; keep false until ready |
|
||||
| `STRIPE_SECRET_KEY` / `STRIPE_PUBLISHABLE_KEY` / `STRIPE_WEBHOOK_SECRET` | empty | yes for billing | Stripe API + webhook (`monetization` app) |
|
||||
| `REVENUECAT_WEBHOOK_SECRET` | empty | yes for store IAP | RevenueCat webhook Authorization bearer |
|
||||
| `APPLE_IAP_BUNDLE_ID` | `ai.hesychia.chat` | yes for iOS IAP | Must match the signed StoreKit transaction |
|
||||
| `GOOGLE_PLAY_PACKAGE_NAME` | `ai.hesychia.chat` | yes for Play IAP | Android application id |
|
||||
| `GOOGLE_PLAY_SERVICE_ACCOUNT_JSON` | empty | yes for Play IAP | Play Console service-account JSON (or a file path) |
|
||||
| `REVENUECAT_PRODUCT_PLAN_MAP` | empty JSON | optional | `{"product_id":"plan_slug"}` fallback map |
|
||||
| `STRIPE_PRICE_ID` | empty | optional | Pre-created Price; else `$10/mo` from settings |
|
||||
| `GOOGLE_OAUTH_CLIENT_ID` / `..._SECRET` | empty | for SSO/Drive | Also used for Drive linking (#47), incremental scopes |
|
||||
@@ -286,10 +288,14 @@ URLs: `/api/monetization/...` and alias `/api/finance/...`.
|
||||
(`POST /api/finance/portal/`). Local state syncs via
|
||||
`customer.subscription.updated` / `deleted` webhooks.
|
||||
|
||||
**Native (Play / App Store):** RevenueCat webhooks at
|
||||
`POST /api/finance/webhooks/revenuecat/` (Authorization bearer =
|
||||
`REVENUECAT_WEBHOOK_SECRET`) upsert Invoice/Payment ledger rows and sync
|
||||
`UserSubscription` (`source=revenuecat`).
|
||||
**Native (Play / App Store):** the app buys through StoreKit or Play Billing,
|
||||
then `POST /api/finance/store/confirm/` with the signed App Store transaction
|
||||
or the Play purchase token. The backend verifies it (Apple certificate chain,
|
||||
or Play Developer API `purchases.subscriptionsv2`) and upserts the ledger.
|
||||
`source` is `app_store` or `play_store`. There is no store webhook. Renewals
|
||||
are another confirm from the app; access ends when `current_period_end` passes.
|
||||
`GET /api/finance/subscription/` includes `store_account_token` to pass into
|
||||
the store purchase as `appAccountToken` / `obfuscatedAccountId`.
|
||||
|
||||
`GET /api/finance/subscription/` includes `cancel_at_period_end` and
|
||||
`current_period_end` for Account UI messaging.
|
||||
|
||||
Reference in new issue
Block a user