Google Play restore purchases after clearing save data

In our game we have a restart button which clears the player’s save data and restarts the game. We’re running into an issue on Google Play where non-consumables are not being restored after using this button, because the restore code only seems to run on a full uninstall/reinstall. Is there a way for us to manually trigger a restore purchases on Google Play or some other way to get around this (e.g. clearing the Unity IAP restore flag)?

Can you elaborate “not being restored”? Are you storing your purchases in PlayerPrefs?

I’m referring to this, from the Unity manual. Unity - Manual: Restoring Transactions

“When a user reinstalls your application they should be granted any Non-Consumable or renewable Subscription products they already own.” and “On platforms that support it (e.g. Google Play and Universal Windows Applications) Unity IAP automatically restores any products the user owns during the first initialization following reinstallation; the ProcessPurchase method of your IStoreListener will be called for each owned item.”

As this only runs after uninstall/reinstall, my restart button doesn’t trigger it because the app isn’t actually uninstalled/reinstalled I just clear the game’s save data (which is stored in PlayerPrefs on Android).

I believe you cache whether an item has been restored in something like… whatevergamename/files/Unity/UnityPurchasing/ and this only gets cleared on a full reinstall. If I could clear/reset this as I clear my save data that would be handy.

You likely do not want to store your purchases in PlayerPrefs for this reason. I will check with the IAP team to see if this would be feasible to include in a future release.

Thanks for the response and checking with the team.

But how else could I store the purchases to get around this issue? I don’t understand what would be different if I stored them in a different way?

It seems odd to me that restoring purchases only happens once on Google Play and can’t be triggered again unless there’s a full reinstall, whereas with iOS we have the functionality to call restore as often as we want.

Can you explain to me how clearing the player prefs requires you to restore purchases? Seems to me if you “didn’t do that” then you wouldn’t NEED to restore? If clearing PlayerPrefs causes the issue, then use persistent storage instead.The restore behavior is store specific, and we have no control over this.

Sorry, the issue is that I’m trying to clear ALL save data upon pressing the restart button. Whether it’s stored in PlayerPrefs or Cloud storage wouldn’t matter as I’m trying to clear ALL save data and give them a fresh start.

If I clear the Unity Purchasing folder for my game on an Android device, it triggers the restore when I next open the game. So it’s not a limitation of the store, as Unity is caching whether it’s been restored or not in this folder.

My problem is that I can’t (or don’t know how to) delete the data (through code) that Unity is caching that stops the restore from taking place.

I suppose what I can do is before wiping all the save data, make a note of which items were unlocked and then after the data wipe restore those manually, but that feels super hacky…

Users are asking for a way to delete their purchases? Then want them back immediately? Sorry I’m not quite following. I suspect what you mean by “ALL save data” is level progress (for example) and not things they have paid for. One easy way not to delete products would be not delete the PlayerPrefs key that stores the purchases (don’t call PlayerPrefs.DeleteAll). At any rate, I mentioned your request to the IAP team and they mentioned it would be possible to include this feature. I will write up a feature request on your behalf and hopefully it will be added in a future release.

Hi @GrumpyRhino ,

This is a good workaround if you don’t need a re-launch after clearing data.

Yes, purchasing records are saved in ‘Application.persistentDataPath/files/Unity/UnityPurchasing’. Deleting this folder could make ‘ProcessPurchase’ invoked again at next launch.
You can do it via this code below:

var purchasingDataPath = Path.Combine(Path.Combine(Application.persistentDataPath, "Unity"), "UnityPurchasing");
Directory.Delete(purchasingDataPath, true);

Here ‘Application.persistentDataPath/files/Unity/UnityPurchasing’ only save the non-consumble purchase, right? How about a pending consumble transaction receipt?

Hi there! Maybe it is offtop a little bit, but

IAP does not retrieve subscriptions purchases history and active purchased subscription on Android 7.1 devices after application’s reopening. Plugin version is 1.20.1 This issue reproduces even if I bought subscription on device with other version of the OS. Logs from Logcat from Android 7.1 device :

