Endre Olah
Endre Olah

Reputation: 955

autoRenewalPreference usage in StoreKit 2

I am facing a problem, that I cannot get the actually selected subscription product in my code. Apple is providing an easy way to get the currentEntitlements, which gives the actually active subscription.

The problem is that this methode does not provide info about any upgrade or downgrade information. So, if the user downgraded the subscription, he will still see the current active subscription, until it expired. Once it expired the method will deliver the right subscription product.

Theoretically there is a value "autoRenewalPreference", which should tell, what is the next renewal productid. But I cannot find, how to get this.

Any suggestion or code? Thanks

Upvotes: 0

Views: 42

Answers (1)

Endre Olah
Endre Olah

Reputation: 955

As it is described above the problem starts where you would like to show to the user which subscription service will be charged when the current subscription period expires. With the Transaction.currentEntitlements request, you will only get the actually running productID, which might not be renewed. So you need to get what will be charged next time.

The Apple documentation does not really gives too much hints.

So here is my solution:

func updatePurchasedProducts() async {
    var differentID = ""
    for await result in Transaction.currentEntitlements {
        guard case .verified(let transaction) = result else {
            continue
        }

        do {
            let products = try await Product.products(for: [transaction.productID])
            for product in products {
                do {
                    let productSubInfo = try await product.subscription?.status
                    for subInfo in productSubInfo! {
                        switch subInfo.renewalInfo {
                        case .verified(let prodStatus):
                            if (prodStatus.autoRenewPreference == transaction.productID) {
                                NSLog("Product is the same")
                            } else {
                                NSLog("Product is different : \(String(describing: prodStatus.autoRenewPreference))")
                                differentID = prodStatus.autoRenewPreference!
                            }
                            break
                        default:
                            break
                        }
                    }
                } catch {
                        
                }
            }
        } catch {
            // do nothing
        }
        
        self.purchasedProductIDs.removeAll()
        if transaction.revocationDate == nil {
            if !expired(transaction: transaction) {
                if (differentID == "") {
                    self.purchasedProductIDs.insert(transaction.productID)
                }
                else {
                    self.purchasedProductIDs.removeAll()
                    self.purchasedProductIDs.insert(differentID)
                }
            } else {
                self.purchasedProductIDs.remove(transaction.productID)
            }
        } else {
            self.purchasedProductIDs.remove(transaction.productID)
        }
    }
    
    subscriptionsPurchased = !self.purchasedProductIDs.isEmpty
    NSLog("Subscription count: \(self.purchasedProductIDs.count)")
    NotificationCenter.default.post(name: Notification.Name("UpdateTabBar"), object: nil)
    formdelegate?.PurchaseUpdated()
}

As you can see, it is not that simple. So a little explanation.

When you request Transaction.currentEntitlements, you get the current subscription active. (And/Or products purchased.) In my case, I have one subscription group with 3 subscription period, and my in-app products are consumables. So I just need to deal with the subscriptions downgrades and upgrades. Actually, downgrades gives the problem, as they become active only when the current current subscription period is expired.

If this is the case, Transaction.currentEntitlements will return 2 values, the active one and the next renewing one. So when you iterate through these purchase transaction, you need to check the status of the products, coverd by the transactions you have got back.

From the products, if they are subscriptions, you can check the subscription info's renewal statuses, one by one. If the autoRenewPreference value, which is a productID, is different from the productID from the currentEntitlements, than you know, that the user already changed the subscription plan.

At the end, you should make sure that the right productID is saved somewhere, as you need to show it on the right way to the Customer.

I hope, I could help with the code.

Upvotes: 0

Related Questions