Where to put, code i want to execute on purchase proccessed, in my own IAP script?

OnPurchaseComplete() doesn’t work, i want the functions onbutton299BOUGHT,onbutton399BOUGHT and onbutton499BOUGHT to execute when they are purchased, also i am getting another error
8655171--1165071--upload_2022-12-12_18-16-51.png

this is what it says, this might be because I havent actually added the id stores into the app store and google play console.

would appreaciate any help, because information on Code IAP is hard to find

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

public class MyIAPManager : MonoBehaviour, IStoreListener
{
    public GameObject RestoreButton;
    public Movement mov;

    private static IStoreController m_StoreController;          // The Unity Purchasing system.
    private static IExtensionProvider m_StoreExtensionProvider; // The store-specific Purchasing subsystems.
    private IAppleExtensions m_AppleExtensions;
    private IGooglePlayStoreExtensions m_GoogleExtensions;

    // ProductIDs
    public static string GOLD_50 = "gold50";
    public static string NONCONSUMABLE1 = "REMOVE_ADS";
    public static string NONCONSUMABLE2 = "REMOVE_ADS_5000";
    public static string NONCONSUMABLE3 = "REMOVE_ADS_30000_4PET";
    public static string WEEKLYSUB = "weeklysub";

    //public Text myText;

    void Awake()
    {

    }
    void Update()
    {
      
    }
   


    void Start()
    {
        StartCoroutine(RestoreSetIfIphone());
        // If we haven't set up the Unity Purchasing reference
        if (m_StoreController == null)
        {
            // Begin to configure our connection to Purchasing, can use button click instead
            InitializePurchasing();
        }
    }
    IEnumerator RestoreSetIfIphone()
    {
        while (true)
        {
            yield return new WaitForSeconds(1.5f);
            if (Application.platform == RuntimePlatform.IPhonePlayer)
                RestoreButton.SetActive(true);
        }
       
    }
    public void MyInitialize()
    {
        InitializePurchasing();
    }

    public void InitializePurchasing()
    {
        if (IsInitialized())
        {
            return;
        }

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

        builder.AddProduct(NONCONSUMABLE1, ProductType.NonConsumable);
        builder.AddProduct(NONCONSUMABLE2, ProductType.NonConsumable);
        builder.AddProduct(NONCONSUMABLE3, ProductType.NonConsumable);
        builder.AddProduct(GOLD_50, ProductType.Consumable);
        builder.AddProduct(WEEKLYSUB, ProductType.Subscription);

        MyDebug("Starting Initialized...");
        UnityPurchasing.Initialize(this, builder);

    }


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

    public void BuySubscription()
    {
        BuyProductID(WEEKLYSUB);
    }


    public void BuyGold50()
    {
        BuyProductID(GOLD_50);
    }


    //DODAJ NA DUGMICE OVO
    public void BuyNonConsumable1()
    {
        BuyProductID(NONCONSUMABLE1);
    }
    public void BuyNonConsumable2()
    {
        BuyProductID(NONCONSUMABLE2);
    }
    public void BuyNonConsumable3()
    {
        BuyProductID(NONCONSUMABLE3);
    }

    public void RestorePurchases()
    {
        m_StoreExtensionProvider.GetExtension<IAppleExtensions>().RestoreTransactions(result => {
            if (result)
            {
                MyDebug("Restore purchases succeeded.");
            }
            else
            {
                MyDebug("Restore purchases failed.");
            }
        });
    }

    void BuyProductID(string productId)
    {
        if (IsInitialized())
        {
            UnityEngine.Purchasing.Product product = m_StoreController.products.WithID(productId);

            if (product != null && product.availableToPurchase)
            {
                MyDebug(string.Format("Purchasing product:" + product.definition.id.ToString()));
                m_StoreController.InitiatePurchase(product);
            }
            else
            {
                MyDebug("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
            }
        }
        else
        {
            MyDebug("BuyProductID FAIL. Not initialized.");
        }
    }

    public void ListProducts()
    {

        foreach (UnityEngine.Purchasing.Product item in m_StoreController.products.all)
        {
            if (item.receipt != null)
            {
                MyDebug("Receipt found for Product = " + item.definition.id.ToString());
            }
        }
    }
    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
        MyDebug("OnInitialized: PASS");
        var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
       
        m_StoreController = controller;
        m_StoreExtensionProvider = extensions;
        m_AppleExtensions = extensions.GetExtension<IAppleExtensions>();
        m_GoogleExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();

        builder.Configure<IGooglePlayConfiguration>().SetDeferredPurchaseListener(OnPurchaseDeferred);


        Dictionary<string, string> dict = m_AppleExtensions.GetIntroductoryPriceDictionary();

        foreach (UnityEngine.Purchasing.Product item in controller.products.all)
        {

            if (item.receipt != null)
            {
                string intro_json = (dict == null || !dict.ContainsKey(item.definition.storeSpecificId)) ? null : dict[item.definition.storeSpecificId];

                if (item.definition.type == ProductType.Subscription)
                {
                    SubscriptionManager p = new SubscriptionManager(item, intro_json);
                    SubscriptionInfo info = p.getSubscriptionInfo();
                    MyDebug("SubInfo: " + info.getProductId().ToString());
                    MyDebug("isSubscribed: " + info.isSubscribed().ToString());
                    MyDebug("isFreeTrial: " + info.isFreeTrial().ToString());
                }
            }
        }
    }