10-12 12:45:04.108 24771-24842/? I/Unity: UnityIAP Version: 1.20.1
10-12 12:45:04.259 24771-24842/? I/UnityIAP: IAB helper created.
10-12 12:45:05.727 24771-24842/? I/UnityIAP: Starting in-app billing setup.
10-12 12:45:05.761 24771-24771/? I/UnityIAP: Billing service connected.
10-12 12:45:05.763 24771-25113/? I/UnityIAP: invoking callback
10-12 12:45:05.763 24771-25113/? I/UnityIAP: Checking for in-app billing 3 support.
10-12 12:45:05.794 24771-25113/? I/UnityIAP: In-app billing version 3 supported for
10-12 12:45:05.810 24771-25113/? I/UnityIAP: Subscriptions AVAILABLE.
10-12 12:45:05.824 24771-25113/? I/UnityIAP: Subscription upgrade and downgrade are AVAILABLE.
10-12 12:45:05.837 24771-25113/? I/UnityIAP: Subscriptions information parse AVAILABLE.
10-12 12:45:05.850 24771-25113/? I/UnityIAP: VR supported. 10-12 12:45:05.851 24771-25113/? I/UnityIAP: onIabSetupFinished: 0
10-12 12:45:05.851 24771-25113/? I/UnityIAP: Requesting 2 products
10-12 12:45:05.851 24771-25113/? I/UnityIAP: QueryInventory: 2
10-12 12:45:05.851 24771-25113/? I/UnityIAP: invoking callback
10-12 12:45:05.851 24771-25113/? I/UnityIAP: Querying owned items, item type: inapp
10-12 12:45:05.851 24771-25113/? I/UnityIAP: Package name:  package-name
10-12 12:45:05.851 24771-25113/? I/UnityIAP: Calling getPurchases with continuation token: null
10-12 12:45:05.868 24771-25113/? I/UnityIAP: Owned items response: 0
10-12 12:45:05.868 24771-25113/? I/UnityIAP: Continuation token: null
10-12 12:45:05.868 24771-25113/? I/UnityIAP: Querying SKU details.
10-12 12:45:05.890 24771-25113/? I/UnityIAP: Querying owned items, item type: subs
10-12 12:45:05.890 24771-25113/? I/UnityIAP: Package name: package-name
10-12 12:45:05.890 24771-25113/? I/UnityIAP: Calling getPurchases with continuation token: null
10-12 12:45:05.906 24771-25113/? I/UnityIAP: Owned items response: 0
10-12 12:45:05.906 24771-25113/? I/UnityIAP: Continuation token: null
10-12 12:45:05.906 24771-25113/? I/UnityIAP: Querying SKU details.
10-12 12:45:05.925 24771-25113/? I/UnityIAP: Querying owned items' purchase history, item type: subs
10-12 12:45:05.925 24771-25113/? I/UnityIAP: Package name: package-name
10-12 12:45:05.925 24771-25113/? I/UnityIAP: Calling getPurchaseHistory with continuation token: null
10-12 12:45:06.401 24771-25113/? I/UnityIAP: Purchase history response: 0
10-12 12:45:06.401 24771-25113/? I/UnityIAP: Continuation token: null
10-12 12:45:06.401 24771-25113/? I/UnityIAP: onQueryInventoryFinished: true
10-12 12:45:06.401 24771-25113/? I/UnityIAP: Inventory refresh successful. (response: 0:OK)
10-12 12:45:06.401 24771-25113/? I/UnityIAP: The number of owned skus is2
10-12 12:45:06.401 24771-25113/? I/UnityIAP: The number of purchased skus is0
10-12 12:45:06.401 24771-25113/? I/UnityIAP: The number of subscriptions purchased history is0
10-12 12:45:08.532 24771-24842/? I/Unity: UnityIAP: Promo interface is available for 2 items

For comparison, logs from genymotion emulator Android 4.4.4 where is all works fine:

