Is subscription autoRenewStatus in StoreKit2 working correctly with Sandbox testing?

It seems that subscription status gives different results with XCode testing and Sandbox testing.

I am using StoreKit2 to implement an IAP of an autorenewable subscription. I want to determine whether the subscription has been cancelled, so that the UI reflects that the subscription will stop after the expiry date and not be renewed.

the 'willAutoRenew' property of the subscription status renewalInfo seems to do exactly what is required, and works fine in XCode testing. My setup is very similar to the StoreKit demo associated with the WWDC21 session available here:

https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_a_store_in_your_app_using_the_storekit_api/

To demonstrate its use, add:

print(renewalInfo.willAutoRenew)

after line 79 of the SubscriptionsView in the demo project. When you run the app, and purchase a Standard Navigation assistance subscription, the console shows 'true'. If you then cancel the subscription in XCode (Debug:StoreKit:Manage Transactions), the console will show 'false' as expected

So far so good. My problem is that when I move to Sandbox testing, and cancel the subscription in another way (eg using the .manageSubscriptionsSheet view modifier, or in Settings:App Store:Sandbox Account), the willAutoRenew property remains true, even though the subscription is in fact cancelled (ie it disappears after the expiry date)

Does anyone know a workaround to determine cancellation status?

Replies

+1 on this issue and I'm also seeing very erratic behavior on these status changes.

Similarly, shouldn't a change in auto-renew status trigger a change via the subscription info's status updates stream? static var updates: Product.SubscriptionInfo.Status.Statuses { get } (https://developer.apple.com/documentation/storekit/product/subscriptioninfo/status/3851115-updates)

@eskimo wondered if you could weigh in on this status change for auto-renew? Thanks in advance.

I see exactly the same problem with "renewalInfo.willAutoRenew" in Sandbox, it doesn't update it's value to false when you cancel the subscription. Has anybody done a product release, does it work there (maybe only sandbox issue)?

try await AppStore.showManageSubscriptions(in: windowScene)
#if DEBUG
try await AppStore.sync()       // brute force fix (sync) to emulate behavior how it should be for debugging, don't do that in the release build
#endif
await storeKit2Service.updateSubscriptionStatus()

This state miss-match appears to be a result of StoreKit2 cacheing subscription info in a local database at: ../app_container/Library/Caches/StoreKit/receipts.db.

I was able to improve my flow by doing the following after displaying the manage subscriptions sheet.

  1. Clear the caches directory
  2. Fetch either the entitlement via Transaction.currentEntitlements or refresh a specific subscription group via Product.SubscriptionInfo.status(for:).

Example cache clear:

public func clearStoreKitReceiptsCache() throws {
    let fileManger = FileManager.default
    guard let cachesDir = fileManger.urls(for: .cachesDirectory, in: .userDomainMask).first else { return }
    guard let storeKitPath = try fileManger.contentsOfDirectory(
        at: cachesDir, 
        includingPropertiesForKeys: nil, 
        options: []).first(where: { $0.lastPathComponent == "StoreKit" }) else { return }
    try fileManger.removeItem(at: storeKitPath)
}

My experience with Sandbox testing is that subscription changes are sometimes significantly delayed. For example, sometimes if I cancel a subscription the cancellation doesn't take effect until much later than the subscription expiration time. If I just wait several minutes then the cancellation takes effect. I thought this might be due to Storekit caching so I've tried signing out and back in, removing the app, etc. but that doesn't seem to help.

So one suggestion: if the subscription status doesn't seem right, give it some more time and see if that fixes it.

  • I've checked willAutoRenew became false in my sandbox(testflight) environement. The answer saved me a lot of time! Thank you!

Add a Comment

Is there any news on this issue?