    public void OnPurchaseDeferred(Product product)
    {

        MyDebug("Deferred product " + product.definition.id.ToString());
    }

    public void OnInitializeFailed(InitializationFailureReason error)
    {
        // Purchasing set-up has not succeeded. Check error for reason. Consider sharing this reason with the user.
        MyDebug("OnInitializeFailed InitializationFailureReason:" + error);
    }


    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    {

        try
        {
            var validator = new CrossPlatformValidator(GooglePlayTangle.Data(), AppleTangle.Data(), Application.identifier);
            var result = validator.Validate(args.purchasedProduct.receipt);
            MyDebug("Validate = " + result.ToString());

            foreach (IPurchaseReceipt productReceipt in result)
            {
                MyDebug("Valid receipt for " + productReceipt.productID.ToString());
            }
        }
        catch (Exception e)
        {
            MyDebug("Error is " + e.Message.ToString());
        }

        MyDebug(string.Format("ProcessPurchase: " + args.purchasedProduct.definition.id));

        return PurchaseProcessingResult.Complete;

    }


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

    public void OnPurchaseComplete(Product product)
    {
        if (product.definition.id == NONCONSUMABLE1)
        {
            onButton299BOUGHT(product);
        }
        if (product.definition.id == NONCONSUMABLE2)
        {
            onButton399BOUGHT(product);
        }
        if (product.definition.id == NONCONSUMABLE3)
        {
            onButton599BOUGHT(product);
        }
    }
    void onButton299BOUGHT(Product product)
    {

    }
    void onButton399BOUGHT(Product product)
    {
        mov.gems += 5000;
    }
    void onButton599BOUGHT(Product product)
    {

    }
    private void MyDebug(string debug)
    {

        Debug.Log(debug);
        //myText.text += "\r\n" + debug;
    }

}

Hi @Dxjukez ,

If you havent added the id stores into the Apple store and Google Play console dashboards, you won’t be able to test these purchases in their sandbox modes in those builds of your app. However, you should be able to test the buttons using the Fake Store in Play In Editor mode. Have you tried that?

If the problem persists, please post your call stack tied to the error you get. I see that in the case of buying your “REMOVE_ADS_5000”, you call mov.gems += 5000; Have you set a valid object for mov and an implementation for gems?

1 Like

Hey @John_Corbett

I havent set up the id stores, however i want to test if they work in sandbox mode for the builds.

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

public class MyIAPManager : MonoBehaviour, IStoreListener
{
    public GameObject RestoreButton;
    public Movement mov;
    public AudioSource audioSource;
    public AudioClip cashedOutClip;
    public GameObject mainUI;
    public AdsManager adManager;
    public ShopUIScript shopUIScript;

    public AddAnimationGems addAnimationsGemsScript;

    private static IStoreController m_StoreController;          // The Unity Purchasing system.
    private static IExtensionProvider m_StoreExtensionProvider; // The store-specific Purchasing subsystems.
    private IAppleExtensions m_AppleExtensions;
    private IGooglePlayStoreExtensions m_GoogleExtensions;

    // ProductIDs
    public static string GOLD_50 = "gold50";
    public static string NONCONSUMABLE1 = "REMOVE_ADS";
    public static string NONCONSUMABLE2 = "REMOVE_ADS_5000";
    public static string NONCONSUMABLE3 = "REMOVE_ADS_30000_4PET";
    public static string WEEKLYSUB = "weeklysub";

    //public Text myText;

    void Awake()
    {

    }
    void Update()
    {
     
    }
  


