store.restore doesn't call back if there is no items to restore

Well I think you should not make them the same then if each store is drastically different, this is the problem. I think it would make more sense to have each store as it’s own plugin so you can update it without breaking other stores sort of thing, almost like gameNetwork plugins. I don’t see why your plugins can’t deal with consuming/errors/already owned/auto restore/ etc out of the box. Surely lot’s people are implementing identical systems wrapped around the store plugin to handle payments, at the moment a lot of work is needed on top of the plugin to make fit for production.

One tried and QA tested system for everyone with only the need to pump product ids in and specify consume rules, I’ve spent days on getting the stores stable and there are issues I can not fix due to lack of callback responses for some obscure errors/situations not handled by the plugin. Doing this would vastly improve the plugin because you would find all the little things that are missing and it would become super solid.

So if you call restore() to apple servers will it return nothing when there are no purchases at all. You send the request and nothing responds at all, the call just times out?

I do appreciate the stuff you guys do, just recently I have found the store lacking in innovation…

Thanks for the feedback, I still think a timer is very amateur solution and I see this as solution for a lot of fixes that corona can’t solve, just make it return failed if possible. Are the apple servers silent when you request restore with not items, my guess is it returns something surely? If not then I apologise. 

Thanks, Stu

I feel this bug reported by our QA team adds to the reason why a timeout is bad:

Issue is reopened in V 1.64.61 as now it is Fail for Case 1 and pass for Case 2 and Case 3: 

Case 1: 

  1. Pre-requisite : If user purchase Non-consumable item.

Select restore option. Restore successful message should appear and item should get restored.

Status: Fail

Actual Result: Item Restored message pop-up saying “Could not retrieve any items from store” is displayed and Non-consumable item is not given to user.

NOTE: If user taps on Restore button again then the “Item Restored successfully pop-up” is shown and item is restored for user.

So whats happening here is the user is on very bad network in India. Not all users have super fast broadband like in the west. So my timeout is triggering before a successful restore is returned. Ive noted that store.request timeouts can last up to 60 seconds. Should I now set my timeout to 60 seconds. This is far from ideal for us. 

Hopefully you can see the issue with it more clearly and why I’m getting frustrated. Thanks again.

I will say that I did not look too deeply into the iOS SDK but I did search questions that developers were asking in public forums about implementing it and I was not seeing anywhere where it showed that StoreKit notified the developer that there were no purchases to restore.

You could do more research on that and then add a feature request if you find out that it can be done natively through the StoreKit functions.  I am sure you could find other developers to vote for that.   :slight_smile:

What would be better in the meantime is for you to design a way to do the restore of purchases in the background where you don’t have to wait on the results to continue with using the app.  You could still put in a timeout and after 5 or 10 seconds, display a message that you have not yet gotten a reply from the iTunes Store and will continue trying to restore the purchases and the user can check in a few moments but still be allowed to use the app while they are waiting.  Or recommend that they try over Wi-Fi because the connection is not currently good.

You have a bad situation that you cannot control.  A good developer can create a way to give the user a decent experience in the face of that situation.

Just to chime in on my use case for this. I’m developing an application for a broad range of people. Some of them are tech savvy, but most are not. I just have one IAP product which unlocks some features of the app.

To simplify the interface there is just one “Upgrade” button that is intended to unlock the locked features and I was hoping to be able to just issue a store.restore() first when clicking the “Upgrade” button, and if that fails (because the user never made a purchase before) call the store.purchase(“myProduct”) to initiate a new purchase.

If there is no callback with the failed restore process this is not possible.

@RicardoGraca,

I will say that going that route may get your app rejected.  Apple has been known to reject apps that offer in-app purchases but do not have a “Restore purchases” button.

On Google you can call store.restore() after starting up and you will get a series of purchases of your managed products.  You can use these purchase events to unlock things you need to unlock.

Apple prompts for a username/password for the App Store when store.restore() is called.  They don’t want users to have to login to use your app and you must defer restore calls until the users desires to restore them.

Rob

Thanks for the reply Rob, but that is the opposite of what’s being asked. We don’t want a response when a user already purchased something, we want a response when the user hasn’t purchased anything yet.

If I do what you say I have to make the user wait before giving up and not try to unlock the app. This timeout solution isn’t acceptable. During this time the app is in limbo waiting for something that may or may not happen. Do I show a message “trying to restore your previous purchase” and wait 30 seconds every single time a user starts the app? If I do it in the background and not show any message, the user can still go to the Upgrade section and click to purchase it again, which is sure to mess things up even further. Or they can exit the app and call support enraged that the app they previously purchased is unlocked without giving enough time for the restore process to go through. Even if the reponse is fast but the user already entered the main screen of my app I can’t just make stuff unlocked like that. It requires re-entering the main screen, so in this case I would have to kick the user out of that screen and reload it with the new features. Not very nice.

You can implement this feature on your side easily if you really want to, by using the getPurchases() Java method since that does return empty if there are no purchases or a list of the user’s purchases otherwise.

If you save the purchases so that on reset you automatically unlock things, the user shouldn’t need to go through a restore process.  Restore is for people who have removed the app and need to restore their settings.

For those in this state, calling restore silently at the beginning should process the purchases rather quickly and there is a good chance it will be done before they can get go that purchasing screen.

Rob

