Search Unity

ios Restore Transactions appears to refresh receipts rather than restore.

Discussion in 'Unity IAP' started by playsportmatt, Jan 25, 2019.

  1. playsportmatt

    playsportmatt

    Joined:
    Sep 1, 2016
    Posts:
    5
    Hi, I'm following your example code for restoring transactions: https://docs.unity3d.com/Manual/UnityIAPiOSMAS.html

    Code (CSharp):
    1. mExtensions.GetExtension<IAppleExtensions>().RestoreTransactions(OnRestore);
    However, the external receipt validation (PlayFab) fails because the receipt has already been used. This seems to suggest the receipts are being refreshed rather than restored, which as I understand it would produce a new transaction & receipt - https://developer.apple.com/documen...23-restorecompletedtransactions?language=objc

    Additionally the docs say the user's password will be required to restore purchases, I'm not being asked for a password when trying to restore. I am asked for a password every time I purchase an item.

    I'm extracting the receipt like so:

    Code (CSharp):
    1. var wrapper = (Dictionary<string, object>)MiniJson.JsonDecode(e.purchasedProduct.receipt);
    2. var payload = (string)wrapper["Payload"];
    Is there something I'm missing or need to setup for this to work as expected?

    I am using 2018.2.4f1, the services tab says IAP is up to date, and the IAP package is 2.0.3 in the package manager.
     
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    I am checking with the IAP team here, but I don't believe Restore creates a new transaction and receipt.
     
  3. playsportmatt

    playsportmatt

    Joined:
    Sep 1, 2016
    Posts:
    5
    It's this part of the Apple docs that suggest to me there should be a new receipt, there's a new transaction anyway.

    "The payment queue delivers a new transaction for each previously completed transaction that can be restored. Each transaction includes a copy of the original transaction."

    Perhaps I'm wrong, but if that's the case how does receipt validation work? I'm just getting errors about it being the same receipt.

    Also, as mentioned above I'm not being asked to enter a password for the restore in sandbox either.
     
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    You would want to contact Apple about the password in the Sandbox. You might count it as a blessing however, previously, a few months ago anyway, users were constantly being asked for their Sandbox password. So Apple may have removed it altogether. And do you really want to check a receipt on a Restore operation? A restore implies they already successfully and legitimately purchased previously.
     
  5. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,259
    Jumping in on this...

    Yes, I would really want to check the restore receipt again, especially when using PlayFab: when users are getting new devices, logging in with PlayFab creates a new account for them. If they forgot adding a persistent login method (like Facebook, or Google), they are forced to use their new PlayFab account. In this case, restoring purchases with Unity IAP & validating receipts fails, due to the receipts being used on a different PlayFab account already - because the transaction id in the restore receipt is the same. So on their new account, they are never able to get the product.

    I created a FogBugz entry for this in 2017 and it was never answered: 932848.
    Source
     
    JeffDUnity3D likes this.
  6. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,259
    Is this being looked at or should I create a new bug report with a recent Unity version (same information though)?
     
  7. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    A bug report would not be necessary. Keep in mind that Apple returns all products in each receipt. Your users create their own PlayFab account? Perhaps I missed your point. Would this not be a PlayFab issue then?
     
  8. cabbyU

    cabbyU

    Joined:
    Sep 21, 2016
    Posts:
    18
    With PlayFab it's possible for this scenario to occur:

    1) A user creates an anonymous PlayFab account on one device and purchases a non-consumable
    2) The user gets a new device hooked up to the same iTunes account and creates a new anonymous PlayFab account (since there's no way to login to an anonymous account on multiple devices).

    On the second device, the user will never be able to purchase the non-consumable item, because according to iTunes it has already been purchased, and according to Playfab it has already been redeemed by the first anonymous account. PlayFab needs a new receipt in order to redeem the item on the second anonymous account, but as far as I can tell there isn't any way to do this with Unity. I'm also having this issue, and I'm now in the process of writing custom restore functionality because the built-in RestoreTransactions function appears to refresh rather than doing a true restore with new receipts.
     
  9. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Restore across devices is currently broken in IAP 1.22. You might test also with IAP 1.19 to confirm. But the user would not be expected to purchase the non-consumable again. But the product "Should" be restored when you call the Restore method https://docs.unity3d.com/Manual/UnityIAPRestoringTransactions.html and ProcessPurchase would be expected to fire for the product upon restore.
     
  10. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,259
    The issue is that the product is restored, but with the same transaction identifier. Which is different from what Apple mentions as I wrote above. We cannot send the same transaction identifier to PlayFab multiple times. I have actually given up on this ever getting fixed.
     
  11. alimustafa90

    alimustafa90

    Joined:
    Jul 23, 2017
    Posts:
    1
    Apple documentation says that there are two unique identifiers in their receipts, an
    original_transaction_id
    and a
    transaction_id
    . These IDs can be used to
    Unity IAP apparently refreshes the original transactions on restoring non-consumable purchases. This results in getting the same
    transaction_id
    as the
    original_transaction_id
    . There can be multiple use cases that need a unique transaction ID on restore purchases, like to prevent fraudulent purchases by re-using a valid receipt. One way to prevent this is to save the unique transaction ID on the server whenever any user makes a purchase, and check for the existence of a transaction ID on the server before rewarding the purchase to the user. But this logic currently doesn't work in Unity since restore purchase returns the original transaction ID that already exists on the server, and the transaction is considered as duplicate. I'm guessing the same logic is used by PlayFab.
     
  12. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    We have no control over the receipts returned by the stores.
     
  13. AllWallsWillFall

    AllWallsWillFall

    Joined:
    Nov 21, 2012
    Posts:
    2
    Im running into the same problem. Unity IAP does not return a restore receipt but the original receipt resulting in "Receipt already used" error being returned from Playfab. Considering that restoring purchases is a mandatory feature on iOS, this means Unity IAPs can't be used with backend service on iOS. I really don't want to have to change tools at the 11th hour but unless this is fixed, I have no choice.
     
  14. Neonlyte

    Neonlyte

    Joined:
    Oct 17, 2013
    Posts:
    515
    The problem isn't with Unity IAP, really. Since iOS 7, Apple uses a single App Receipt that records all the transactions for each app. When one calls the Unity IAP API to restore IAP, what really happens is that iOS replays all the previous transactions with new transaction objects (and thus new transaction IDs), which Unity passes back to the game logic, but the App Receipt does not recreate itself with new IDs. Take a look at Apple's guide on restoring transaction. Nowhere in the document says that the app receipt would be regenerated with new IDs.
    https://developer.apple.com/documen...se/restoring_purchased_products?language=objc

    The problem is with the decision of PlayFab to only accept IAP transactions once to stop cheating, which I favor. If IAP items is set as non-consumbale, unless you want to prevent people from using others' Apple ID to cheat the IAP items for free, it is best not to verify the receipt through PlayFab but instead verify it on-device, or roll your own verification server.

    Another approach is to set IAP items as consumable.

    Either way, it is best to provide a user ways to recover their PlayFab account, e.g. ask them to provide email/password or link with a third party account. When a user signs into another device using the same account, query its inventory from PlayFab to restore purchases.
     
  15. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,259
    While I agree restoring from PlayFab's player inventory directly is the most secure approach, the issue of duplicated transaction IDs is still with Unity IAP. From the Apple developer site link:

    The receipt created and delivered to Unity IAP has a different transaction ID as stated by Apple. However, Unity IAP uses the "original_transaction_id" on restore, thus returning a duplicate transaction to PlayFab. The case is documented in the bug report above and honestly, it should not be that difficult to provide the correct transaction ID. It is clear that the priority is somewhere else though.
     
  16. Neonlyte

    Neonlyte

    Joined:
    Oct 17, 2013
    Posts:
    515
    The transaction is new, but the receipt is not. Do note that you are submitting the App Receipt to PlayFab, not the transaction objects. The original transaction in the receipt does not change no matter how many times you restore it -- the system only sync with the original copy from App Store.
     
  17. Neonlyte

    Neonlyte

    Joined:
    Oct 17, 2013
    Posts:
    515
    By the way, this screenshot is from is the Unity IAP source code that you can also observe in your exported Xcode project.

    Here, Unity never passed back any original transaction IDs, which in iOS is retrieved by calling "transaction.originalTransaction.originalTransaction".
    QQ20200419-193313@2x.png
    QQ20200419-192431@2x.png

    Here's is their logic of "selectReceipt:" method
    QQ20200419-193423@2x.png
     
  18. m-Stratikopoulos

    m-Stratikopoulos

    Joined:
    Feb 19, 2014
    Posts:
    9
    Is there any update on this? This is mandatory in order to publish for IOS. The apps will get rejected due to this.
     
  19. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    FWIW, we have many developers successfully publishing on iOS. I will mention this again to the IAP team
     
  20. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Can you describe what you would expect to see here?
     
  21. Neonlyte

    Neonlyte

    Joined:
    Oct 17, 2013
    Posts:
    515
    Oh I was just trying to tell them that restoring receipt has nothing to do with transaction IDs.
     
  22. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Can you elaborate?
     
  23. chad47

    chad47

    Joined:
    Dec 17, 2015
    Posts:
    4
    This post might be relevant:

    https://community.playfab.com/questions/9957/ios-7-style-itunes-receipt-failing-restoreiospurch.html

    Brendan says that the apple gives a "refresh receipt" instead of a restore receipt. A refresh receipt is not unique but a restore receipt is unique so that is what is needed (for playfab).

    "In all the cases I've managed to find, there isn't a response from Apple stating how to use appStoreReceiptURL to get a Restore receipt instead of a Refresh receipt. Developers appear to largely be falling back to using the transactionReceipt, despite it having been deprecated (and because Apple have called it out as the fall-back to use)."
     
  24. OneManEscapePlan

    OneManEscapePlan

    Joined:
    Oct 14, 2015
    Posts:
    222
    We're running into the same issue, which is preventing us from restoring purchases on PlayFab on iOS.
     
  25. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Got it, I have alerted the dev team.
     
  26. pantoygames

    pantoygames

    Joined:
    Mar 23, 2019
    Posts:
    1
    Is there an update to this? I am using Unity 2019.4.13f1 and IAP 2.1.1 still receiving the refresh receipt
     
  27. nindim

    nindim

    Joined:
    Jan 22, 2013
    Posts:
    130
    Hi @JeffDUnity3D ,

    We are having similar problems using UnityIAP and PlayFab, please see these posts for more information where there are quite a few other users running into this issue as well.

    https://community.playfab.com/questions/27917/ios-restore-purchase-receipt-using-unity-iap.html
    https://community.playfab.com/questions/6045/restoring-purchases-multiple-playfab-accounts.html
    https://community.playfab.com/questions/5815/receipt-validation-iosandroid-after-restore-purcha.html
    https://community.playfab.com/quest...nity-provide-the-ios-restore-purchase-re.html

    As PlayFab keeps a list of redeemed receipts (to avoid players amassing an item multiple times and paying once), a unique new receipt must be used for each purchase (and each restore) for the items to be successfully awarded on the server.

    As it stands, this is game breaking for us. I would expect that if the problem is in UnityIAP then anyone doing receipt validation alongside selling non-consumables would be running into these same issues...

    Would you perhaps be able to get in touch with the PlayFab guys direct? It could be an issue their end with how they are detecting the already used receipts for instance!

    Thanks a lot for your help.

    Niall
     
  28. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Please share the code that you are using. Those posts are old, please test with IAP 2.2.6
     
  29. Job_MTalha

    Job_MTalha

    Joined:
    Jan 14, 2021
    Posts:
    61
    Hi, I was just implementing the same thing. what if we save the user's device id (before he switches the mobile) in google play saved game file and after he switches the his device. just call that saved game file from google play, grab the deviceID key and log the user into his same playfab account. For this to work user must always have one google play account. What do you think? I'll continue reading this thread.
     
  30. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Not sure what you mean by "saved game file". But feel free to test.
     
  31. Foxbyter

    Foxbyter

    Joined:
    Sep 28, 2019
    Posts:
    3
    I can confirm that this is still an issue for anybody trying to restore purchases on iOS when using PlayFab with Unity IAP 4.1.3. Still receiving refresh receipts where restore receipts should be provided. Our app got rejected by Apple because of this.

    btw. I don't think that Job_MTalha said anything about hacking Google security Jeff :)
     
  32. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Not sure what you mean by restore receipts. In particular, during the restore operation, you should expect ProcessPurchase to be triggered for each non-consumable and subscription product. What was the exact text of the rejection?
     
  33. Foxbyter

    Foxbyter

    Joined:
    Sep 28, 2019
    Posts:
    3
    Andy from PlayFab summarizes it nicely in his response here :
    https://community.playfab.com/quest...nity-provide-the-ios-restore-purchase-re.html

     
  34. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  35. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    We have looked into this in good detail. Without doing into specifics, we are hoping that our upcoming StoreKit2 integration later this year will help here.
     
    bbridgesvb and Foxbyter like this.
  36. unity_C04A99B9AF3268C39B1B

    unity_C04A99B9AF3268C39B1B

    Joined:
    Feb 13, 2022
    Posts:
    1
    Hello, Also getting this issue using unity IAP 4.9.3.
    after purchasing non consumable when i uninstall the game and install again in same Iphone i can't restore my purchases until i make on payment.
    please help if any one have any solution regarding this.