I’ve been following this thread, but I haven’t been able to replicate the problems others seem to be facing. Things seem to be working fine for me on both iOS and Google Play.
Here’s my setup. I have some managed products that the user can purchase, and I have a separate button to restore purchases. I don’t call store.restore() until the user actually presses the restore purchases button.
Here’s what I’m seeing.
On Android, let’s say the user buys a product, deletes the app, and then reinstalls the app. If they try to buy the product again, my transaction callback receives a “failed” transaction. The user also sees an automatic popup from Google Play telling them they already own the product. True, it’s up to the user to then realize they need to go and select restore purchases, but I don’t think that’s a big issue. If it’s something you’re worried about, then in response to a failed state, you can show your own popup reminding the user to try restoring purchases, which, Krystian, it sounds like is what you’re doing, and is what I do too. Either way, if the user then does hit the restore purchases button, initiating a call to store.restore(), my transaction callback gets a “purchased” transaction for each restored product as expected. So that all seems fine to me.
On iOS, let’s again say the user buys a product, deletes the app, and then reinstalls the app. If they try to buy the product again, the user gets a popup from iOS indicating that they already own the product and can download it again for free. If they say yes, then my transaction callback gets a “purchased” transaction. If they so no, it gets a “cancelled” transaction. If instead of all this, they happen to go directly to the restore purchases button, initiating a call to store.restore(), my transaction callback gets a “restored” transaction. So again, that all seems fine to me.
It sounds like many on this thread are calling store.restore() immediately after store.init() and not receiving any transactions in your transaction listener that you think should be restored. Just a thought, but try calling store.restore() after a few second delay or by making a separate button for it. Notwithstanding that the sample code in the API documentation shows store.restore() being called immediately after store.init(), I wonder if there’s something asynchronous about store.init() that could prevent it from working.
Separately, @krystian6, you raised a separate point about what should happen when store.restore() is called if the user hasn’t previously purchased anything and there’s nothing to restore. It sounds like you’re saying that you expect your transaction callback to receive an event indicating that there was nothing to restore, but instead your callback isn’t receiving anything. First, from a user standpoint, I don’t see that as a big problem, since a user wouldn’t be expected to press a restore purchases button unless they had something in mind that they were trying to restore. Second, on the question of whether this behavior is a Corona bug or not, I don’t think it is. For iOS, according to the bottom of this page – http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/MakingaPurchase/MakingaPurchase.html – “the App Store generates a new restore transaction for each transaction that was previously completed”. This implies to me that it generates nothing if no products were previously purchased. The Android documentation isn’t quite as clear, but this page – http://developer.android.com/google/play/billing/v2/api.html – does say that RESTORE_TRANSACTIONS “retrieves a user’s transaction status for managed purchases and subscriptions”, which again implies to me that if the user has no managed purchases or subscriptions, it retrieves nothing.
I guess the problem is if, after a user presses the button and you call store.restore(), you activate the system’s activity indicator or some modal dialog that prevents the user from using the app. You’d turn it off in your transaction callback, but since it never gets called, the user is stuck. The solution is to either use a timeout, which, @krystrian6, it sounds like is what you do, or you not show an activity indicator / modal dialog in the first place. But again, it seems to me like this would be the same thing on iOS or Android natively.