[Android] Unity IAP "Purchase failed because Purchasing was not initialized correctly"

What I have

IAP button is working perfectly in unity editor. After purchasing, i’m getting debug message “ProcessPurchase: PASS. Product: ‘full_version’” . But the button does nothing when I try to make a purchase on the device.

Don’t have any errors when purchasing product in editor

What have i done so far

  • Automatically initialize UnityPurchasing checkbox is switched ON
  • I’ve checked that the product ID, and price are the same in unity and Play console
  • My IAP product is showing active in play console
  • setup the Codeless IAP like this

LogCat error when I press the button on the device
~~~csharp
2022-03-14 20:08:18.244 9293-9334/? E/Unity: Purchase failed because Purchasing was not initialized correctly
UnityEngine.Purchasing.CodelessIAPStoreListener:InitiatePurchase(String)
UnityEngine.Events.UnityAction:Invoke()
UnityEngine.Events.UnityEvent:Invoke()
UnityEngine.EventSystems.EventFunction1:Invoke(T1, BaseEventData) UnityEngine.EventSystems.ExecuteEvents:Execute(GameObject, BaseEventData, EventFunction1)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchPress(PointerEventData, Boolean, Boolean)
UnityEngine.EventSystems.StandaloneInputModule:ProcessTouchEvents()
UnityEngine.EventSystems.StandaloneInputModule:Process()

~~~
IAP script
```csharp
**using System;
using UnityEngine;
using UnityEngine.Purchasing; //библиотека с покупками, будет доступна когда активируем сервисы

public class IAP : MonoBehaviour, IStoreListener //для получения сообщений из Unity Purchasing
{

private static IStoreController m_StoreController;          //доступ к системе Unity Purchasing
private static IExtensionProvider m_StoreExtensionProvider; // подсистемы закупок для конкретных магазинов

public static string fullVersion = "full_version";


void Start()
{
    if (m_StoreController == null) //если еще не инициализаровали систему Unity Purchasing, тогда инициализируем
    {
        InitializePurchasing();
    }

}

public void InitializePurchasing()
{
    if (IsInitialized()) //если уже подключены к системе - выходим из функции
    {
        return;
    }

    var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());

    builder.AddProduct(fullVersion, ProductType.NonConsumable);


    UnityPurchasing.Initialize(this, builder);
}

public void Buy_full_version()
{
    BuyProductID(fullVersion);
}



void BuyProductID(string productId)
{
    if (IsInitialized()) //если покупка инициализирована
    {
        Product product = m_StoreController.products.WithID(productId); //находим продукт покупки

        if (product != null && product.availableToPurchase) //если продукт найдет и готов для продажи
        {
            Debug.Log(string.Format("Purchasing product asychronously: '{0}'", product.definition.id));
            m_StoreController.InitiatePurchase(product); //покупаем
           
        }
        else
        {
            Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
        }
    }
    else
    {
        Debug.Log("BuyProductID FAIL. Not initialized.");
    }
}

public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) //контроль покупок
{
   


   

     if (String.Equals(args.purchasedProduct.definition.id, fullVersion, StringComparison.Ordinal))
    {
        Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));

        //действия при покупке
        if (PlayerPrefs.HasKey("full_version") == false)
        {
            PlayerPrefs.SetInt("full_version", 1);

        }
       
    }

    else
    {
        Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
    }

    return PurchaseProcessingResult.Complete;
}

public void RestorePurchases() //Восстановление покупок (только для Apple). У гугл это автоматический процесс.
{
    if (!IsInitialized())
    {
        Debug.Log("RestorePurchases FAIL. Not initialized.");
        return;
    }

    if (Application.platform == RuntimePlatform.IPhonePlayer ||
        Application.platform == RuntimePlatform.OSXPlayer) //если запущенно на эпл устройстве
    {
        Debug.Log("RestorePurchases started ...");

        var apple = m_StoreExtensionProvider.GetExtension<IAppleExtensions>();

        apple.RestoreTransactions((result) =>
        {
            Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore.");
        });
    }
    else
    {
        Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
    }
}



public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    Debug.Log("OnInitialized: PASS");
    m_StoreController = controller;
    m_StoreExtensionProvider = extensions;
}

private bool IsInitialized()
{
    return m_StoreController != null && m_StoreExtensionProvider != null;
}

public void OnInitializeFailed(InitializationFailureReason error)
{
    Debug.Log("OnInitializeFailed InitializationFailureReason:" + error);
}

public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
{
    Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
}

}
__
```**__
The problem is that I don’t understand what this error means, and subsequently how to solve it. Hoping for your help

@vavavagyan You are mixing Codeless and Scripted IAP unfortunately. You should avoid Codeless IAP altogether, it has not been updated in some time and has issues, as you are seeing. Instead, use Scripted IAP (only), perhaps start with this Sample IAP Project Sample IAP Project

@JeffDUnity3D I’m currently using Codeless IAP and it seems to be working okay at present.

Would it be your recommendation that I too change to Scripted IAP, is Codeless IAP likely to become more unstable in the future?

Did the store accept your game? Codeless does not support receipt validation nor Google deferred purchases. We’ve also heard reports that all purchases are refunded after 3 days. However, if it’s working for you currently without issue, then no need to change.

I’ve currently got 8 games using codeless IAP, none of which are being rejected when I submit updates (which I do quite regularly). I get no purchases refunded either.

However, the possibility of the above problems starting to occur in future is worrying, so I think I will change to Scripted IAP nonetheless.

Another reason to change, is the ability to implement receipt validation, but would this cause a problem for non-consumables that have already been purchased?

It would only be a problem if the receipts were hacked! Otherwise they would pass validation

1 Like

So, if I understand you correctly, the only people that would lose their entitlement would be anyone that got them without paying, which I wouldn’t mind at all :slight_smile:

Thanks very much for taking the time to answer my questions.

1 Like

So you are saying the codeless IAP YOU at unity yourselves gave, is not competent and should not be used even in 2023 using unity 2021?? and that purchases can be refunded after 3 days??

sigh, smh

1 Like

@JeffDUnity3D – what is the latest update on this situation? I’m working on adding some IAPs to my game on iOS and would like to use the codeless option if possible. Are you still suggesting to used scripted instead?

My test results are similar: purchasing appears to work fine within the Unity Editor, but once compiled and put on the iPhone, I get "Purchase failed because Purchasing was not initialized correctly" error in Xcode.

I have the same issue on Android. Did you solve the problem?

3 Likes

Ping. Running into the same issue on iOS.

1 Like

I have the same problem… how you all fixed it?