Search code examples
iosswiftin-app-purchasestorekitios16

Is it possible to test AppTransaction.originalAppVersion using TestFlight?


I would like to determine which app version the user first downloaded. For that, I'm using StoreKit and the originalAppVersion property of AppTransaction:

let verificationResult = try await AppTransaction.shared
switch verificationResult {
  case .verified(let appTransaction):
    return "\(appTransaction.originalAppVersion) (\(appTransaction.environment.rawValue))"
  case .unverified(let appTransaction, let verificationError):
  // The app transaction didn't pass StoreKit's verification.

The code runs fine, but always returns "1.0" for the app version and "Sandbox" for the environment. I tried debug/release builds and even pushed a build to TestFlight.

Is the only way to test this to push a new App Store version that should go live?


Solution

  • Yes, it seems that the sandbox always returns "1.0" for originalAppVersion, and TestFlight uses the sandbox (as does app review). On the other hand, StoreKit Testing in Xcode (using a StoreKit configuration file) always seems to return the current version set in your project. So the only time you get the "real original version" seems to be in production.

    I ran into this when developing a new version of my app which switched from a paid model to freemium, and wanted to automatically upgrade existing users to premium.

    I ended up testing the auto-upgrade logic by using the sandbox (where the "1.0" essentially always simulates an existing user), and using a StoreKit configuration file to test the case of a new user.

    However, another wrinkle is that, because Apple's reviewers use the sandbox, they always look like "existing users", so if your code hides the in-app purchase option in that case, they'll never get to see it and will reject your app as a result.

    So, to ensure the reviewers get the in-app purchase option, my code skips the auto-upgrade if the transaction is from the sandbox and it's not a Debug build. You can do this with an #if to check the compiler configuration, and then checking whether AppTransaction.shared.environment is .sandbox.

    It's a bit nerve-racking that there's no true end-to-end test with a real originalAppVersion before production, but I haven't found a way around this.