onPurchaseFailedEvent : PurchaseState is UNSPECIFIED_STATE, no more details exists {M: GPUL.OPO}

When attempting to pay with the codeless inapp button, the following error message is displayed.
The receipt is printed out.
What can you try on this issue?

logcat log

IAPButton.PurchaseProduct() with product ID: com.xxxx.yyyy.android.gold_ten

purchase({0}): com.xxxx.yyyy.android.gold_ten

onPurchaseFailedEvent({0}): productId:com.xxxx.yyyy.android.gold_ten message:PurchaseState is UNSPECIFIED_STATE, no more details exists {M: GPUL.OPO}

Welcome to the Unity Forum! Has IAP worked for you in the past? Can you provide a little background and steps to reproduce? Can you show a screenshot of your IAP Button properties in the Inspector? What version of Unity, what version of IAP? What Android device are you testing on? Please show a screenshot of your Google Play developer dashboard showing this ProductID. You’ll want to ensure you follow the directions here Unity - Manual: Configuring for Google Play Store

It is an app that was previously released. As a result of testing last December, the above error came out. Request you to check.

test : Unity 2019.2.7.f2
UnityIAP Version: 2.2.5

iap catalog automatically initialize unitypurchasing (recommended) check on

We are not familiar with this behavior. What changed in December? Can you confirm if you see the same problem with scripted IAP, perhaps test with the Sample IAP Project here? Sample IAP Project

This is happening to me also, I just implemented IAP a couple of days ago (from learning portal of unity) and I Get the same error or ā€œOnPurchaseFailed: FAIL. Product: ā€˜noads’, PurchaseFailureReason: Unknownā€

Unknown is a separate error code UNSPECIFIED_STATE as reported in this thread. Please open a separate thread with steps to reproduce.

I understand, what I meant is that sometimes in some of the test builds I created (android) I get the ā€œUNSPECIFIED_STATEā€ and sometimes the PurchaseFailureReason: Unknown". So I was guessing that maybe they are related

Ah got it. Are you using Codeless IAP also? What version of IAP? The latest is Unity IAP Asset version 2.2.5 and In App Purchasing library 2.2.1 in Package Manager (both components are required)

I’m using Unity 2019.2.2f1 IAP 2.2.5 and in packagemanager(2.2.1) I followed this tutorial:

and in the apks when you click the button the google pay starts (I have test account so I don’t pay) and the payment is succesfull and then I get:

NOTE: as far as I know, I’m not using codeless iap, but in the log apparently I’m using it

Initializing UnityPurchasing via Codeless IAP

UnityIAP Version: 2.2.5

<b>Initializing Purchases</b>

<b>Adding Product noads</b>

<b>Adding Product unlimitedammo</b>

<b>Adding Product ultimatepack</b>

AndroidAgent ctr

OnInitialized: PASS

Purchasing product asychronously: 'unlimitedammo'

purchase({0}): unlimitedammo

onPurchaseFailedEvent({0}): productId:unlimitedammo message:PurchaseState is UNSPECIFIED_STATE, no more details exists {M: GPUL.OPO}

OnPurchaseFailed: FAIL. Product: 'unlimitedammo', PurchaseFailureReason: Unknown

and here is my code

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Purchasing;

public class IAPManager : MonoBehaviour, IStoreListener
{
    private static IStoreController m_StoreController;        
    private static IExtensionProvider m_StoreExtensionProvider;

    public static string noAds = "noads";
    public static string unlimitedammo = "unlimitedammo";
    public static string ultimatePack = "ultimatepack";

    public Transform iapsContainer;
    public IAPElement iapElementPrefab;

    public List<ProductInfo> products;

    void Start()
    {
        if (m_StoreController == null)
        {
            InitializePurchasing();
        }
    }

    public void InitializePurchasing()
    {
        Debug.LogFormat("<b>Initializing Purchases</b>");
        if (IsInitialized())
        {
            return;
        }

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

        Debug.LogFormat("<b>Adding Product {0}</b>", noAds);
        builder.AddProduct(noAds, ProductType.NonConsumable);
        Debug.LogFormat("<b>Adding Product {0}</b>", unlimitedammo);
        builder.AddProduct(unlimitedammo, ProductType.NonConsumable);
        Debug.LogFormat("<b>Adding Product {0}</b>", ultimatePack);
        builder.AddProduct(ultimatePack, ProductType.NonConsumable);

        UnityPurchasing.Initialize(this, builder);
    }

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

    public void BuyNoAds()
    {
        BuyProductID(noAds);
    }

    public void BuyUnlimitedAmmo()
    {
        BuyProductID(unlimitedammo);
    }

    public void BuyUltimatePack()
    {
        BuyProductID(ultimatePack);
    }


    public 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 void RestorePurchases()
    {
        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;

        for (int i = 0; i < products.Count; i++)
        {
            if(PlayerPrefs.GetInt(products[i].id,0) == 1)
            {
                UpdateUIPurchase(products[i].id);
            }
        }
    }


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


    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    {
        if (String.Equals(args.purchasedProduct.definition.id, noAds, StringComparison.Ordinal))
        {
            Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
            PlayerPrefs.SetInt("noads", 1);
            UpdateUIPurchase("noads");
        }
        else if (String.Equals(args.purchasedProduct.definition.id, unlimitedammo, StringComparison.Ordinal))
        {
            Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
            PlayerPrefs.SetInt("unlimitedammo", 1);
            UpdateUIPurchase("unlimitedammo");
        }
        else if (String.Equals(args.purchasedProduct.definition.id, ultimatePack, StringComparison.Ordinal))
        {
            Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
            PlayerPrefs.SetInt("noads", 1);
            PlayerPrefs.SetInt("unlimitedammo", 1);
            PlayerPrefs.SetInt("ultimatepack", 1);
            PlayerPrefs.SetInt("jedipowers", 1);
            UpdateUIPurchase("ultimatepack");
            UpdateUIPurchase("noads");
            UpdateUIPurchase("unlimitedammo");
        }
        else
        {
            Debug.Log(string.Format("ProcessPurchase: FAIL. Unrecognized product: '{0}'", args.purchasedProduct.definition.id));
        }
        return PurchaseProcessingResult.Complete;
    }

    public void UpdateUIPurchase(string productID)
    {
        foreach(ProductInfo product in products)
        {
            if(product.id == productID)
            {
                product.uiElement.buyBtnText.text = "Purchased";
                product.uiElement.buyBtn.interactable = false;
            }
        }
    }

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

[Serializable]
public class ProductInfo
{
    public string id;
    public ProductType type;
    public IAPElement uiElement;
}

The important fact is that the app worked very well until last year.
check plz…

You have a Codeless IAP Button in your scene so it’s initializing IAP twice. Please compare to the Sample IAP Project. You’ll want to remove Codeless components from your project.

It was because I had some products added in the cataloge + the IAP listener, I removed them, and I don’t get the codeless Init but I still get the same erros

<b>Initializing Purchases</b>

UnityIAP Version: 2.2.5

<b>Adding Product noads</b>

<b>Adding Product unlimitedammo</b>

<b>Adding Product ultimatepack</b>

OnInitialized: PASS

Purchasing product asychronously: 'ultimatepack'

purchase({0}): ultimatepack

onPurchaseFailedEvent({0}): productId:ultimatepack message:PurchaseState is UNSPECIFIED_STATE, no more details exists {M: GPUL.OPO}

OnPurchaseFailed: FAIL. Product: 'ultimatepack', PurchaseFailureReason: Unknown

I was able to make it work I downgraded the IAP plugin to 2.0.0 and the Package manager version to 2.0.3 and it works just fine

1 Like