    void Start()
    {
        StartCoroutine(RestoreSetIfIphone());
        // If we haven't set up the Unity Purchasing reference
        if (m_StoreController == null)
        {
            // Begin to configure our connection to Purchasing, can use button click instead
            InitializePurchasing();
        }
    }
    IEnumerator RestoreSetIfIphone()
    {
        while (true)
        {
            yield return new WaitForSeconds(1.5f);
            if (Application.platform == RuntimePlatform.IPhonePlayer)
                RestoreButton.SetActive(true);
        }
      
    }
    public void MyInitialize()
    {
        InitializePurchasing();
    }

    public void InitializePurchasing()
    {
        if (IsInitialized())
        {
            return;
        }

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

        builder.AddProduct(NONCONSUMABLE1, ProductType.NonConsumable);
        builder.AddProduct(NONCONSUMABLE2, ProductType.NonConsumable);
        builder.AddProduct(NONCONSUMABLE3, ProductType.NonConsumable);
        builder.AddProduct(GOLD_50, ProductType.Consumable);
        builder.AddProduct(WEEKLYSUB, ProductType.Subscription);

        MyDebug("Starting Initialized...");
        UnityPurchasing.Initialize(this, builder);

    }


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

    public void BuySubscription()
    {
        BuyProductID(WEEKLYSUB);
    }


    public void BuyGold50()
    {
        BuyProductID(GOLD_50);
    }


    //DODAJ NA DUGMICE OVO
    public void BuyNonConsumable1()
    {
        BuyProductID(NONCONSUMABLE1);
    }
    public void BuyNonConsumable2()
    {
        BuyProductID(NONCONSUMABLE2);
    }
    public void BuyNonConsumable3()
    {
        BuyProductID(NONCONSUMABLE3);
    }

    public void RestorePurchases()
    {
        m_StoreExtensionProvider.GetExtension<IAppleExtensions>().RestoreTransactions(result => {
            if (result)
            {
                MyDebug("Restore purchases succeeded.");
            }
            else
            {
                MyDebug("Restore purchases failed.");
            }
        });
    }

    void BuyProductID(string productId)
    {
        if (IsInitialized())
        {
            UnityEngine.Purchasing.Product product = m_StoreController.products.WithID(productId);

            if (product != null && product.availableToPurchase)
            {
                MyDebug(string.Format("Purchasing product:" + product.definition.id.ToString()));
                m_StoreController.InitiatePurchase(product);
            }
            else
            {
                MyDebug("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
            }
        }
        else
        {
            MyDebug("BuyProductID FAIL. Not initialized.");
        }
    }

    public void ListProducts()
    {

        foreach (UnityEngine.Purchasing.Product item in m_StoreController.products.all)
        {
            if (item.receipt != null)
            {
                MyDebug("Receipt found for Product = " + item.definition.id.ToString());
            }
        }
    }
    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
        MyDebug("OnInitialized: PASS");
        var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
      
        m_StoreController = controller;
        m_StoreExtensionProvider = extensions;
        m_AppleExtensions = extensions.GetExtension<IAppleExtensions>();
        m_GoogleExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();

        builder.Configure<IGooglePlayConfiguration>().SetDeferredPurchaseListener(OnPurchaseDeferred);


        Dictionary<string, string> dict = m_AppleExtensions.GetIntroductoryPriceDictionary();

        foreach (UnityEngine.Purchasing.Product item in controller.products.all)
        {

            if (item.receipt != null)
            {
                string intro_json = (dict == null || !dict.ContainsKey(item.definition.storeSpecificId)) ? null : dict[item.definition.storeSpecificId];

                if (item.definition.type == ProductType.Subscription)
                {
                    SubscriptionManager p = new SubscriptionManager(item, intro_json);
                    SubscriptionInfo info = p.getSubscriptionInfo();
                    MyDebug("SubInfo: " + info.getProductId().ToString());
                    MyDebug("isSubscribed: " + info.isSubscribed().ToString());
                    MyDebug("isFreeTrial: " + info.isFreeTrial().ToString());
                }
            }
        }
    }

    public void OnPurchaseDeferred(Product product)
    {

        MyDebug("Deferred product " + product.definition.id.ToString());
    }

