Testing & Sandbox

In-app purchases require specific setup for testing on each platform. This guide covers sandbox environments, common pitfalls, and framework-specific notes to help you test effectively.

iOS Testing#

Sandbox Apple Account#

Apple provides sandbox accounts for testing purchases without real charges. To configure a sandbox account on your device:

  1. Create sandbox testers in App Store Connect → Users and Access → Sandbox Testers
  2. On your device, go to Settings → App Store → Sandbox Account (iOS 14+) and sign in with the sandbox Apple ID
  3. Run your app — purchases will use the sandbox environment

Reference: Apple: Testing in-app purchases with sandbox

StoreKit Testing in Xcode#

Xcode provides local StoreKit testing that works without a network connection or sandbox account. This is the fastest way to iterate on your purchase logic:

  1. Create a StoreKit Configuration file in Xcode (File → New → File → StoreKit Configuration File)
  2. Define your products and subscriptions in the configuration
  3. Edit your scheme (Product → Scheme → Edit Scheme) and set the StoreKit Configuration under the Options tab
  4. Run the app in the simulator or on device — purchases use the local configuration

Local StoreKit testing also lets you simulate scenarios like subscription renewal, refunds, ask-to-buy, and interrupted purchases via the StoreKit Transaction Manager in Xcode.

Reference: Apple: Setting up StoreKit testing in Xcode

TestFlight Testing#

TestFlight builds use the sandbox environment automatically. Testers do not need a separate sandbox account — purchases made in TestFlight are not charged. This is the closest test environment to production.

Reference: Apple: TestFlight

Clearing Sandbox Purchase History#

To reset sandbox purchase history on iOS:

  1. Go to Settings → App Store → Sandbox Account
  2. Tap your sandbox account
  3. Select Manage and clear purchase history for specific apps

Alternatively, create a new sandbox tester account in App Store Connect for a completely fresh state.

Android Testing#

License Testers#

License testers can make test purchases without being charged. To set them up:

  1. Open Google Play Console → Settings → License testing
  2. Add the Gmail addresses of your testers
  3. Set the license response to RESPOND_NORMALLY

Reference: Android: Test your Google Play Billing integration

Internal Testing Track#

Upload your APK or AAB to an internal testing track in Google Play Console. This gives you a test link that testers can use to install the app. The app must be installed from the Play Store (not sideloaded) for billing to work properly.

Reference: Google: Set up internal testing

Test Card Numbers#

When testing with license tester accounts, Google Play provides special test instruments:

  • Test card, always approves — Purchase completes successfully
  • Test card, always declines — Purchase is rejected
  • Test card, slow — Simulates a slow network response

These appear automatically in the payment sheet when a license tester initiates a purchase.

Clearing Test Purchases#

To clear test purchases on Android:

  • Consumable products are automatically consumed when purchased by license testers (after 3 minutes if not consumed by the app)
  • For subscriptions, cancel them in the Google Play app or wait for the short test renewal period to expire
  • You can also refund or revoke purchases in the Google Play Console → Order management

Common Issues#

Products Not Found#

If fetchProducts returns an empty list, check the following:

  • Agreements: Ensure all paid app agreements are signed in App Store Connect / Google Play Console
  • Banking & Tax: Complete your banking and tax information in the respective console
  • Bundle ID: The app's bundle identifier must exactly match what is configured in the store
  • Product IDs: Verify product identifiers match exactly (case-sensitive)
  • Product Status: Products must be in "Ready to Submit" or "Approved" state (iOS) or "Active" state (Android)
  • Wait time: New products can take several hours to propagate — up to 24 hours in some cases

Purchase Not Completing#

If a purchase starts but never completes or stays in a pending state:

  • Ensure you are calling finishTransaction after processing the purchase. Unfinished transactions block future purchases.
  • Check that your purchase listener is properly set up before initiating the purchase
  • On Android, verify the app is signed correctly and installed from the Play Store test track

Connection Failed#

If you receive connection errors when trying to fetch products or make purchases:

  • Ensure initConnection is called before any other IAP operations
  • On Android, the Google Play Billing client may fail to connect if the Play Store app is outdated or the device does not have Google Play Services
  • On iOS, verify the device has network access and is signed in with a valid (sandbox or production) Apple ID
  • Always call endConnection when the app is closing or the IAP context is being torn down

Sandbox vs Production Differences#

  • iOS: Sandbox subscriptions renew at an accelerated rate (e.g., monthly subscription renews every 5 minutes). Production subscriptions renew at their normal interval.
  • Android: Test subscriptions have a shortened renewal period (default 5 minutes). The billing flow UI shows "Test card" options for license testers.
  • Receipt/purchase token formats may differ between sandbox and production — do not hard-code assumptions about their structure

iOS Sandbox Subscription Renewal Rates

ProductionSandbox
1 week3 minutes
1 month5 minutes
2 months10 minutes
3 months15 minutes
6 months30 minutes
1 year1 hour

References: Apple: Sandbox testing | Android: Test subscriptions

Framework-Specific Testing Notes#

React Native / Expo#

  • IAP must be tested on a real device. The iOS simulator has limited StoreKit functionality and Android emulators require a Google Play Store image.
  • For React Native CLI: cd libraries/react-native-iap/example && yarn ios (or yarn android)
  • For Expo: use a development build (npx expo run:ios) — Expo Go does not support native modules like IAP

Flutter#

  • Run flutter run on a connected real device for the best testing experience
  • The iOS simulator supports basic StoreKit testing with a local configuration file, but real-device testing is recommended
  • On Android, ensure the device or emulator has the Play Store installed

Godot#

  • In-app purchases cannot be tested in the Godot editor. You must export the project to a real device.
  • For Android: export an APK, sign it, and upload to an internal testing track
  • For iOS: export via Xcode and run on a physical device with a sandbox account

Kotlin Multiplatform#

  • Android: Use an emulator with a Google Play Store image (e.g., "Google APIs" system image) or a real device. Build with Gradle: ./gradlew :composeApp:assembleDebug
  • iOS: Open the iosApp/ directory in Xcode and run on a physical device. The simulator supports local StoreKit testing only.

References#

Apple

Google

OpenIAP