Flutter Android: Unable to fetch in-app products from Google Play

220

The issue has finally been solved. You need to call InAppPurchase method, isAvailable(), before queryProductDetails() when on the Android platform. I'm not sure why you don't need to do the same when on the IOS platform.

The documentation didn't specify the need for this outright, but let it stand that querying for products AFTER checking if the store is available fixed my issue on Android.

Share:
220
desap
Author by

desap

Updated on January 04, 2023

Comments

  • desap
    desap 10 months

    I'm currently facing an issue where my Flutter application is unable to fetch consumable in-app products from Google Play store. However, my application is able to fetch all products from the Apple app store.

    I can't identify what step I'm missing or what is causing all of my product ids to be not found. I'm using flutter's in_app_purchase module to facilitate in app purchases.

    For Android, here are the setup steps I've taken.

    1. I've setup my Google Play Console and Developer Account
    2. Completed all the tasks in the Set up your app section
    3. Generated a keystore file to sign my app keytool -genkey -v -keystore c:\Users\USER_NAME\key.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias key
    4. Created a file named /android/key.properties that contains a reference to my keystore file. The contents of this file look like the following:
    storePassword=<password from previous step>
    keyPassword=<password from previous step>
    keyAlias=key
    storeFile=<location of the key store file, such as /Users/<user name>/key.jks>
    
    1. Configured my build.gradle file to include the following
    def keystoreProperties = new Properties()
    def keystorePropertiesFile = rootProject.file('key.properties')
    if (keystorePropertiesFile.exists()) {
       keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
    }
    android {
       signingConfigs {
           release {
               keyAlias keystoreProperties['keyAlias']
               keyPassword keystoreProperties['keyPassword']
               storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
               storePassword keystoreProperties['storePassword']
           }
       }
       buildTypes {
           release {
               signingConfig signingConfigs.release
           }
       }
    }
    
    1. Created a app bundle and published it under the closed track flutter build appbundle --flavor prod --release. I also let google sign my app "Google signing the app" when I was uploading the artifact.

    2. I've added a tester that is not associated with the developer account and added the same email under "License testing" with the License response "RESPOND_NORMALLY".

    3. I've also created three consumable products and set them to active.

    The following shows my code that fetches products

      List<String> _kProductIds = <String>[
        'my_app_premium_year_c',
        'my_app_premium_month_c',
        'my_app_premium_week_c'
      ];
    final ProductDetailsResponse productResponse =
            await InAppPurchase.instance.queryProductDetails(_kProductIds.toSet());
    

    The following shows the unexpected results I'm getting. That is all of my products are in the notFoundIDs list. [my_app_premium_year_c, my_app_premium_month_c, my_app_premium_week_c]

    I expect the notFoundIDs list to be empty when including the following code print("ProductIDs not found: ${productResponse.notFoundIDs}");

    Any hints or suggestions would be much appreciated.

    EDIT: The following screenshot shows my in-app products page on the google console. I've covered up certain identifiers to protect my privacy, however the product ids in the screenshot match the product ids in my code. in-app-products

    The following screenshot shows my app published under the alpha, closed track. alpha track

    • ch271828n
      ch271828n over 1 year
      is your productid name correct? what about a screenshot
    • desap
      desap over 1 year
      Yes it's correct. It matches exactly for all three products.
    • ch271828n
      ch271828n over 1 year
      could you please provide some screenshots of google console
    • desap
      desap over 1 year
      @ch271828n Updated with a screenshot.
    • desap
      desap over 1 year
      My app isn't even able to find the product with ID android.test.purchased. Isn't this product automatically configured and available?
    • ch271828n
      ch271828n over 1 year
      hmm could you please use network tools to examine the network traffic? (even if you use https there are some tools to decrypt it; or intercept the flutter HttpClient etc). Please paste the raw network traffic (possibly HTTP request and response) here to see what is indeed sent to google
    • desap
      desap over 1 year
      Does it matter that the in app products were created before the first bundle was uploaded to the test track?
    • ch271828n
      ch271828n over 1 year
      I am not sure. Why I talk about network traffic is that, you are using a wrapped API (the InAppPurchase), which can have subtle bugs. So we need to examine the raw data (raw HTTP request) that sends to google
    • desap
      desap over 1 year
      Ok makes sense. Always the chance for bugs but it might be important to know it's a first party library, officially supported by Flutter. Anyway, I was able to collect quite a few packets sent between google play and my app via wireshark. I've saved the packets using the DNS protocol and the subsequent packets using QUIC protocol. I'm not sure how to extract much information out of these packets though.
    • ch271828n
      ch271828n over 1 year
      Well it should be HTTP/HTTPS. Search about it - how to extract https
    • Mukund Jogi
      Mukund Jogi over 1 year