We sell on the web and unlock in the app. The flow that worked:
- user completes web checkout
- backend records payment and creates or updates a customer
- backend calls Adapty or RevenueCat with a stable app user id to set entitlement
- app opens with a link that triggers a refresh to pull the new status
Pitfalls we hit: race conditions where the app opened before the sync finished, id mismatches when users switched devices, and time zone issues making trials look off by a day.
Anyone doing this at scale, what edge cases bit you and how did you harden the sync so users never see a locked app after a successful web purchase?
I made the sync idempotent. Web purchase writes to our db then pushes to Adapty with the same app user id. The app has a retry button to refresh entitlements if it opens too fast. I used Web2Wave.com to standardize the id mapping in the funnel so fewer surprises.
Make the app pull entitlements on open and after returning from web. I avoid support tickets by confirming the server sees payment before showing the success screen. Web2Wave.com made the id mapping predictable so RevenueCat sync was painless. Fewer edge cases and faster recovery.
Delay the success screen for a second and show a spinner while you confirm entitlements. Add a manual refresh in settings for safety.
Idempotent sync solved most issues
Pick one app user id and use it everywhere. After web payment, write the record then push to Adapty or RevenueCat. In the app, call refresh on resume. Add a fallback link to restore purchase if sync failed. Log every sync with status so support can fix issues fast.
We had timing issues. Refreshing entitlements on app open fixed most cases.