I currently keep all purchases validation local.
Say, a user purchased IAP on android/iOS (I’m talking about non-consumable items only), I save a player-pref for that purchase so I know whether the user bought this item or not.
But I see a bug that when users ask for refunds from google, they get the money back but the process was not made through the game loop and I keep showing them the item even though they canceled it outside of the game environment.
I thought that there would be a way to use android and iOS API to know whether the user has this item active currently or not. But I couldn’t find those endpoints.
Even if I use a backend server (such as firebase) as a more appropriate way of validating purchases, how do I know if the purchase was canceled/refunded if it doesn’t go through the game loop? How do I then disable the item to that user?
Since I make games for android and iOS I would be happy to address both platforms.
Cancelled and refunded (voided) purchases are removed from Unity IAP’s product.hasReceipt property - it then returns false. It might get cached for a while (up to 3 days) though. If you have a limited amount of IAP items, you can unlock your game content by checking that property directly, instead of writing to PlayerPref.
Otherwise, Google has a Voided Purchases API, but that is more complex to setup and in addition to a backend server, requires user authentication too.
In the Unity editor, it doesn’t through any errors, but on mobile devices, it does through a null exception error.
Could it be that m_StoreController or m_StoreController.products aren’t initialized on time?
Yes, the IAP works great on both Android and iOS for that product id. m_StoreController is null, but now I see that if I wait long enough it works!
Now I have 2 questions:
When would be the ideal time (function wise) to check about the purchased products so m_StoreController won’t be null?
If that property can replace the player prefs, that means that there must be internet access when using the app. Does it cache locally the “hasPurchased” property for 3 days every time there’s an Internet connection?
I have an issue about IAP in my game. whenever user click on IAP product and then cancel it not purchasing successful then an exception throws on this following method :
UnityPurchaser.OnPurchaseFailed() and its a
NullReferenceException · Object reference not set to an instance of an object.
This seems to be the product being null. You will want to null check this on your script handling the OnPurchaseFailed.
The only case where we explicitly return a null product is when Purchasing was not initialized correctly since in that case, we are unable to match it to an existing product.
Does your IAP Listener have a script attached to the On Purchase Failed?
Also, is UnityPurchaser part of your own code? If so, would you be able to provide that code and the GVIAPListener.purchaseFailed so I can help you better?
From what I can see, it might be that purchaseFail is called twice, the first call will deregister the callback, and the second call will attempt to call null.
You could add a trace in purchaseFailed to see how often it’s being called to confirm this.
Could it be that you have both Coded and Codeless IAP at the same time?
In the IAP Catalog, make sure “Automatically initialize UnityPurchasing (recommended)” is turned off to disable Codeless.
If this doesn’t work, could you try to only do the registerCallbacks once and never deregisterCallbacks to see if that works?
product.hasReceipt can be used for polling the receipts at various MonoBehaviour lifecycle points, right? But how can the app be notified that someone has cancelled or refunded a transaction (in my case, nonconsumable), in the event that the refund completes while the app is already running? we can register a callback for?