[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?

Same issue on iOS with new InApp Purcahse API (5.x)

InAppPurchasing: Cannot initiate purchase because product was not found for ID ‘commission’

only on iOS. It’s working on Android.

I thought I needed to add the product on my Apple dashboard but apple needs a screenshot that show it is working on my phone to be able to validated the product on the apple dashboard. It seems to be a stupid loop where I need first on the dashboard but to be able to have it on the dashboard I need it first in my app ? WTF ?

Hi @Fangh,

It seems this is not a bug in IAP; it is Apple’s setup flow that is confusing.
The good news is you do not need an approved product to test.

Please try these steps:

  1. Create the product in App Store Connect (just fill in details and save - “Missing Metadata” state is fine)

  2. Create a Sandbox tester in App Store Connect (go to Users and Access → Sandbox → Testers)

  3. On device, use the Sandbox account when prompted during purchase

Sandbox testing should work with unapproved products. The screenshot Apple asks for is only needed when submitting for review.

Quick checklist:

  • Product ID in code matches one in App Store Connect (case-sensitive)
  • You’re testing with a Sandbox account, not a real Apple ID
  • Bundle ID in your build matches App Store Connect

Let us know if this helps!

Thanks!

1 Like

This is exactly what I did.
But it’s EVEN MORE confusing !
Because there is one more step ! (that does not exists for Google Play Store ofc)
I write it down in case another dev have the same issue :

  • in the main page you need to add the product to your current version of the app.

Yes. Products needs to be manually added to a specific version of the app.

It’s pushed to Apple now, I’m waiting for their review

1 Like