Hi, we have several apps in app store with in-app feature, however recently while updating one of our app, apple rejected it saying “We found that while your app offers In-App Purchase(s) that can be restored, it does not include the required “Restore” feature to allow users to restore the previously purchased In-App Purchase(s)”. All our in-app products are of type non-consumable.
From sample code in corona community, though the restore button and its functionality can be added, however it will be visible at all time even when user might not have purchased the app. So what I am looking for is, the Restore button should be available only when the user has purchased the app and app is deleted or wiped out from the device.
Any help will be appreciated. Thanks. [import]uid: 71670 topic_id: 28612 reply_id: 328612[/import]
Actually you would want the restore button visible at all times because you do not know when they will get a new device, wipe their device, uninstall the game, or any other action that would require the user to restore their non-consumables iAPs. So short of keeping an online database of who has bought the game, your only choice is to put it visible all the time.
We put our in our in game store at the bottom but you can put it in your options or anywhere else. Apple just wants to see the restore for the non-consumables in there at all times. If you are worried about the user getting items they they did not purchase through the restore button then don’t worry, it wont happen unless its something on apples end because the restore function will only restore if it gets the proper callback from apple. [import]uid: 126161 topic_id: 28612 reply_id: 115423[/import]
3 Dream Gaming ,
First thanks for bringing such a important “thing” about the IAP process out.
Now, if you do not mind, could you post here some “sample” code (even a “hard” example) regarding the “HOW to implement a RESTORE button (as you mentioned above) into our app”?
It would help me so much because right now I do have an app having the IAP for non-consumable items BUT I honestly did not know (and even now) about how to implement a simple Restore button into the app.
Thanks in advance,
Cheers,
Rodrigo. [import]uid: 89165 topic_id: 28612 reply_id: 115488[/import]
@RSCdev No problem, glad to help! With iOS, when you hit the restore button what will happen is apple will send a restore state for each and every item that is purchased for for instance if i have 6 non consumables and i hit the restore button then the restore function will be called once for each purchase for a total of 6 calls so all you need to do is break down the restore state with your iOS product identifier. Now with android you will NOT get a restore state, you will get a purchased state back but other wise it works the same. Here is some iOS sample code, This is assuming you have required the store in and all that good stuff.
[lua]–Restore
–Call Restore Function
local function callRestore()
–Restore Function
local function restorePurchases(event)
–Check for restored state
if event.transaction.state == “restored” then
–Product 1
–If restore state is true then check for a match on the product identifier
if event.transaction.productIdentifier == “myIdentifier1” then
–If the product is called for restore do your restore code here
print (“Success! Product restored”)
end
–Product 2
–If restore state is true then check for a match on the product identifier
if event.transaction.productIdentifier == “myIdentifier2” then
–If the product is called for restore do your restore code here
print (“Success! Product restored”)
end
–Product 3
–If restore state is true then check for a match on the product identifier
if event.transaction.productIdentifier == “myIdentifier3” then
–If the product is called for restore do your restore code here
print (“Success! Product restored”)
end
–Finish Transaction
store.finishTransaction( event.transaction )
end
end
–Call the apple store
store.init( “apple”, restorePurchases )
–Lastly call the restore function
store.restore()
end
–Restore button
local restore_Btn = display.newRect (0, 0, 50, 50)
restore_Btn.x = 200; restore_Btn.y = 200
restore_Btn: addEventListener (“tap”, callRestore)[/lua]
This pretty much reflects the code we have in our game for our restore button. Hope this helps! [import]uid: 126161 topic_id: 28612 reply_id: 115506[/import]
3 Dreams Gaming ,
WOW!
Thank you so much for that!
I really appreciate your reply - A LOT.
BTW, just to get it really understood, so for example, into this chunck of code below:
[lua]if event.transaction.state == “restored” then
–Product 1
–If restore state is true then check for a match on the product identifier
if event.transaction.productIdentifier == “myIdentifier1” then
–If the product is called for restore do your restore code here
print (“Success! Product restored”)
end[/lua]
Would I insert my function that “unlock” the paid level of my app into the exactly line where is your [lua]print(“Success! Product restored”)[/lua] ?
Because I understand that if the code interpreter comes to this part of the code above is because the “store” was called already, checked and so the user would be able to restore if necessary or not if the store “internally” says that the user has never bought that product. Is my way to think about it correct or do I miss something relevant?
Thanks for your time,
Cheers,
Rodrigo.
[import]uid: 89165 topic_id: 28612 reply_id: 115539[/import]
@RSCdev you are 100% correct, just replace the print statement with what ever you want to unlock and replace the myIdentifier1 with the actual product identifier from apple you created and your function to unlock the bought content will only be called if the user has purchased that product identifier before and it gets the proper restore state back. [import]uid: 126161 topic_id: 28612 reply_id: 115557[/import]
3 Dreams Gaming ,
Mate, have no words to say Thank YOU!
I highly appreciate your time here.
Cheers,
Rodrigo. [import]uid: 89165 topic_id: 28612 reply_id: 115560[/import]
Glad i can help! [import]uid: 126161 topic_id: 28612 reply_id: 115561[/import]
first of all thanks for the feedback and sorry for delay in replying (I didnt had net connection for two days).
@3 Dreams Gaming -as you suggested that i should keep restore button visible at all the time, however I had not seen any app in the app store having in-app feature with restore button visible at all the time. Will wait for your reply… thanks… [import]uid: 71670 topic_id: 28612 reply_id: 115642[/import]
Just to add to @mrigendras, are there any Corona developers that can share titles of their apps with a IAP Restore feature included? I’d like to purchase your app to see how the whole Restore process works for you. (plus I’ll post a good rating for your app too) [import]uid: 82194 topic_id: 28612 reply_id: 115647[/import]
I don’t quite get why you need a purchase and a restore. But i did implement both in:
http://itunes.apple.com/us/app/hexagong/id509186866?ls=1&mt=8
The interesting thing is that if you try to purchase a non-consumable a second time apple sends back state that basically says you purchased already so you can then just restore their functionality.
Probably bigger minds than mine have thought through why we need two buttons vs one that says (purchase or restore). So i just added a second button.
Really appreciate “3 Dreams Gaming”'s post my current app has multiple non-consumables and the code snippit is certainly helpful in understanding how that works. Was wondering how you tell it what to restore but if i get what you are saying there apple will just tell you which of all the IAP’s for that app the user has purchased one after the other from the single restore call. So guess the question from an apple requirement perspective is do you need one button for each IAP or simply one that says “Restore Previous Purchases”
[import]uid: 118012 topic_id: 28612 reply_id: 115658[/import]
@mrigendras - I was rejected for not having a restore button in my game so its either a new policy or some people were able to sneak it through, the restore button is no big deal though, just need 1 button and you can put it anywhere. On the note of it not being visible, the main issue with this is when the user gets a new device. If the user gets new device they would want to be able to restore purchases. How would you tell the button to display on the users screen if it is a new device? the only way other than calling a random restore, which would prompt with a login and is not very practical, would be to store the user in an online database, which is also not very practical so i would just add the button somewhere.
@mslack - Regarding your question about why you would need both restore and a purchase. When you purchase an item, you are purchasing one item, when you restore, you restore everything at once. Also, as you have experienced, you can purchase an item you have already purchased and it will reactivate the item and not charge you. This is not how apple wants to handle restores though. They want a nice and shiny restore button to handle all restores at once. Because this is what the user expects, most will not go to the purchase in fear of being recharged.
Now to answer your other question about the requirements for the buttons. Yes you hit the restore button and the function will be called once for each item that the user has been purchased. So if the user has purchased 6 extra individual levels then the user would touch the restore button once and it will be called 6 times, once for each purchase. All you need is one button to handle all the restores, if you include all of your product id’s in the function it will do the work for you. One function to rule them all.
Hope this helps! [import]uid: 126161 topic_id: 28612 reply_id: 115721[/import]
@3 Dreams Gaming - thanks for all the feedbacks… [import]uid: 71670 topic_id: 28612 reply_id: 115768[/import]
No problem, i hope i helped! [import]uid: 126161 topic_id: 28612 reply_id: 115853[/import]
Thanks for very informative thread! We recently experienced the same cause of rejection (lack of “Restore Button” (RB) ), but now we’re wondering how should we iplement this feature because our users are also registered in our online DB and they could always restore the account using their UN/PW pair (which they can also alter in the application). Our application also has a license that users buy either one of or auto-renewable using InApp purchase.
So what should the UX be like in our case? Is it enough to show the Reset Button (RB) only in the case where user is logged out (which then would naturally be also shown when device wiped or user has new device)
Will we satisfy the requirements if we implement the Restore feature so that when
- User is logged out from his account, only then the RB is shown in our application UI
- Once RB is pressed, we use the “restoreCompletedTransactions” method in the client to seek user’s license based on his/her iTunes account
- and based on that info we then seek the user in our system (not sure if this is possible yet) and log him/her in automatically with his/her account name and password (and we then show UN as clear text in client UI and PW as “hidden”, just as in normal logged in case)
Any help would be highly appreciated! And I’d gladly clarify if the above is not clear enough…
BR,
Jukka [import]uid: 166004 topic_id: 28612 reply_id: 116443[/import]
info392,
Your case is unique, as you have a online database to store the users and allow the users to restore from your database. But, there seems to be a trend of Apple wanting restore buttons in their apps to restore purchases and i do not know if their is some official literature on this subject from Apple. The only information i can give you is that they want the user to see the restore button. I know if you implement a restore button that is shown at all times then you will not have an issue.
From the information i am assuming that you have your own restore function created from your database and you do not access Apple’s database for restores at all right now? Also, you would like to create an apple restore button when the user is logged out and use yours when the user is logged in? If that is correct, i would recommend that you use Apple’s restore process at all times, unless you have a good reason not to. So just show the button at all times as “Restore Purchases” or something like that and they will be satisfied. Hope this helps! [import]uid: 126161 topic_id: 28612 reply_id: 116446[/import]
Thanks 3DG!
“From the information i am assuming that you have your own restore function created from your database and you do not access Apple’s database for restores at all right now?” -> yes
“Also, you would like to create an apple restore button when the user is logged out and use yours when the user is logged in?” -> well, once we’re at it I guess that’s what Apple wants, right?
How we plan to implement this now is we just show the button all te time, and once pressed we tell user that either
- You have active continious subscription
- You can use your your application account to login and start using your license
- If you have forgotten your password you can reset it in this same “User Details” view
- If you have forgotten your username/email, please contact and we well solve the issue for you"
If user doesn’t have continious subscription we just tell him so and give other general information.
Do you think the above approach would work?
Interestingly enough, we just figured when testing this in the sandbox that the restore does not work for one-time payments, just renewing subscriptions. That’s also confirmed by what Apple in the instructions “Non-renewing subscriptions and consumable products are not automatically restored by Store Kit. Non-renewing subscriptions must be restorable, however. To restore these products, you must record transactions on your own server when they are purchased and provide your own mechanism to restore those transactions to the user’s devices.”
Of course our online DB management handels both types but doesn’t really make sence that “Non-renewing” license is considered consumable and renewing one non-consumable, when actual product you get is exactly same with both… [import]uid: 166004 topic_id: 28612 reply_id: 116610[/import]
Yea Apple is going out into left field with this one i think. Well your idea seems viable but only one way to know if it will pass is to submit. I have had no use for subscriptions yet so i cannot give you a best case to use. That being said, it looks like Non-renewing subscriptions need to be handled by you and renewable subscriptions can be handled by Apple. I cannot say that this is the case 100% but if so, you could make one restore button that checks for apple restore first then if the user does not have anything to restore from Apple, ask for login. I do not know how your app functions but that is just one idea, i do not see a problem with your idea as long as your are giving the user every chance to restore logins/content/passwords. You are so i would give it a shot! [import]uid: 126161 topic_id: 28612 reply_id: 116618[/import]
FWIW, our implementation was accepted by Apple
[import]uid: 166004 topic_id: 28612 reply_id: 117874[/import]
Hey, forgot to inform you all, our app was also accepted by apple… thanks for all your support… [import]uid: 71670 topic_id: 28612 reply_id: 117953[/import]