Search Unity

Non-consumable purchases occasionally not recognized

Discussion in 'Unity IAP' started by tessellation, Jan 22, 2020.

  1. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    We're having an issue occasionally with Google Play customers. We use Unity 2017.4.35f1 with UnityIAP 1.23.1 and we use client-side purchase validation.

    There's a scenario that comes up occasionally when someone purchases a non-consumable and then they somehow repeat buying the same item with Google Play, but that second transaction is declined for whatever reason. I've taken a screenshot from the Google Play store to explain what we see in these cases:

    Screen Shot 2020-01-21 at 5.02.39 PM.png
    NOTE: Google Play shows most recent orders first in the list, so the second purchase is first above (the declined one).

    When this scenario happens, UnityIAP fails to recognize that the first transaction was approved so our game never awards the purchase. This could either be because ProcessPurchase never gets called (even after restarting the app) or the CrossPlatformValidator fails to validate the receipt. When the receipt fails to validate, the game does not award the purchase and then returns PurchaseProcessingResult.Complete.

    Let me know if you think we're doing something wrong or whether this is a problem with UnityIAP.
     
    Last edited: Jan 22, 2020
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Are you able to reproduce? We have heard similar reports, and looking into it. Are you handling the PurchaseFailure callback also? You may be receiving "UserCancelled" on the first purchase, but it still seems to charge the user.
     
  3. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    I can't think of a scenario for how to reproduce this exactly. My closest guess would be to do something like:
    1. Hack the build so that we return PurchaseProcessingResult.Pending from ProcessPurchase and not award the purchase.
    2. With that hacked build, perform a non-consumable test purchase.
    3. Hack the app again so in the code we register all the IAP items as consumable and perform the same purchase, but this time use the payment that always fails.
    4. Restore the app with the items as non-consumable and make ProcessPurchase return a Complete result.
    5. Clear the storage/cache on the installed app.
    6. Run the app and see if/why it's not able to recognize/restore the first, successful purchase.
    Yes, but we don't revoke the product or anything, we just alert the user of an error using a message box. If the result is UserCancelled, then we do nothing.
     
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Sorry, I meant reproduce as your customers do. Can you confirm that these users are receiving the PurchaseFailed callback? I suspect you may not know, unless you have their device logs or can reproduce yourself.
     
  5. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    Thanks for the quick replies @JeffDUnity3D.

    The customers recounts of the event are strange. One said that "google charged me twice and then reversed the duplicate charge" but I don't know if Google did that automatically or if they had to talk to Google Play support about it.

    Correct, I don't know and I don't have the logs. Even if I did log this to Unity Diagnostics, it would be hard to know which customer's device it was for.

    Hope that helps.
     
  6. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    I'm wondering if any progress has been made regarding this problem. I continue to get complaints from users who say their purchases were never awarded. Here's an example from one in January:

    Screen Shot 2020-02-19 at 10.02.13 PM.jpg
     
  7. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Do you have code to handle the PurchaseFailed callback? Just checking, this is where you would notify the user that the purchase did not succeed in a pop up or similar. Granted not a solution, but would help us to understand the transaction flow in this scenario.
     
  8. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    Yes, we pop up a message in this case to display the error to the user. In the above scenario, there are no failure errors shown to the user. The only symptom is that their purchase is never awarded.

    If you could show this scenario to a UnityIAP Engineer, I think this might help. I believe what's happening is that, for a given IAP product, the Unity IAP code parses the receipts in chronological order. If it finds a newer "cancelled" or "payment declined" receipt, it assumes that this receipt "invalidates" a previous purchase on the same product. This could be true for a "refund" (which replaces the state of an existing "charged" purchase), but not for a separate "cancelled" receipt. As long as a previous "charged" receipt went through, this should not count as a revoked product purchase. The key here is that these "cancelled" or "payment declined" receipts have a completely different Order ID from the successful one, yet somehow Unity IAP is using these newer, failed receipts as the commander of the product's current purchase state, which isn't the correct behavior.

    To summarize, I believe the way it should work is that if ANY order ID for a given product is successful, the product should be considered successfully purchased, regardless of how many non-successful order IDs are there for the same product, and regardless of time-order.

    Please let me know what you find out.
     
    Last edited: Feb 22, 2020
  9. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Sorry, no, we don't parse the receipts in our processing as you suggest. We are essentially a pass through service for the native APIs. We are expecting either a ProcessPurchase or onPurchaseFailed for every transaction, but it looks like a possible issue in the store library code when we don't receive either one. We are working with the developers at Google to hopefully find a resolution.
     
  10. tessellation

    tessellation

    Joined:
    Aug 11, 2015
    Posts:
    390
    I see, thanks for looking into it.