purchase method

  1. @override
Future<bool> purchase(
  1. dynamic productDetails
)
override

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;
}