-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Description
I believe that the current implementation of the transaction handling on iOS (using product identifier as the key) creates issues when attempting to complete more than one queued transactions. This manifests as the following exception:
PlatformException(storekit_platform_invalid_transaction, The transaction with transactionIdentifer:(null) does not exist. Note that if the transactionState is purchasing, the transactionIdentifier will be nil(null).
The issue can be recreated when testing auto-renewable subscriptions. Creating a 1 year auto-renewing subscription, creates 6 events over the course of 6 hours in sandbox testing. When calling queryPastPurchases these 6 events are returned, however attempting to complete any more than 1 returns the exception above. When restarting the app, the remaining 5 transactions are sent to the purchaseUpdate handler. Of these, only one transaction can be completed, so the application needs to be restarted repeatedly to drain the list.
I was able to resolve the issue by changing the transaction handlers in packages/in_app_purchase/ios/Classes/FIAPaymentQueueHandler.m to use transaction.transactionIdentifier as the key with NSMutableDictionary<NSString *, SKPaymentTransaction *> *transactionsSetter.
The comments in the code helpfully point out that the product identifier is used because:
// Use product identifier instead of transaction identifier for few reasons:
// 1. Only transactions with purchased state and failed state will have a transaction id, it
// will become impossible for clients to finish deferred transactions when needed.
// 2. Using product identifiers can help prevent clients from purchasing the same
// subscription more than once by accident.
Would you consider having two NSMutableDictionary objects, one keyed on product identifier for transactions without an identifier and one keyed by transaction identifier if there is one?
Many thanks!