-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Description
I'm using the latest in_app_purchase plugin (0.3.4+8).
According to documentation on iOS all error purchaseses need to be completed by calling InAppPurchaseConnection.instance.completePurchase.
Steps to reproduce:
-
On iOS 14.0 invoke a consumable in-app:
InAppPurchaseConnection.instance.buyConsumable -
Wait for the system dialog for approving the payment.
-
Don't approve the payment, hit the Cancel button to interrupt the in-app process.
-
Step 3 generates an error state for the Purchase and the Purchase is returned in
InAppPurchaseConnection.instance.purchaseUpdatedStream. The underlyingSKPaymentTransactionWrapper(used by thePurchaseDetailsclass) containstransactionIdentifierwhich is later used byInAppPurchaseConnection.instance.completePurchasemechanism to complete the purchase.
According to the documentation in src/store_kit_wrappers/sk_payment_transaction_wrappers.dart
The unique string identifer of the transaction.
It is only defined when the [transactionState] is
[SKPaymentTransactionStateWrapper.purchased] or
[SKPaymentTransactionStateWrapper.restored]. You may wish to record this
string as part of an audit trail for App Store purchases. The value of
this string corresponds to the same property in the receipt.
This is not true, transactionIdentifier is returned for error Purchases as well because it is needed by the undelaying mechanisms to complete the transactions (see SKPaymentQueueWrapper.finishTransaction in src/store_kit_wrappers/sk_payment_queue_wrapper.dart). This worked well until iOS 14.0 was released. Now hitting Cancel button in step 3 throws en exception:
<SKPaymentQueue: 0x280050d90>: Payment completed with error: Error Domain=ASDErrorDomain Code=907 "Unhandled exception" UserInfo={NSUnderlyingError=0x280ca7a50 {Error Domain=AMSErrorDomain Code=6 "Payment Sheet Failed" UserInfo={NSLocalizedDescription=Payment Sheet Failed, NSLocalizedFailureReason=Payment sheet cancelled}}, NSLocalizedFailureReason=An unknown error occurred, NSLocalizedDescription=Unhandled exception}
and the returned PurchaseDetails class (or more precisely the underlaying SKPaymentTransactionWrapper) contains no transactionIdentifier (it is null):
skPaymentTransaction: {transactionState: 2, payment: {productIdentifier: XXX, applicationUsername: null, requestData: null, quantity: 1, simulatesAskToBuyInSandbox: false}, originalTransaction: null, transactionTimeStamp: null, transactionIdentifier: null, error: Instance of 'SKError'}
Now trying to call InAppPurchaseConnection.instance.completePurchase while the transactionIdentifier of the underlaying SKPaymentTransactionWrapper is null throws an exception:
[VERBOSE-2:ui_dart_state.cc(166)] Unhandled Exception: PlatformException(storekit_invalid_argument, Argument type of finishTransaction is not a string., null)
#0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:572:7)
#1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:161:18)
<asynchronous suspension>
#2 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:334:12)
#3 SKPaymentQueueWrapper.finishTransaction (package:in_app_purchase/src/store_kit_wrappers/sk_payment_queue_wrapper.dart:106:19)
#4 AppStoreConnection.completePurchase (package:in_app_purchase/src/in_app_purchase/app_store_connection.dart:68:10)
I believe there may be some problem processing error Purchases on iOS 14 thus not getting their transactionIdentifiers.