Search Unity

OnInitializeFailed InitializationFailureReason:NoProductsAvailable

Discussion in 'Unity IAP' started by SUUNE, Sep 29, 2019.

  1. SUUNE

    SUUNE

    Joined:
    Mar 10, 2019
    Posts:
    65
    Hello.
    I don't really know what to do and how to fix this. This is my first time implementing IAP, I used this tutorial
    to set this up.
    My Code:

    manager:

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.Purchasing;
    6. public class IAPManager : Singleton<IAPManager>, IStoreListener
    7. {
    8.    
    9.     private static IStoreController m_StoreController;          // The Unity Purchasing system.
    10.     private static IExtensionProvider m_StoreExtensionProvider; // The store-specific Purchasing subsystems.
    11.  
    12.  
    13.     public string GetKey = "getkey";
    14.     public string No_ADS = "no_ads";
    15.  
    16.  
    17.     void Start()
    18.     {
    19.        
    20.         if (m_StoreController == null)
    21.         {
    22.            
    23.             InitializePurchasing();
    24.         }
    25.     }
    26.  
    27.     public void InitializePurchasing()
    28.     {
    29.        
    30.         if (IsInitialized())
    31.         {
    32.            
    33.             return;
    34.         }
    35.  
    36.      
    37.         var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
    38.  
    39.      
    40.         builder.AddProduct(GetKey, ProductType.Consumable);
    41.      
    42.         builder.AddProduct(No_ADS, ProductType.NonConsumable);
    43.  
    44.      
    45.         UnityPurchasing.Initialize(this, builder);
    46.     }
    47.  
    48.  
    49.     public bool IsInitialized()
    50.     {
    51.      
    52.         return m_StoreController != null && m_StoreExtensionProvider != null;
    53.     }
    54.  
    55.  
    56.     public void BuyKey()
    57.     {
    58.      
    59.         BuyProductID(GetKey);
    60.     }
    61.  
    62.  
    63.     public void BuyNo_ADS()
    64.     {
    65.    
    66.         BuyProductID(No_ADS);
    67.     }
    68.  
    69.     public string GetProductPriceFromStore(string id)
    70.     {
    71.         if (m_StoreController != null && m_StoreController.products != null)
    72.             return m_StoreController.products.WithID(id).metadata.localizedPriceString;
    73.         else
    74.             return "";
    75.     }
    76.  
    77.  
    78.     void BuyProductID(string productId)
    79.     {
    80.      
    81.         if (IsInitialized())
    82.         {
    83.            
    84.          
    85.             Product product = m_StoreController.products.WithID(productId);
    86.  
    87.          
    88.             if (product != null && product.availableToPurchase)
    89.             {
    90.                 Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
    91.            
    92.                 m_StoreController.InitiatePurchase(product);
    93.             }
    94.             // Otherwise ...
    95.             else
    96.             {
    97.          
    98.                 Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
    99.             }
    100.         }
    101.  
    102.         else
    103.         {
    104.          
    105.             Debug.Log("BuyProductID FAIL. Not initialized.");
    106.         }
    107.     }
    108.  
    109.  
    110.  
    111.  
    112.  
    113.  
    114.     //
    115.     // --- IStoreListener
    116.     //
    117.  
    118.     public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    119.     {
    120.         // Purchasing has succeeded initializing. Collect our Purchasing references.
    121.         Debug.Log("OnInitialized: PASS");
    122.  
    123.         // Overall Purchasing system, configured with products for this application.
    124.         m_StoreController = controller;
    125.         // Store specific subsystem, for accessing device-specific store features.
    126.         m_StoreExtensionProvider = extensions;
    127.     }
    128.  
    129.  
    130.     public void OnInitializeFailed(InitializationFailureReason error)
    131.     {
    132.         // Purchasing set-up has not succeeded. Check error for reason. Consider sharing this reason with the user.
    133.         Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
    134.     }
    135.  
    136.  
    137.     public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    138.     {
    139.         // A consumable product has been purchased by this user.
    140.         if (String.Equals(args.purchasedProduct.definition.id, GetKey, StringComparison.Ordinal))
    141.         {
    142.             Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    143.             // The consumable item has been successfully purchased, add 100 coins to the player's in-game score.
    144.             GameManager.Instance.StoreGetKey();
    145.         }
    146.         // Or ... a non-consumable product has been purchased by this user.
    147.         else if (String.Equals(args.purchasedProduct.definition.id, No_ADS, StringComparison.Ordinal))
    148.         {
    149.             Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    150.             GameManager.Instance.StoreNoAds();
    151.         }
    152.         // Or ... a subscription product has been purchased by this user.
    153.    
    154.         // Or ... an unknown product has been purchased by this user. Fill in additional products here....
    155.         else
    156.         {
    157.             Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
    158.         }
    159.  
    160.         // Return a flag indicating whether this product has completely been received, or if the application needs
    161.         // to be reminded of this purchase at next app launch. Use PurchaseProcessingResult.Pending when still
    162.         // saving purchased products to the cloud, and when that save is delayed.
    163.         return PurchaseProcessingResult.Complete;
    164.     }
    165.  
    166.  
    167.     public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    168.     {
    169.         // A product purchase attempt did not succeed. Check failureReason for more detail. Consider sharing
    170.         // this reason with the user to guide their troubleshooting actions.
    171.         Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
    172.     }
    173. }
    and here is script on store buttons:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using TMPro;
    5. public class StoreButton : MonoBehaviour
    6. {
    7.     public enum ItemType
    8.     {
    9.         GetKey,
    10.         NoAds
    11.     }
    12.  
    13.     public ItemType itemType;
    14.     public TextMeshProUGUI priceText;
    15.     private string defaultText;
    16.  
    17.  
    18.     void Start()
    19.     {
    20.         defaultText = priceText.text;
    21.         StartCoroutine(LoadPriceRoutine());
    22.     }
    23.  
    24.     public void ClickBuy()
    25.     {
    26.         switch (itemType)
    27.         {
    28.             case ItemType.GetKey:
    29.                 IAPManager.Instance.BuyKey();
    30.                 break;
    31.             case ItemType.NoAds:
    32.                 IAPManager.Instance.BuyNo_ADS();
    33.                 break;
    34.         }
    35.     }
    36.  
    37.     private IEnumerator LoadPriceRoutine()
    38.     {
    39.         while (!IAPManager.Instance.IsInitialized())
    40.             yield return null;
    41.         string loadedPrice = "";
    42.         switch (itemType)
    43.         {
    44.             case ItemType.GetKey:
    45.                 loadedPrice = IAPManager.Instance.GetProductPriceFromStore(IAPManager.Instance.GetKey);
    46.                 break;
    47.             case ItemType.NoAds:
    48.                 loadedPrice = IAPManager.Instance.GetProductPriceFromStore(IAPManager.Instance.No_ADS);
    49.                 break;
    50.         }
    51.  
    52.         priceText.text = defaultText + "" + loadedPrice;
    53.     }
    54.  
    55.  
    56. }

    - Product IDs match with those from script.
    - I waited 24h
    - first check on dev acc, than check on tester acc, both same results in logcat
    - ofc everything works in editor
    - unity dashboard see that there are IAP set on google dev console with correct names.(edit - dashboard have under Platform column "Windows editor" so I guess it's not recognized.
    - tested on real devices, 3 phones and 1 tablet
    edit:
    - I added product ID's to the Unity dashboard under Monetization - In-app purchases, I don't know I should do it but it's only idea I've got so far.
    - Unity version - 2018.3.11f1
    - UnityIAP ver 1.22.0

    I don't really know where to start and what can I do now.
    Please help.

    edit.
    btw. why all knowleage base and tutorials screenshots comes from old version of google dev console? Is it really that hard to update them to the current look? I know, everything is "findable" but implementing everything in Google Console is already very confusing so making it even more not-clear isn't help anyone.
     

    Attached Files:

    Last edited: Sep 30, 2019
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Except for the good luck comment, you need to define your products on the Google Developer dashboard. This link is a bit outdated, but should get you started. https://docs.unity3d.com/Manual/UnityIAPGoogleConfiguration.html
     
  3. SUUNE

    SUUNE

    Joined:
    Mar 10, 2019
    Posts:
    65
    Ok, didnt said that... Ofcourse I did it. Second part of the tutorial I posted I did too... Everything is set up from google dev console side.
    (Oh noooo... And again I will have to wait for reply 2 days :( )
     
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    So like Wednesday? Got it! :)
     
  5. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    So in the meantime while you're waiting, please provide a screenshot of your products defined on Google Play. The error says can't find product GetKey, but you have it defined as getkey in your code.
     
  6. SUUNE

    SUUNE

    Joined:
    Mar 10, 2019
    Posts:
    65
    I hope polish language isn't a problem for you ;)
     

    Attached Files:

  7. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Why are you requesting GetKey and not getkey? See the logs. Also, I might politely suggest, sarcasm is not in your best interest when someone is trying to help you. Regarding your 2 day comment, I generally don't watch the forums on my days off.
     
  8. SUUNE

    SUUNE

    Joined:
    Mar 10, 2019
    Posts:
    65
    Do you mean my code should look like this?
    Code (CSharp):
    1. public string getkey = "getkey";
    or I should change name of the request in google dev console?

    Ok, I will not use sarcasm anymore. ;)
     
  9. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    No, you need to find out why your program is calling as GetKey and not getkey. Your method signature is as follows:
    Code (CSharp):
    1.  public void BuyKey()
    2.     {
    3.    
    4.         BuyProductID(GetKey);
    5.     }
    6.  
    You are passing a global variable to a method. I would not do that. Use Debug.Log to confirm the string you are actually sending.
     
  10. SUUNE

    SUUNE

    Joined:
    Mar 10, 2019
    Posts:
    65
    What you mean by "I would not do that" ? This script is copied from here https://learn.unity.com/tutorial/unity-iap and look exactly the same.
    And maybe it's a lame question but how I should "use" Debug.log to confirm the string I'm sending ?
     
  11. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    I can't comment on the tutorial video. But I would suggest

    Code (CSharp):
    1. void BuyProductID(string productId)
    2. {
    3.   Debug.Log ("My product is " + productId.ToString());
    4. ...
    This will show in the device logs, or in the Unity Console. But you'll want to test on a device, and capture the device logs. Debug.Log will show in the logs. https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/
     
  12. SUUNE

    SUUNE

    Joined:
    Mar 10, 2019
    Posts:
    65
    Why you can't comment on the tutorial video? If it's bad, and I shouldn't use it maybe it's better to get rid of this scripts and just create a proper one? I don't have programistic background so my code are mostly copy-paste and in most cases I can handle problems but if Unity or Google services are in play I don't really know what I'm doing.
    (I was sure this tutorial will be good - it's a new wave - robotic hindi - just can't be bad)
     
  13. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    I simply meant that I can't comment because I didn't write it, was my point. Please follow my suggestions, and provide the output of Debug.Log. It is likely just a small syntax error in your C# code.
     
  14. SUUNE

    SUUNE

    Joined:
    Mar 10, 2019
    Posts:
    65
    Ok, did what you said... I hope it is not a problem that I upload it as internal test (alpha test is like 12h waiting these days) and use my account.
     

    Attached Files:

  15. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    You have other problems, note "NullReferenceException: Object reference not set to an instance of an object." So you are not initializing, and there is a null object in your code that you'll need to find via Debug.Log. Please show the code now that you've added the additional Debug.Log statement, and where you see it in the logs. And there is no "My product is..." in the logs, so that part of the code never executed.
     
    Last edited: Sep 30, 2019
  16. SUUNE

    SUUNE

    Joined:
    Mar 10, 2019
    Posts:
    65
    I add to the script that store button is disabled on initialization failed... hmm... I didn't test it because its always pass initialization in editor

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.Purchasing;
    6. public class IAPManager : Singleton<IAPManager>, IStoreListener
    7. {
    8.    
    9.     private static IStoreController m_StoreController;          // The Unity Purchasing system.
    10.     private static IExtensionProvider m_StoreExtensionProvider; // The store-specific Purchasing subsystems.
    11.  
    12.  
    13.     public string GetKey = "getkey";
    14.     public string No_ADS = "no_ads";
    15.    
    16.  
    17.     void Start()
    18.     {
    19.        
    20.         if (m_StoreController == null)
    21.         {
    22.            
    23.             InitializePurchasing();
    24.         }
    25.     }
    26.  
    27.     public void InitializePurchasing()
    28.     {
    29.        
    30.         if (IsInitialized())
    31.         {
    32.            
    33.             return;
    34.         }
    35.  
    36.        
    37.         var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
    38.  
    39.      
    40.         builder.AddProduct(GetKey, ProductType.Consumable);
    41.      
    42.         builder.AddProduct(No_ADS, ProductType.NonConsumable);
    43.    
    44.        
    45.         UnityPurchasing.Initialize(this, builder);
    46.     }
    47.  
    48.  
    49.     public bool IsInitialized()
    50.     {
    51.        
    52.         return m_StoreController != null && m_StoreExtensionProvider != null;
    53.     }
    54.  
    55.  
    56.     public void BuyKey()
    57.     {
    58.      
    59.         BuyProductID(GetKey);
    60.     }
    61.  
    62.  
    63.     public void BuyNo_ADS()
    64.     {
    65.        
    66.         BuyProductID(No_ADS);
    67.     }
    68.  
    69.     public string GetProductPriceFromStore(string id)
    70.     {
    71.         if (m_StoreController != null && m_StoreController.products != null)
    72.             return m_StoreController.products.WithID(id).metadata.localizedPriceString;
    73.         else
    74.             return "";
    75.     }
    76.  
    77.  
    78.     void BuyProductID(string productId)
    79.     {
    80.         Debug.Log("My product is " + productId.ToString());
    81.    
    82.         if (IsInitialized())
    83.         {
    84.        
    85.             Product product = m_StoreController.products.WithID(productId);
    86.  
    87.            
    88.             if (product != null && product.availableToPurchase)
    89.             {
    90.                 Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
    91.            
    92.                 m_StoreController.InitiatePurchase(product);
    93.             }
    94.             // Otherwise ...
    95.             else
    96.             {
    97.                
    98.                 Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
    99.             }
    100.         }
    101.      
    102.         else
    103.         {
    104.      
    105.             Debug.Log("BuyProductID FAIL. Not initialized.");
    106.         }
    107.     }
    108.  
    109.  
    110.  
    111.  
    112.  
    113.  
    114.  
    115.     public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    116.     {
    117.  
    118.         Debug.Log("OnInitialized: PASS");
    119.  
    120.        
    121.         m_StoreController = controller;
    122.      
    123.         m_StoreExtensionProvider = extensions;
    124.     }
    125.  
    126.  
    127.     public void OnInitializeFailed(InitializationFailureReason error)
    128.     {
    129.        
    130.         Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
    131.         MenuScript.Instance.StoreButton.SetActive(false);
    132.     }
    133.  
    134.  
    135.     public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    136.     {
    137.        
    138.         if (String.Equals(args.purchasedProduct.definition.id, GetKey, StringComparison.Ordinal))
    139.         {
    140.             Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    141.        
    142.             GameManager.Instance.StoreGetKey();
    143.         }
    144.      
    145.         else if (String.Equals(args.purchasedProduct.definition.id, No_ADS, StringComparison.Ordinal))
    146.         {
    147.             Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
    148.             GameManager.Instance.StoreNoAds();
    149.         }
    150.      
    151.         else
    152.         {
    153.             Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
    154.         }
    155.  
    156.    
    157.         return PurchaseProcessingResult.Complete;
    158.     }
    159.  
    160.  
    161.     public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    162.     {
    163.  
    164.         Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
    165.     }
    166. }
     
  17. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  18. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Yes, we use a fake store in the Editor that always initializes successfully (as long as there are no errors in your code)
     
  19. SUUNE

    SUUNE

    Joined:
    Mar 10, 2019
    Posts:
    65
    there is "My product is.."
    (Filename: ./Runtime/Export/Debug.bindings.h Line: 45)
    09-30 20:50:40.974 25377-25398/? I/Unity: My product is GetKey
    IAPManager:BuyProductID(String)
    UnityEngine.Events.UnityEvent:Invoke()
    UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
    UnityEngine.EventSystems.StandaloneInputModule:processTouchPress(PointerEventData, Boolean, Boolean)
    UnityEngine.EventSystems.StandaloneInputModule:processTouchEvents()
    UnityEngine.EventSystems.StandaloneInputModule:process()

    (Filename: ./Runtime/Export/Debug.bindings.h Line: 45)
    09-30 20:50:40.985 25377-25398/? I/Unity: BuyProductID FAIL. Not initialized.
    UnityEngine.Events.UnityEvent:Invoke()
    UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction`1)
    UnityEngine.EventSystems.StandaloneInputModule:processTouchPress(PointerEventData, Boolean, Boolean)
    UnityEngine.EventSystems.StandaloneInputModule:processTouchEvents()
    UnityEngine.EventSystems.StandaloneInputModule:process()
     
  20. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    There you go. Your product is named getkey and not GetKey. I see two possible solutions, one to fix your code, and other to simply change the product name on the Google Dashboard (which I would not advise as it would only mask your bug)
     
  21. SUUNE

    SUUNE

    Joined:
    Mar 10, 2019
    Posts:
    65
    sooo... where I should type getkey instead of GetKey :| ?
     
  22. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    So this is basic C# and not specific to IAP. If you are having problems with variables, just hard code the product name in quotes where you need it. But the correct approach would be to add additional debug statements and find out yourself. I might also recommend some basic C# training first.
     
  23. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Point taken on editing on replied posts. And you're welcome (I think, I'm not sure if you're been sarcastic again). I offered several tips, it's up to you at this point to follow my suggestions or not. I mentioned one very easy solution. Edit: make that two easy solutions: hard code the productID or change the product name on Google.
     
  24. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    That is incorrect. You have it defined as getkey (lowercase) but you are passing GetKey (note the difference, it is case sensitive). So you can either hard code the correct case, or change it on the Dashboard. Simply put, the error logs say "No product named GetKey", so make one!
     
  25. Huriyasoft

    Huriyasoft

    Joined:
    Jun 24, 2016
    Posts:
    5
    @JeffDUnity3D
    OnInitializeFailed InitializationFailureReasonpurchasingUnavailableGoogleBillingResponseCode: BillingUnavailable

    I am using Unity 2022.2.9 and IAP version 4.8.0

    Any solution will be appreciated
     
    Last edited: May 24, 2023
  26. Yannick_D

    Yannick_D

    Unity Technologies

    Joined:
    Feb 21, 2022
    Posts:
    231
  27. Huriyasoft

    Huriyasoft

    Joined:
    Jun 24, 2016
    Posts:
    5