AppActor integrations should be tested in real store environments before launch. The SDK layer, your catalog, and the store itself can all be valid independently while the full purchase flow is still broken.

Test in the real store path

  • iOS should be tested with StoreKit local testing for quick iteration and with Apple sandbox or TestFlight for real account and receipt behavior
  • Android should be tested with license testers and an internal testing track in Google Play
  • Flutter and React Native should be tested through the underlying native store paths on each platform, not only through mocked Dart or JavaScript state

Store-backed recipe

  1. Create the fake-safe catalog shape from Catalog Setup: premium, default, monthly, annual.
  2. Configure the app with the platform’s public app SDK key.
  3. Fetch offerings and verify the current offering has packages.
  4. Render package cards using localized store prices.
  5. Purchase monthly and verify hasActiveEntitlement("premium").
  6. Cancel or expire in the sandbox and verify access changes.
  7. Reinstall and test restore or sync behavior.
  8. Test empty offering, missing product, pending purchase, and flaky-network paths.
  9. Confirm the purchase appears in the AppActor dashboard customer or transaction view.
  10. Confirm Apple notification health, Google RTDN health, and outbound webhook delivery if your backend uses webhooks.

Validate the catalog first

Before you debug app code, confirm:
  • the app is using the expected public pk_... key
  • the current offering exists
  • the package slots your paywall reads are actually populated
  • those packages map to real store products on the target platform
  • the products unlock the entitlement keys your app checks after purchase

High-value scenarios to test

Run these on every platform you support:
  1. Fresh install, configure, fetch offerings, and render a paywall.
  2. Purchase from the current offering and verify the expected entitlement unlocks.
  3. Re-open the app and confirm customer state restores without duplicate purchase UI.
  4. Reinstall, then validate your restore or sync path.
  5. If your app supports anonymous purchase then login, verify the identity transition explicitly.
  6. Test offline or flaky-network launch behavior if your app depends on cached offerings or offline entitlement decisions.

Recovery flows deserve dedicated testing

Do not treat these as interchangeable:
  • restorePurchases()
  • syncPurchases()
  • explicit queue-drain recovery APIs
Your QA plan should prove that each one is wired to the right user or operational flow.

Pre-release checklist

Before go-live, verify:
  • the production key and production catalog are selected
  • the paywall can render when offerings are present
  • premium access is gated from customer entitlements, not local UI state
  • cancellation, renewal, or expired-access behavior is visible in the app state you use
  • support or settings surfaces expose the correct recovery path
  • Apple App Store Server Notifications are healthy for the iOS app
  • Google RTDN is healthy for the Android app
  • outbound webhooks verify X-AppActor-Signature and dedupe by eventId
  • refund, renewal, cancellation, grace, billing retry, and expiration scenarios have dashboard evidence

Go-live evidence matrix

Use this table as the release gate. A row is not done until the SDK result, dashboard evidence, notification or webhook evidence, and owner are all filled in.

Use the example apps and tests as support material

Each SDK repo still contains useful reference material:
  • iOS package UI: Examples/AppActorExample/AppActorExample/Features/Offerings/PackageRow.swift
  • iOS purchase and restore flows: Examples/AppActorExample/AppActorExample/Features/Offerings
  • Android offerings UI: app/src/main/java/com/appactor/example/ui/Features/Offerings/OfferingsTab.kt
  • Flutter package card: example/lib/widgets/package_card.dart
  • Flutter purchase controls: example/lib/screens/home/home_screen.dart
  • React Native offerings and purchase section: example/src/App.tsx
Those examples are excellent debugging references, but they are not a substitute for store-backed release testing in your own app.

Sandbox-specific checks