3

I do use : https://pub.dev/packages/in_app_purchase

The following code work perfectly on IOS real device but it cannot connect to Google Play store on Android.

IOS : working perfectly

Android : Stuck on line

 final bool available = await InAppPurchase.instance.isAvailable();

it load forever The isAvailable command never end. There is no error returned.

Future<void> _purchasePremiumInstallation(DateTime _premiumExpireDt) async {
    try {
      setState(() {
        widget.isLoadingPurchase = true;
      });
      setState(() {
        widget.error = 'good 1';
      });
      //in_app_purchase initialisation
      try {
        if (!kIsWeb) {
          setState(() {
            widget.error = 'good 2';
          });
          String productIdString = '';
          if (Platform.isIOS) productIdString = 'PremiumInstallation_1Y';
          if (Platform.isAndroid) productIdString = 'premiuminstallation_1y';
          print('in_app_payment : ' + productIdString);
          setState(() {
            widget.error = 'good 3';
          });
          final bool available = await InAppPurchase.instance.isAvailable();
          setState(() {
            widget.error = 'good 4';
          });
          if (!available) {
            print('ERROR in_app_purchase - Cannot connect to the store');
            setState(() {
              widget.isLoadingPurchase = false;
            });
            setState(() {
              widget.error = 'Error cannot connect to the store';
            });
            errorPopUp(
                context, 'ERROR in_app_purchase - Cannot connect to the store');
          }
          //first android then ios
          Set<String> _kIds = <String>{
            productIdString,
          };
          setState(() {
            widget.error = 'good 4';
          });
          final ProductDetailsResponse response =
              await InAppPurchase.instance.queryProductDetails(_kIds);
          setState(() {
            widget.error = 'good 5';
          });
          if (response.notFoundIDs.isNotEmpty) {
            print('Error in_app_purchase item id not found');
            setState(() {
              widget.isLoadingPurchase = false;
            });
            setState(() {
              widget.error = 'Error item not found';
            });
            errorPopUp(context, 'Error in_app_purchase item id not found');
          }
          List<ProductDetails> products = response.productDetails;
          print('in_app_purchase item found' + products.toString());
          setState(() {
            widget.error = 'good 6';
          });
          final ProductDetails productDetails =
              products.first; // Saved earlier from queryProductDetails().
          print('in_app_purchase product detail we are gonna buy is :' +
              productDetails.id);
          setState(() {
            widget.error = 'good 7';
          });
          final PurchaseParam purchaseParam =
              PurchaseParam(productDetails: productDetails);
          InAppPurchase.instance
              .buyConsumable(purchaseParam: purchaseParam, autoConsume: true);
          print('in_app_purchase completed');
          setState(() {
            widget.error = 'good 8';
          });
        }
      } catch (e) {
        print('Error catched for in_app_purchase : ' + e.toString());
        setState(() {
          widget.isLoadingPurchase = false;
        });
        setState(() {
          widget.error = e.toString();
        });
        errorPopUp(context, e.toString());
      }
    } on PlatformException catch (err) {
      errorPopUp(context, err).show();
      setState(() {
        widget.error = err.toString();
      });
    } catch (err) {
      errorPopUp(context, err).show();
      setState(() {
        widget.error = err.toString();
      });
    }
    setState(() {
      widget.isLoadingPurchase = false;
    });
  }

also i have that line on main - app init

if (defaultTargetPlatform == TargetPlatform.android) {
        InAppPurchaseAndroidPlatformAddition.enablePendingPurchases();
      }
Jason Simard
  • 103
  • 5
  • 18
  • InAppPurchase.instance.isAvailable() is a Future callback. Could you try adding catchError and onError on isAvailable to debugPrint any error thrown from the Future callback? I'm unable to replicate the same issue on InAppPurchase.instance.isAvailable() locally – Omatt Sep 23 '21 at 04:28
  • The line InAppPurchase.instance.isAvailable() doesn't throw any error. It run forever, no timeout or anything. That's pretty weird i think i am the only one with that problem on the web. It's only happening on Android. Work perfectly fine on ios – Jason Simard Sep 27 '21 at 13:04
  • 1
    This answer might help you, check it https://stackoverflow.com/a/56643449/11352456 – Rose Riyadh Sep 28 '21 at 09:46
  • did you solve this issue? right now i am facing same issue. – Himanshu Sharma Dec 22 '21 at 12:29
  • @HimanshuSharma no i finally used another plugin what about you – Jason Simard Feb 20 '22 at 22:07

2 Answers2

2

I had exactly the same problem. Removing the billing client implementation from the app-level build.gradle solved it. See this answer for details.

Ronald Blüthl
  • 311
  • 4
  • 9
0

Use the product ID of the subscription group and not the ID for the subscription duration.

See also: https://stackoverflow.com/a/74733040/5833548

MartinP
  • 47
  • 7