Purchase Testing
Test purchases, restore flows, and entitlement updates.
Purchases require a native development, preview, or store build. Expo Go and web
can render the rest of the starter, but they cannot exercise
react-native-purchases.
iOS purchases are end-to-end with the shipped webhook. Android can load the RevenueCat SDK when configured, but Google Play webhook events are ignored by the current Supabase mapper. Extend the webhook before treating Android purchase tests as entitlement tests.
Build requirement
Use an EAS development build or a store-distribution build:
eas build --profile development --platform ios
eas build --profile development --platform androidSet the RevenueCat key for the platform you test:
EXPO_PUBLIC_REVENUECAT_IOS_KEY=appl_xxxxxxxxxxxxxxxxx
EXPO_PUBLIC_REVENUECAT_ANDROID_KEY=goog_xxxxxxxxxxxxxxxxxRestart Metro after env changes. Rebuild after bundle/package ID, signing, or store configuration changes.
Store test accounts
Use a real device whenever possible.
Create a sandbox tester
In App Store Connect, create a sandbox tester under Users and Access → Sandbox Testers. Use an email that is not already an Apple ID.
Install a native build
Install a development build, internal distribution build, or TestFlight build whose bundle identifier matches the products you configured.
Sign into the sandbox account
On the device, sign into the Sandbox Account from App Store or Developer settings, depending on iOS version.
Use a Play-distributed test build when testing Google Play Billing.
Configure license testers
In Play Console, add license testers and make sure the tester can access the internal, closed, or open testing track that contains your build.
Match package and signing
The package name and signing certificate must match the app and products in Play
Console. Variant IDs such as expo.soarstarter.com.dev need their own product
setup if you test them.
Extend the webhook before entitlement testing
The current RevenueCat Edge mapper ignores PLAY_STORE. Android purchase UI can
be tested, but the Supabase entitlement row will not update until that backend
path is implemented.
Run an iOS purchase test
Sign into the app
Launch the native build and sign into a Supabase account. RevenueCat identity sync must use that Supabase user UUID before purchase.
Open the paywall
Open Home's license card, Me → Upgrade to Pro, or /paywall. Confirm packages
load from the current offering and Annual is selected when present.
Buy a package
Tap Continue and approve the sandbox purchase sheet. The paywall closes on
success and entitlement.pollAfterPurchase() starts polling Supabase for the
authoritative row.
Verify RevenueCat
In RevenueCat, switch to sandbox data and find the customer whose App User ID is
the Supabase user UUID. The pro entitlement should be active.
Verify Supabase
Run a SQL check in Supabase:
select user_id, provider, product_id, product_type, status, period_end
from public.subscriptions
where user_id = 'your-supabase-user-uuid';For an App Store purchase, expect provider = 'app_store', status of active
or trialing, and period_end in the future. Lifetime purchases use
product_type = 'one_time'.
Restore test
- Reinstall the native build or sign out and back in.
- Use the same store sandbox account and the same Supabase account.
- Open the paywall or Manage subscription.
- Tap Restore purchases.
- Confirm RevenueCat returns an active
proentitlement and the app polls the Supabase row.
Restore checks RevenueCat's purchase cache; the actual gate still depends on the
subscriptions row.
Common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| Paywall says purchases are not configured | Missing platform RevenueCat key, web runtime, or Expo Go | Set EXPO_PUBLIC_REVENUECAT_IOS_KEY / EXPO_PUBLIC_REVENUECAT_ANDROID_KEY and use a native build |
| Packages never load | No current offering, packages missing, product metadata incomplete, or store sync delay | Activate the offering, attach packages, complete store metadata, wait for sync |
| User is asked to sign in before buying | No Supabase session | Sign in first so the purchase is tied to the account UUID |
| Bundle/package mismatch | Testing expo.soarstarter.com.dev while products were created for production ID | Configure products for the active variant or build the matching variant |
| RevenueCat entitlement active but Supabase row missing | Webhook URL/Authorization wrong, function not deployed, or app_user_id is not a UUID | Recheck REVENUECAT_WEBHOOK_AUTH, function logs, and RevenueCat customer ID |
| Android purchase does not unlock Supabase entitlement | Current webhook ignores PLAY_STORE events | Extend the webhook mapper and database enum before Android entitlement testing |
| Restore finds nothing | Different store sandbox account, different Supabase account, or no active purchase | Use the same accounts, or test with a fresh sandbox purchase |
