Mobile entitlements are granted only when RevenueCat POSTs /monetization/webhooks/revenuecat/. That is a webhook, not a store payment. Web checkout stays on Stripe.
What
iOS purchases go through StoreKit. Android purchases go through Play Billing.
The signed-in app sends the signed App Store transaction or the Play purchase token to an authenticated confirm endpoint.
The backend verifies the transaction with Apple (signed transaction chain) or Google Play Developer API, then writes the same subscription, invoice, and payment rows.
Bind a purchase to the signed-in user (appAccountToken / obfuscatedAccountId). Reject a transaction already linked to a different account.
Drop the RevenueCat webhook as a way to grant access.
Renewals and restores are the app re-confirming the current store entitlement. Access ends when the verified period end passes.
Stripe Checkout and the Stripe webhook stay for the website.
Companion
chat_web_app Capacitor shell: replace the RevenueCat purchase call with the native store plugin and POST the result to the confirm endpoint.
## Why
Mobile entitlements are granted only when RevenueCat POSTs `/monetization/webhooks/revenuecat/`. That is a webhook, not a store payment. Web checkout stays on Stripe.
## What
- iOS purchases go through StoreKit. Android purchases go through Play Billing.
- The signed-in app sends the signed App Store transaction or the Play purchase token to an authenticated confirm endpoint.
- The backend verifies the transaction with Apple (signed transaction chain) or Google Play Developer API, then writes the same subscription, invoice, and payment rows.
- Bind a purchase to the signed-in user (`appAccountToken` / `obfuscatedAccountId`). Reject a transaction already linked to a different account.
- Drop the RevenueCat webhook as a way to grant access.
- Renewals and restores are the app re-confirming the current store entitlement. Access ends when the verified period end passes.
- Stripe Checkout and the Stripe webhook stay for the website.
## Companion
`chat_web_app` Capacitor shell: replace the RevenueCat purchase call with the native store plugin and POST the result to the confirm endpoint.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Why
Mobile entitlements are granted only when RevenueCat POSTs
/monetization/webhooks/revenuecat/. That is a webhook, not a store payment. Web checkout stays on Stripe.What
appAccountToken/obfuscatedAccountId). Reject a transaction already linked to a different account.Companion
chat_web_appCapacitor shell: replace the RevenueCat purchase call with the native store plugin and POST the result to the confirm endpoint.Backend: #79
Client: ai_ml_operations/chat_web_app#122
Closed. The work is on master: backend #79 and chat_web_app #122.