purchase method
Make a purchase
If you want to know if the purchase is pending, listen to listenOnPendingPurchase
@returns true if UI is shown, false otherwise
Implementation
@override
Future<bool> purchase(dynamic productDetails) async {
makeSureIsInitialize();
if (_purchaseMethodOngoing || super.isPendingPurchase) {
LinkFiveLogger.e(
"Purchase was trigger but there is already a purchase in progress. Please make sure to only trigger it once");
return false;
}
// make sure this method is only triggered once.
_purchaseMethodOngoing = true;
ProductDetails? productDetailsProcessed;
if (productDetails is ProductDetails) {
productDetailsProcessed = productDetails;
}
if (productDetails is SubscriptionData) {
if (productDetails.productDetails != null && productDetails.productDetails is ProductDetails) {
productDetailsProcessed = productDetails.productDetails;
} else {
LinkFiveLogger.e(
"SubscriptionData.productDetails is null. Make sure to set `productDetails` when initializing the SubscriptionData.");
}
}
if (productDetailsProcessed == null) {
LinkFiveLogger.d("No ProductDetails to purchase found");
return false;
}
final purchaseParam = PurchaseParam(productDetails: productDetailsProcessed);
var showBuySuccess = false;
// We're saving the product Details whenever the user purchases a product to send it to the server
// after a purchase
_lastProductDetailsToPurchase = productDetailsProcessed;
try {
// try to buy it
LinkFiveLogger.d("Starting purchase process");
showBuySuccess = await inAppPurchaseInstance.buyNonConsumable(purchaseParam: purchaseParam);
} on PlatformException catch (e) {
LinkFiveLogger.e("PlatformException when trying to Purchase");
LinkFiveLogger.e(e);
if (Platform.isIOS) {
/// Exception could be:
/// Unhandled Exception: PlatformException(storekit_duplicate_product_object, There is a pending transaction for the same product identifier. Please either wait for it to be finished or finish it manually using `completePurchase` to avoid edge cases., {applicationUsername: null, requestData: null, quantity: 1, productIdentifier: quarterly_pro_2020_4, simulatesAskToBuyInSandbox: false}, null)
// https://github.com/flutter/flutter/issues/60763#issuecomment-769051089
// try to clear the transactions
LinkFiveLogger.d("Finish previous transactions");
var transactions = await SKPaymentQueueWrapper().transactions();
for (SKPaymentTransactionWrapper transactionWrapper in transactions) {
LinkFiveLogger.d("Pending transaction: state=${transactionWrapper.transactionState}");
if (transactionWrapper.transactionState != SKPaymentTransactionStateWrapper.purchasing) {
LinkFiveLogger.d("Pending transaction: finishTransaction");
try {
await SKPaymentQueueWrapper().finishTransaction(transactionWrapper);
} catch (e) {
LinkFiveLogger.e("Tried to finish transaction, but got an unexpected error");
LinkFiveLogger.e(e);
}
}
}
}
showBuySuccess = false;
} catch (e) {
LinkFiveLogger.e("Tried to buy a product, but got an unexpected error.");
LinkFiveLogger.e(e);
showBuySuccess = false;
}
LinkFiveLogger.d("Show Buy Intent success: $showBuySuccess");
// set Pending Purchase. this will notify all listeners
if (showBuySuccess) {
super.isPendingPurchase = true;
}
_purchaseMethodOngoing = false;
return showBuySuccess;
}