Monetization app + RevenueCat webhooks (store IAP ledger) (#69)
## Summary - Rename `finance` → **`monetization`** Django app (keep `finance_*` tables via `label = "finance"`) - Add `services/stripe.py` + `services/revenuecat.py`; RevenueCat webhook upserts **subscription + Invoice/Payment** (billing history parity with Stripe) - Mount `/api/monetization/` + keep `/api/finance/` alias - Extend `Source`/`Provider` with `revenuecat`; product→plan mapping via `revenuecat_product_id` / `REVENUECAT_PRODUCT_PLAN_MAP` Closes #68. Companion to [chat_web_app#100](ai_ml_operations/chat_web_app#100). ## Test plan - [x] `manage.py test monetization.tests` (54 OK) - [x] Smoke `chat_backend.tests.test_views_documents` + `test_oauth` - [ ] Deploy: set `REVENUECAT_WEBHOOK_SECRET`; point RC webhook at `/api/finance/webhooks/revenuecat/` - [ ] Map store product IDs on `SubscriptionPlan.revenuecat_product_id` (or env JSON map) - [ ] Sandbox INITIAL_PURCHASE → subscription `source=revenuecat` + invoice in `/finance/invoices/`Reviewed-on: #69
This commit was merged in pull request #69.
This commit is contained in:
@@ -98,7 +98,9 @@ with `COMPOSE_DATABASE_URL` if needed.
|
||||
| `EMAIL_HOST_*` | empty | yes (prod/beta) | SMTP2GO |
|
||||
| `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 |
|
||||
| `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 |
|
||||
| `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 |
|
||||
| `MICROSOFT_OAUTH_CLIENT_ID` / `..._SECRET` / `..._TENANT` | empty / `common` | for SSO/Drive | Also used for Drive linking (#47), incremental scopes |
|
||||
@@ -276,9 +278,19 @@ Post-delete UX: clear local tokens → redirect to sign-in. Subsequent
|
||||
|
||||
### Subscription change / cancel (portal + webhooks)
|
||||
|
||||
Plan change and cancel stay on Stripe Customer Portal
|
||||
Billing lives in the **`monetization`** Django app (package rename of
|
||||
`finance`; DB tables keep the `finance_*` prefix via app `label = "finance"`).
|
||||
URLs: `/api/monetization/...` and alias `/api/finance/...`.
|
||||
|
||||
**Web:** plan change/cancel stay on Stripe Customer Portal
|
||||
(`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`).
|
||||
|
||||
`GET /api/finance/subscription/` includes `cancel_at_period_end` and
|
||||
`current_period_end` for Account UI messaging.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user