Search code examples
flutterdartin-app-purchase

On complete purchase i'm getting developer error such as response (In app purchase )


BillingResponse.developerError I/flutter ( 5091): Purchase is in an invalid state.

Sometimes i'm getting this error but i have cases when billing response is ok (BillingResponse.ok). What can be the problem? My code is following official example of flutter.dev which is https://pub.dev/packages/in_app_purchase Everything is good until this fragment of code

var completePurchase = await InAppPurchaseConnection.instance
              .completePurchase(purchaseDetails);

which returns BillingResponse.developerError or sometimes of magic returns BillingResponse.ok

In widget i just call buyNonConsumable

  instance.buyNonConsumable(prod);

Is there a chance to be because it is not in production or something else which is linked with the internal testing because the app is on internal test? In summary, the code looks like this

     _subscription = getPurchaseStream.listen(
        (purchaseDetailsList) {
          _listenToPurchaseUpdated(purchaseDetailsList);
        }, onDone: () {
      _subscription.cancel();
      }, onError: (error) {
        // handle error here.
        print('Subscription error: $error');
      });

    _isAvailable = await _connection.isAvailable();
    if(!_isAvailable) {
      print('The store is not available, try again later..');
      return;
    }
    _myProductsIds = await _categoryRepository.getCategoriesGoogleProductsIds(); 
    await _getProducts();
    await _getPastPurchases();
    for (PurchaseDetails purchase in _purchases) {
      verifyPurchase(purchase.productID);
      if (_isPurchased) {  //Check if product is purchased
        await deliverProduct(); // Give the products on the user
      } else {
         _handleInvalidPurchase(purchase);
      }
    }
 purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
      if (purchaseDetails.status == PurchaseStatus.pending) { 
        print('Pending..');
      } else {
        if (purchaseDetails.status == PurchaseStatus.error) {
         print('To purchases status error: ${purchaseDetails.error}');
        } else if (purchaseDetails.status == PurchaseStatus.purchased) {
          verifyPurchase(purchaseDetails.productID); // change value of _isPurchased
          if (_isPurchased) {
            _purchases.add(purchaseDetails);
     
            for(String id in _myProductsIds) {
              if (purchaseDetails.productID == id) {
                await deliverProduct(); // Give the products on the user
              }
            }
          } else {
            _handleInvalidPurchase(purchaseDetails);
            return;
          }
        }
        if (Platform.isAndroid) {
          for(String id in _myProductsIds) {
            if (purchaseDetails.productID == id) {
              await InAppPurchaseConnection.instance
                  .consumePurchase(purchaseDetails);
            }
          }
        }
        if (purchaseDetails.pendingCompletePurchase) {
          var completePurchase = await InAppPurchaseConnection.instance
              .completePurchase(purchaseDetails);
        }
      }

Solution

  • I don't know why in the official example there is consumePurchase, if the platform is android, but because of this fragment of code my application was crashing and it was returning an error 'Developer.error' in the important lines and they are

    var completePurchase = await InAppPurchaseConnection.instance
                  .completePurchase(purchaseDetails);
    

    I read the documentation of the completePurchase method and i saw important comment which reads:

      /// The [consumePurchase] acts as an implicit [completePurchase] on Android.
      Future<BillingResultWrapper> completePurchase(PurchaseDetails purchase);
    

    Maybe there was update on the version of in app purchases and after this the certain example is not has been updated.

    Link of an example: https://github.com/flutter/plugins/tree/master/packages/in_app_purchase/in_app_purchase/example