    public void OnInitializeFailed(InitializationFailureReason error)
    {
        // Purchasing set-up has not succeeded. Check error for reason. Consider sharing this reason with the user.
        MyDebug("OnInitializeFailed InitializationFailureReason:" + error);
    }


    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    {

      
        try
        {
            var validator = new CrossPlatformValidator(GooglePlayTangle.Data(), AppleTangle.Data(), Application.identifier);

            var result = validator.Validate(args.purchasedProduct.receipt);
            MyDebug("Validate = " + result.ToString());

            foreach (IPurchaseReceipt productReceipt in result)
            {
                MyDebug("Valid receipt for " + productReceipt.productID.ToString());
            }
        }
        catch (Exception e)
        {
            MyDebug("Error is " + e.Message.ToString());

        }

        MyDebug(string.Format("ProcessPurchase: " + args.purchasedProduct.definition.id));

        return PurchaseProcessingResult.Complete;

    }


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

    public void OnPurchaseComplete(Product product)
    {
        if (product.definition.id == NONCONSUMABLE1)
        {
            onButton299BOUGHT(product);
        }
        if (product.definition.id == NONCONSUMABLE2)
        {
            onButton399BOUGHT(product);
        }
        if (product.definition.id == NONCONSUMABLE3)
        {
            onButton599BOUGHT(product);
        }
    }
    void onButton299BOUGHT(Product product)
    {
        Debug.Log("button $2.99 has been bought");

        SaveManager.Instance.state.boughtButton1 = true;
        SaveManager.Instance.state.RemoveAdsSave = true;
      


        audioSource.PlayOneShot(cashedOutClip);
        adManager.removeAds = true;
        mainUI.gameObject.SetActive(true);
        gameObject.SetActive(false);
    }
    void onButton399BOUGHT(Product product)
    {
        Debug.Log("button $4.99 has been bought");

        SaveManager.Instance.state.boughtButton2 = true;
        SaveManager.Instance.state.RemoveAdsSave = true;
     


        audioSource.PlayOneShot(cashedOutClip);
        adManager.removeAds = true;

        StartCoroutine(PlayAddAnimationAfterHowManySecondsAndHowMuchGemsToAddAndShow(5000, 1.9f));
        mainUI.gameObject.SetActive(true);
        gameObject.SetActive(false);
    }
    void onButton599BOUGHT(Product product)
    {
        Debug.Log("button $5.99 has been bought");





        SaveManager.Instance.state.boughtButton3 = true;
      

        audioSource.PlayOneShot(cashedOutClip);


        shopUIScript.ownsPetsArray[8] = true;
        shopUIScript.ownsPetsArray[9] = true;
        shopUIScript.ownsPetsArray[10] = true;
        shopUIScript.ownsPetsArray[11] = true;

        StartCoroutine(PlayAddAnimationAfterHowManySecondsAndHowMuchGemsToAddAndShow(30000, 1.9f));
        mainUI.gameObject.SetActive(true);
        gameObject.SetActive(false);

    }
    IEnumerator PlayAddAnimationAfterHowManySecondsAndHowMuchGemsToAddAndShow(int gems, float waitTime)
    {
        yield return new WaitForSeconds(waitTime);
        addAnimationsGemsScript.PlayAnimationGemsAndAddGemsBOUGHTAD(gems);
    }
    private void MyDebug(string debug)
    {

        Debug.Log(debug);
        //myText.text += "\r\n" + debug;
    }

}

this is the updated code where i have debug.log if the functions get called
this is what happens here: Screen capture - e6b5cfd0ce8c1f77f9e9eb7913d9df9f - Gyazo

basically if you cant see the video, the fake storegets popped up, and I press yes but
onbutton299bought, onbutton499bought,onbutton599bought dont get called since i dont get the debug.log message

this is the two errors i get:

Error is The method or operation is not implemented.
UnityEngine.Debug:Log (object)
MyIAPManager:MyDebug (string) (at Assets/MyIAPManager.cs:328)
MyIAPManager:processPurchase (UnityEngine.Purchasing.PurchaseEventArgs) (at Assets/MyIAPManager.cs:235)
UnityEngine.GUI:CallWindowDelegate (UnityEngine.GUI/WindowFunction,int,int,UnityEngine.GUISkin,int,single,single,UnityEngine.GUIStyle)

Can’t add component ‘Transform’ to UIFakeStoreWindow because such a component is already added to the game object!
UnityEngine.Purchasing.PurchasingManager:InitiatePurchase (UnityEngine.Purchasing.Product)
MyIAPManager:BuyProductID (string) (at Assets/MyIAPManager.cs:146)
MyIAPManager:BuyNonConsumable2 () (at Assets/MyIAPManager.cs:116)
UnityEngine.EventSystems.EventSystem:Update ()

also I am sure everything is referenced.