The restore process in my case is precisely for “people who have removed the app and need to restore their settings”. I’ll try your suggestion, but I don’t know why you guys aren’t even considering adding what is being asked here since it would make our life much easier and it is now possible to offer that functionality on both platforms, so your previous excuse of “keeping consistency” isn’t valid anymore.

If this is important to you, I would recommend filing a feature request at http://feedback.coronalabs.com and get people to vote it up.  I know many people are frustrated at the lack of a call back when there is nothing to restore, but my understanding is that’s a feature of the SDK’s driving the store.* code.  Apple insists that you provide a restore button.  That same logic works just fine for Google too if you want to provide UI consistency.

Rob

Okey dokey. Feature request created: http://feedback.coronalabs.com/forums/188732-corona-sdk-feature-requests-feedback/suggestions/7237058-call-back-the-store-restore-callback-even-if-the

Bump bump bump bump. Why can this not return anything to the callback? Is it technically impossible?

Like others have said, people may hit that button and nothing happens. Timeout is a option but leaning towards a new SDK entirely.

Sorry just angry I have to lose valuable time messing around with obvious things that should work.

I totally understand wanting to be consistent on the 2 platforms, after all the idea of Corona SDK is not having to write your game twice. However, something as specific as the stores (as they involved users spending money) it seems full control is needed surely.

It was my understanding that at least on iOS, the store does not return anything if there are no purchases to restore.  So unless all the different app stores consistently returned when there were no purchases, the only way to do this the same across all platforms is for the developer to code something that works best for the app.

Each store’s eco system is drastically different.  There are limits to what we can do to make them behave the same.   While I understand the desire to get something usable back from store.restore() when there is nothing, if you think about the transaction states, there isn’t a “Sorry, nothing to do at this time”.  Things like purchase has a defined outcome.  They bought it, cancelled it, or it failed.  But for store. restore() there is only two states:  nothing or “restored”.  

Common practice is to set a timer when you detect a press on your restore() call to terminate whatever you need to terminate when there is nothing to restore.  If you get the restore, process the information and do what you need to do.

Rob

Well I think you should not make them the same then if each store is drastically different, this is the problem. I think it would make more sense to have each store as it’s own plugin so you can update it without breaking other stores sort of thing, almost like gameNetwork plugins. I don’t see why your plugins can’t deal with consuming/errors/already owned/auto restore/ etc out of the box. Surely lot’s people are implementing identical systems wrapped around the store plugin to handle payments, at the moment a lot of work is needed on top of the plugin to make fit for production.

One tried and QA tested system for everyone with only the need to pump product ids in and specify consume rules, I’ve spent days on getting the stores stable and there are issues I can not fix due to lack of callback responses for some obscure errors/situations not handled by the plugin. Doing this would vastly improve the plugin because you would find all the little things that are missing and it would become super solid.

So if you call restore() to apple servers will it return nothing when there are no purchases at all. You send the request and nothing responds at all, the call just times out?

I do appreciate the stuff you guys do, just recently I have found the store lacking in innovation…

Thanks for the feedback, I still think a timer is very amateur solution and I see this as solution for a lot of fixes that corona can’t solve, just make it return failed if possible. Are the apple servers silent when you request restore with not items, my guess is it returns something surely? If not then I apologise. 

Thanks, Stu

I feel this bug reported by our QA team adds to the reason why a timeout is bad:

Issue is reopened in V 1.64.61 as now it is Fail for Case 1 and pass for Case 2 and Case 3: 

Case 1: 

  1. Pre-requisite : If user purchase Non-consumable item.

Select restore option. Restore successful message should appear and item should get restored.

Status: Fail

Actual Result: Item Restored message pop-up saying “Could not retrieve any items from store” is displayed and Non-consumable item is not given to user.

NOTE: If user taps on Restore button again then the “Item Restored successfully pop-up” is shown and item is restored for user.

So whats happening here is the user is on very bad network in India. Not all users have super fast broadband like in the west. So my timeout is triggering before a successful restore is returned. Ive noted that store.request timeouts can last up to 60 seconds. Should I now set my timeout to 60 seconds. This is far from ideal for us. 

Hopefully you can see the issue with it more clearly and why I’m getting frustrated. Thanks again.

I will say that I did not look too deeply into the iOS SDK but I did search questions that developers were asking in public forums about implementing it and I was not seeing anywhere where it showed that StoreKit notified the developer that there were no purchases to restore.

You could do more research on that and then add a feature request if you find out that it can be done natively through the StoreKit functions.  I am sure you could find other developers to vote for that.   :slight_smile:

What would be better in the meantime is for you to design a way to do the restore of purchases in the background where you don’t have to wait on the results to continue with using the app.  You could still put in a timeout and after 5 or 10 seconds, display a message that you have not yet gotten a reply from the iTunes Store and will continue trying to restore the purchases and the user can check in a few moments but still be allowed to use the app while they are waiting.  Or recommend that they try over Wi-Fi because the connection is not currently good.

You have a bad situation that you cannot control.  A good developer can create a way to give the user a decent experience in the face of that situation.

Just to chime in on my use case for this. I’m developing an application for a broad range of people. Some of them are tech savvy, but most are not. I just have one IAP product which unlocks some features of the app.

To simplify the interface there is just one “Upgrade” button that is intended to unlock the locked features and I was hoping to be able to just issue a store.restore() first when clicking the “Upgrade” button, and if that fails (because the user never made a purchase before) call the store.purchase(“myProduct”) to initiate a new purchase.

If there is no callback with the failed restore process this is not possible.