10-12 06:09:37.697 1872-1955/ I/Unity: UnityIAP Version: 1.20.1
10-12 06:09:37.757 1872-1955/ I/UnityIAP: IAB helper created.
10-12 06:09:38.909 1872-1955/ I/UnityIAP: Starting in-app billing setup.
10-12 06:09:40.525 1872-1872/ I/UnityIAP: Billing service connected.
10-12 06:09:40.533 1872-2264/ I/UnityIAP: invoking callback
10-12 06:09:40.533 1872-2264/ I/UnityIAP: Checking for in-app billing 3 support.
10-12 06:09:40.861 1872-2264/ I/UnityIAP: In-app billing version 3 supported for
10-12 06:09:41.021 1872-2264/ I/UnityIAP: Subscriptions AVAILABLE.
10-12 06:09:41.037 1872-2264/ I/UnityIAP: Subscription upgrade and downgrade are AVAILABLE.
10-12 06:09:41.061 1872-2264/ I/UnityIAP: Subscriptions information parse AVAILABLE.
10-12 06:09:41.113 1872-2264/ I/UnityIAP: VR supported.
10-12 06:09:41.113 1872-2264/ I/UnityIAP: onIabSetupFinished: 0
10-12 06:09:41.113 1872-2264/ I/UnityIAP: Requesting 2 products
10-12 06:09:41.113 1872-2264/ I/UnityIAP: QueryInventory: 2
10-12 06:09:41.113 1872-2264/ I/UnityIAP: invoking callback
10-12 06:09:41.113 1872-2264/ I/UnityIAP: Querying owned items, item type: inapp
10-12 06:09:41.113 1872-2264/ I/UnityIAP: Package name:
10-12 06:09:41.113 1872-2264/ I/UnityIAP: Calling getPurchases with continuation token: null
10-12 06:09:41.133 1872-2264/ I/UnityIAP: Owned items response: 0
10-12 06:09:41.133 1872-2264/ I/UnityIAP: Continuation token: null
10-12 06:09:41.133 1872-2264/ I/UnityIAP: Querying SKU details.
10-12 06:09:41.745 1872-2264/ I/UnityIAP: Querying owned items, item type: subs
10-12 06:09:41.745 1872-2264/ I/UnityIAP: Package name:
10-12 06:09:41.745 1872-2264/ I/UnityIAP: Calling getPurchases with continuation token: null
10-12 06:09:41.777 1872-2264/ I/UnityIAP: Owned items response: 0
10-12 06:09:41.777 1872-2264/ I/UnityIAP: Continuation token: null
10-12 06:09:41.777 1872-2264/ I/UnityIAP: Querying SKU details.
10-12 06:09:42.137 1872-2264/ I/UnityIAP: Querying owned items' purchase history, item type: subs
10-12 06:09:42.137 1872-2264/ I/UnityIAP: Package name:
10-12 06:09:42.137 1872-2264/ I/UnityIAP: Calling getPurchaseHistory with continuation token: null
10-12 06:09:43.061 1872-2264/ I/UnityIAP: Purchase history response: 0
10-12 06:09:43.065 1872-2264/ I/UnityIAP: This sku has purchase history: .subscriptionweek.premium
10-12 06:09:43.065 1872-2264/ I/UnityIAP: This sku has purchase history: .subscription.premium
10-12 06:09:43.065 1872-2264/ I/UnityIAP: Continuation token: null
10-12 06:09:43.065 1872-2264/ I/UnityIAP: onQueryInventoryFinished: true
10-12 06:09:43.065 1872-2264/ I/UnityIAP: Inventory refresh successful. (response: 0:OK)
10-12 06:09:43.065 1872-2264/ I/UnityIAP: The number of owned skus is2
10-12 06:09:43.065 1872-2264/ I/UnityIAP: The number of purchased skus is0
10-12 06:09:43.065 1872-2264/ I/UnityIAP: The number of subscriptions purchased history is2
10-12 06:09:43.673 1872-1955/ I/Unity: UnityIAP: Promo interface is available for 2 items

I hope someone can help me.

Hi @LiuChong ,

It also saves Consumable purchases.
For a pending Consumable transaction, “ProcessPurchase” will be invoked every time after initialization. And a record will be made in that folder after you call “m_Controller.ConfirmPendingPurchase”.

Hi @Anagr ,
I’m sorry that I couldn’t reproduce this issue.
I’m using Unity IAP v1.20.1, Google Pixel 2 and Samsung Galaxy Tab A (SM-T350).
Please make sure that you are using the same package name and test account.
And please use 2 Android devices to test IAP.

(Copied from this page)

I did. It is not necessary device or emulator. I used 2 devices too and the same account. Package names are equals, because I used one APK file for both devices.

Actually you can. If emulator has Play Services installed it is possible.