Search Unity

Question Restore Purchase

Discussion in 'Unity IAP' started by compyler, May 2, 2023.

  1. compyler

    compyler

    Joined:
    Mar 30, 2020
    Posts:
    102
    I have a simple question about restoring purchases on iOS.

    In my game I have a "restore purchases" button that executes this code:
    Code (CSharp):
    1. public void RestorePurchases() {
    2.         if(initializationStatus != InitializationStatus.Succeeded) {
    3.             return;
    4.         }
    5.  
    6.         IAppleExtensions iosExtensions = storeExtensionProvider.GetExtension<IAppleExtensions>();
    7.         iosExtensions.RestoreTransactions((result) => {
    8.             if(result) {
    9.                 Debug.Log("RestorePurchases. Positive result: " + result);
    10.             }
    11.             else {
    12.                 // Restoration failed.
    13.             }
    14.    
    15.         });
    16.     }
    If I understand the docu correctly, pressing the button will then trigger ProcessPurchase() for all items that are already bought. ProcessPurchase() looks like this:
    Code (CSharp):
    1. public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) {
    2.         string productId = args.purchasedProduct.definition.id;
    3.  
    4.         switch(productId) {
    5.             case Product_removeAds:
    6.                 gameManager.GameState.removeAds = true;
    7.                 gameManager.SaveGameState();
    8.                 buyProductSucceeded?.Invoke(productId);
    9.                 break;
    10. ...
    My problem: ProcessPurchase() calls callback buyProductSucceeded?.Invoke() which will eventually show a dialog "Purchase successful". I did this cause ProcessPurchase() is also called when the user buys an item in the shop and then its desired to show a success dialog.
    But when ProcessPurchase() is called cause the user pressed "Resore Purchases", I do NOT want to show a success dialog (imagine if 3 items are restored, the user would see 3 dialogs).

    How can I suppress dialogs during restore phase? How can I detect that ProcessPurchase() was called because of a "Restore Purchase" (and not a real initial purchase)?
     
  2. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,268
    Unity IAP cannot send you that information, because it treats restores and purchases the same. In another thread it was mentioned that this functionality might be provided in a future update, maybe with support for StoreKit2.

    Currently, one way to work around this is by:
    - saving the current application time when the user pressed your "Restore" button
    - in ProcessPurchase, check whether that time was within ~10 seconds
    - if so, do not show your "Purchase successful" UI message
     
  3. compyler

    compyler

    Joined:
    Mar 30, 2020
    Posts:
    102
    Thanks for your reply Baroni.
    I already feared Unity does not provide me this information.

    I solved it this way: When the Restore Purchases Button is pressed, I call IAPManager.RestorePurchases() and this method sets a private member isRestoreProcessRunning = true. While this flag is true, IAPManager.ProcessPurchase() will NOT call the callbacks (so no dialogs pop up). In RestoreTransactions() I reset the flag.

    I could not test the code on an iOS device yet but I hope it works:)
     
  4. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,268
    Yeah you definitely want to test, as there could be a delay with the ProcessPurchase method being called after a restore. Meaning, the IAppleExtensions.RestoreTransactions callback could be called when it has sent all transactions for restore, but before they are actually processed (so at that point your flag is false already and still invokes the UI popup).
     
  5. compyler

    compyler

    Joined:
    Mar 30, 2020
    Posts:
    102
    You are right, that would be really bad. I assumed the RestoreTransactions callback is GUARANTEED to be called after all ProcessPurchase() methods have been called. If this is not 100% guaranteed my code does not work. Then I probably have to user a timer like you mentioned but thats never gonna be 100% safe :(

    Can anyone confirm (or deny) that the RestoreTransactions callback is only ever called AFTER all ProcessPurchse() calls have been performed?

    I am actually totally baffled that it seems like I am the first one that has this problem (did not find any other thread). I think what I want is absolutely standard: Give a confirm message when a manual purchase was successfull but when you restore 10 items you do NOT want to show 10 confirm messages. Really really suprised Unity API does not cover this ;(
     
    Last edited: May 5, 2023
  6. Yannick_D

    Yannick_D

    Unity Technologies

    Joined:
    Feb 21, 2022
    Posts:
    235
    The RestoreTransactions callback is Apple's confirmation that they will send the restored transactions, but you will usually be receiving that callback before any restored transactions reaches the ProcessPurchase.

    We recently added Product.appleProductIsRestored which should help with the handling of restored transactions.
    Does this help for your case to avoid showing the confirmation message on restored transactions?
     
  7. PeterGost

    PeterGost

    Joined:
    Jan 27, 2020
    Posts:
    18
    I have 3 different items that the user can purchase. Do I need to implement 3 different Restore buttons - or one is enough? I am using codeless IAP.

    Bunch of thanks
     
  8. Yannick_D

    Yannick_D

    Unity Technologies

    Joined:
    Feb 21, 2022
    Posts:
    235
    Just a single button, it will restore every transactions!
     
  9. T-1K

    T-1K

    Joined:
    Jun 1, 2021
    Posts:
    6
    What is the equivalent way/property for the Google Play store. I want to distinguish ProcessPurchase calls for whether it is a restore or a pending purchase or a new purchase call?
     
  10. Yannick_D

    Yannick_D

    Unity Technologies

    Joined:
    Feb 21, 2022
    Posts:
    235
    On the Google Play Store, because the transaction ids don't change, the restored ones will not be processed again so there's nothing to do for those in the ProcessPurchase.

    For deferred purchases, since IAP 4.6.0, these are no longer sent to your ProcessPurchase, so there's nothing to do too.

    For pending purchase (paid, but not acknowledged), these will still be processed on every application launch until they are acknowledged, otherwise they get refunded after 72h. We don't have anything in place to detect if these have already been through the ProcessPurchase (they are always sent to it). If this is a need for you, could you tell us more about your use case?
     
  11. T-1K

    T-1K

    Joined:
    Jun 1, 2021
    Posts:
    6
    My use case is very similar to OP's case, have to distinguish ProcessPurchase call reason(restore, pending, new purchase). We want to give different UI feedbeacks to user for each one them.

    From Restoring Transactions
    From Processing Purchases
    What I understand from these is that on the Google Play Store ProcessPurchase is going to be invoked automatically after new installs and pending purchases on application restart. Not fully tested yet.
    I am a bit confused. Are you saying ProcessPurchase wont invoke or you dont have to do anything about them?

    And what is deferred pruchase? :rolleyes: I dont encounter them on docs.
     
  12. Yannick_D

    Yannick_D

    Unity Technologies

    Joined:
    Feb 21, 2022
    Posts:
    235
    You're right, for new installs, this should be called!
    It's in cases where it was already processed that you won't be getting the ProcessPurchase for that same transaction again (on Google Play Store).

    Purchase approvals is one example of deferred purchases where a transaction is created for a product, but the payment hasn't been done yet.

    If you're using IAP 4.6.0 and above, I think this could help you GetPurchaseState
     
  13. game_unity849

    game_unity849

    Joined:
    Sep 27, 2021
    Posts:
    14
    Excuse me...
    Could you also confirm about restore purchases on google?

    https://forum.unity.com/threads/google-play-store-restore-purchase.1479192/