Search Unity

Restore purchases in iOS (Apple policy message)

Discussion in 'Unity IAP' started by Etsai, Mar 5, 2020.

  1. Etsai

    Etsai

    Joined:
    Sep 12, 2014
    Posts:
    24
    HI,
    When developing for iOS I always add the mandatory button "Restore purchases" somewhere in the app. With no problems with this (+10 games) using this well-known call based on Unity IAP plugin:

    Code (CSharp):
    1.  m_StoreExtensionProvider.GetExtension<IAppleExtensions>().RestoreTransactions(
    2. (result) => {Debug.log("RestorePurchases continuing: " + result);});
    But yesterday I received this message from Apple:

    We found that your app includes a feature to restore previously purchased in-app purchase products by entering the user's Apple ID and password. However, Non-Consumable in-app purchases cannot be restored in this manner.
    To resolve this issue, please revise your binary to implement your own restore mechanism, if you would like users to be able to restore Non-Consumable in-app purchase products.
    More information on in-app purchase product types is available in App Store Connect Help.
    https://help.apple.com/app-store-connect/#/dev3cd978dbd

    As far as i know, Non-Consumable IAP purchases MUST be restored in this manner...

    Does this make sense for you? Did Apple change their purchasing policies and we should wait for Unity IAP plugin to be updated?

    Thak you!
     
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    We are checking on this.
     
  3. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  4. game5mobile

    game5mobile

    Joined:
    Sep 25, 2013
    Posts:
    3
    Yeah It's funnier now even for consumable!

    I just got this:

    We found that your app includes a feature to restore previously purchased in-app purchase products by entering the user's Apple ID and password. However, consumable in-app purchases cannot be restored in this manner.

    Specifically, “Restore mechanism” should be removed for consumable in-app purchase.

    To resolve this issue, please revise your binary to implement your own restore mechanism, if you would like users to be able to restore consumable in-app purchase products.


    I have my own restore mechanism and 0 non-consumable items in the IAP though, I thought restore purchase button was mandantory no matter your IAP items you have
     
  5. Etsai

    Etsai

    Joined:
    Sep 12, 2014
    Posts:
    24
    It makes sense in your case. Restore purchases button is not mandatory in consumable items. You may add one, using your own mechanism of course, and probably with some cloud based storage.
     
  6. Etsai

    Etsai

    Joined:
    Sep 12, 2014
    Posts:
    24
    Let´s see if the reviewer assumes his/her mistake...
     
  7. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    You should not Restore consumable items. If a user purchases 50 Gold Coins for example, they would simply Restore each time when their coins run low.
     
  8. zenasprime

    zenasprime

    Joined:
    Mar 31, 2010
    Posts:
    166
    I'm having the same problem.

    So if I'm understanding this correctly, if a user loses their in game currency purchase for some reason, they are simply out of luck?
     
  9. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    626
    The app store does not provide the feature of restoring consumable products. You may want to store consumable products on the cloud to restore consumables.

    https://docs.unity3d.com/Manual/UnityIAPRestoringTransactions.html
    When a user reinstalls your application they should be granted any Non-Consumable or renewable Subscription products they already own. App stores maintain a permanent record of each user’s Non-Consumable and renewable Subscription products which Unity IAP can retrieve.
     
  10. MigrantP

    MigrantP

    Joined:
    Jun 24, 2013
    Posts:
    119
    We just got the same response with an app rejection. It makes no sense. We responded with links to the SDK documentation that says to use StoreKit for restoring non-consumables. @Etsai what happened with your case?
     
  11. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Yes, for non-consumables you are required to have a Restore button on iOS. Codeless IAP has a Restore button type. If you're using scripted IAP, you'll need to code a Restore button (if you haven't already) https://docs.unity3d.com/Manual/UnityIAPCodelessIAP.html
     
  12. MigrantP

    MigrantP

    Joined:
    Jun 24, 2013
    Posts:
    119
    We have a restore button, and its location is given in the reviewer notes for the IAP. This is the second IAP for the app. If it's not clear, we got the same message that basically said "You shouldn't use StoreKit API for restore purchases for non-consumables" which is bonkers.

    Here it is in full:

    Guideline 3.1.1 - Business - Payments - In-App Purchase


    We found that your app includes a feature to restore previously purchased in-app purchase products by entering the user's Apple ID and password. However, non-consumable in-app purchases cannot be restored in this manner.

    To resolve this issue, please revise your binary to implement your own restore mechanism, if you would like users to be able to restore non-consumable in-app purchase products.

    More information on in-app purchase product types is available in App Store Connect Help.​
     
  13. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Interesting, I am checking
     
  14. Etsai

    Etsai

    Joined:
    Sep 12, 2014
    Posts:
    24
    We wrote them back, explaining and showing their own documentation parts, but the same bot response arrived. So we wrote to them explaining that we were going to upload a new fixed binary, and waited a couple of weeks to upload it waiting for another reviewer that time... and voila!

    EDIT: By the way, the binary was the same.
     
  15. MigrantP

    MigrantP

    Joined:
    Jun 24, 2013
    Posts:
    119
    Thanks Etsai. Not what I was hoping to hear when we're planning to launch that expansion tomorrow. I will prepare a new binary right now..

    @JeffDUnity3D Here's our response to them, no answer just yet.

    Unless there has been a policy change recently that we are not aware of, we have implemented Restore Purchases according to Apple’s Guidelines. The items in our App are non-consumable. The guidelines and SDK documentation say to use the StoreKit API for restore purchases, which we do. and therefore can be restored via the mechanism as implemented.

    From “Restoring Purchased Products” - “Users sometimes need to restore purchased content, such as when they upgrade to a new phone. Include some mechanism in your app, such as a Restore Purchases button, to let them restore their purchases.” We include a Restore Purchases button and use the StoreKit API as directed. https://developer.apple.com/documentation/storekit/in-app_purchase/restoring_purchased_products

    From “Offering, Completing, and Restoring In-App Purchases” - “When users purchase non-consumables, auto-renewable subscriptions, or non-renewing subscriptions, they expect them to be available on all their devices and indefinitely. See In-App Purchase for more information. The app provides a UI that allows users to restore their past purchases. Use SKPaymentQueue’s restoreCompletedTransactions to restore non-consumables and auto-renewable subscriptions.” We use the StoreKit API as documented. https://developer.apple.com/documen...ing_completing_and_restoring_in-app_purchases

    App Review Guidelines - 3.1.1 In-App Purchase - makes no mention of Apple ID and password. It says “you should make sure you have a restore mechanism for any restorable in-app purchases” and we do using the method for non-consumables required by Apple SDK documentation.​
     
    Sailendu and JeffDUnity3D like this.
  16. MigrantP

    MigrantP

    Joined:
    Jun 24, 2013
    Posts:
    119
    @JeffDUnity3D We're trying again with a build bump. One thing that may be a factor is I tried using the restore purchases button in the test flight version, and it got a success callback from Unity IAP but nothing seemed to happen (no password request, no IAPs restored). There isn't anything logged so I can't tell if anything actually happened. This could be just a temporary issue in TestFlight though, we've seen weird behaviour there often.
     
  17. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    If you got a success callback, that means that Restore was successful. You award the product in your success method.
     
  18. MigrantP

    MigrantP

    Joined:
    Jun 24, 2013
    Posts:
    119
    @JeffDUnity3D Hmm, so I put a testing version on TestFlight with more logging. With a fresh install: When I call IAppleExtensions.RestoreTransactions(), the callback is immediately called with success = true. There is no Apple ID or password popup. ProcessPurchase is not called as the Unity documentation says it should be. None of the products have receipts (before or after: hasReceipt = false). I can still initiate a purchase and get the "you've already purchased this" flow from StoreKit, and that goes through fine. Then, if I kill and relaunch the app, the other IAP shows up as purchased during initialization time.

    When I use our Restore Purchases button on the App Store shipped version, it works properly. But not here.. so I'm not totally sure it's going to work if/when it gets approved.
     
  19. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Got it, I wasn't sure if you were using Codeless. And this user has previously purchased a non-consumable or a subscription?
     
  20. MigrantP

    MigrantP

    Joined:
    Jun 24, 2013
    Posts:
    119
    Yeah, this is my own user on TestFlight. I've purchased both non-consumable IAP.
     
  21. MigrantP

    MigrantP

    Joined:
    Jun 24, 2013
    Posts:
    119
    Well, the resubmission with the exact same build (sans build number bump) was approved. I'll take it =)
     
    Marcos-Elias and JeffDUnity3D like this.