4

I'm implementing auto renewable subscriptions with StoreKit 2, but I'm getting transaction updates when a subscription expires. The idea is to update the purchased products when a subscription expires by listening to a hook. I'm testing this from Xcode by cancelling the subscription and waiting for the expiration to happen.

I'm using Transaction.updates for listening to transaction updates. I also used as a reference the Apple's project example for implementing in-app purchases.

This is the method for listening to transaction updates:

func listenForTransactions() -> Task<Void, Error> {
    return Task.detached {
        //Iterate through any transactions that don't come from a direct call to `purchase()`.
        for await result in Transaction.updates {
            do {
                let transaction = try self.checkVerified(result)
                
                //Deliver products to the user.
                await self.updateCustomerProductStatus()
                
                //Always finish a transaction.
                await transaction.finish()
            } catch {
                //StoreKit has a transaction that fails verification. Don't deliver content to the user.
                print("Transaction failed verification")
            }
        }
    }
}

and this one is for updating the purchased subscriptions:

@MainActor
func updateCustomerProductStatus() async {
    var purchasedProducts: [Product] = []
    
    // Iterate through all of the user's purchased products.
    for await result in Transaction.currentEntitlements {
        do {
            // Check whether the transaction is verified. If it isn’t, catch `failedVerification` error.
            let transaction = try checkVerified(result)
            
            // Check the `productType` of the transaction and get the corresponding product from the store.
            switch transaction.productType {
            case .autoRenewable:
                if let revocationDate = transaction.revocationDate {
                    //do nothing if transaction was revoked
                    print("Transaction was revoked on \(revocationDate)")
                    return
                } else if let expirationDate = transaction.expirationDate,
                            expirationDate < Date() {
                    // Do nothing, this subscription is expired.
                    return
                } else {
                    if let subscription = subscriptions.first(where: { $0.id == transaction.productID}) {
                        // Provide access to the product
                        purchasedProducts.append(subscription)
                    }
                }
            default:
                break
            }
        } catch {
            //storekit has a transaction that fails verification, don't delvier content to the user
            print("Failed - error retrieving products \(error)")
        }
    }
    //finally assign the purchased products
    self.purchasedSubscriptions = purchasedProducts
}

This means that updateCustomerProductStatus() has to be called manually to check whether a subscription is expired or not. I guess it could be because the expiration of a subscription is not considered a transaction update? If that's the case - Is there any other hook to listen to expirations?

3
  • 1
    I'm in the same case. Based on my experience (testing locally) Transaction.currentEntitlements may return an expired subscription... Which contradicts the documentation. Commented May 13, 2023 at 9:03
  • Any news on this ? Same issue here ! Commented Mar 1, 2024 at 10:07
  • Are there any updates regarding this? Transaction.currentEntitlements returns expired subscriptions. Also canceled suscriptions are not in transaction updates. Does anyone know how is this supposed to be handled because Apple's WWDC videos are not handling as they should Commented Mar 31 at 15:45

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.