Search Unity

User's purchase success, but OnPurchaseFailed() is called

Discussion in 'Unity IAP' started by YujenDev, Dec 27, 2018.

  1. YujenDev

    YujenDev

    Joined:
    Oct 21, 2014
    Posts:
    7
    Our team receives this issue from some players.
    Players purchase consumable product, but don't get ProcessPurchase() called.
    We test on some android devices and emulators,
    it seems can be reproduced on some old version android environment.

    Description
    When user enable the google IAP interface, click BUY button, and click other interface space area quickly.
    It will cause this order success, but OnPurchaseFailed() is called, and
    return parameter is PurchaseFailureReason.UserCancelled.

    Unity Version
    2017.4.14f1

    Unity IAP version
    1.20.1

    Platform and Store
    Android GooglePlay IAP
     
    domodsc likes this.
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Would "other interface" be part of the same Unity game? So touching any other background object should also show this behavior?
     
  3. YujenDev

    YujenDev

    Joined:
    Oct 21, 2014
    Posts:
    7
    Thanks for fast reply.
    The "other interface space area" is google IAP interface.
    I upload our game's IAP screenshot.
    If I click BUY button, and click the upper background area will close IAP interface.
    I guess it could interrupt the purchase process, and cause player receives google's receipt, but can't get IAP item.
     

    Attached Files:

  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    If you click the BUY button, that dialog should go away. And the background in red in your screenshot is just your game, correct? The only "Goggle IAP Interface" is the Buy button. Do you mean click the Buy button, and then quickly click (touch) your game ?
     
  5. YujenDev

    YujenDev

    Joined:
    Oct 21, 2014
    Posts:
    7
    The background is a part of Google IAP interface.
    It seems like we can't control this background's behavior.
     
  6. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    No, the background is not the Google IAP Interface. There looks to be a banner ad or your game interface, and a purple icon with a score on it at the very top. What does the text say?
     
  7. YujenDev

    YujenDev

    Joined:
    Oct 21, 2014
    Posts:
    7
    I misunderstand the background :confused:
    The text is product name and description, purple icon is game currency.
     
  8. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @YujenDev At any rate, we will investigate.
     
  9. YujenDev

    YujenDev

    Joined:
    Oct 21, 2014
    Posts:
    7
  10. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Can you confirm that this happens on all Android versions, or just a subset?
     
  11. YujenDev

    YujenDev

    Joined:
    Oct 21, 2014
    Posts:
    7
    Hi Jeff,
    The deviceModel.txt is latest collected device information.
    It's seems can happen on any version.
     

    Attached Files:

  12. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  13. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    Hi, I would like to add that we are also seeing this similar issue happening to a large number of users that write to us. On both Android and iOS, primarily Android.

    Unity Version
    2017.4.11f1

    Unity IAP version
    1.20.1


    We see that some players charged for failed transaction. From the data of affected users, we see that they receive the 'onPurchaseFailed' event with 'User Canceled' failure reason, usually followed by many 'Duplicate Transaction' failure reasons.

    My questions are

    1. There seems to be a bug with allegedly UserCanceled purchase getting through and charged, if Unity IAP thinks user canceled the purchase, the user should not get charged the transaction.

    2. When Unity IAP calls `OnPurchaseFailed`, besides the PurchaseFailureReason.ExistingPurchasePending failure reason, should we consider the purchase terminated right there? Is it safe to remove it from our own cache of pending purchases?

    For 2, asking because we are also seeing that sometimes the supposedly 'User Canceled' transaction was actually a pending transaction that would be recovered on next app install (and Unity IAP initialization) therefore leading to a call of 'ProcessPurchase'.
     
    YujenDev and domodsc like this.
  14. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    A purchase left in Pending would indeed trigger ProcessPurchase on next app launch. Are you able to reproduce? Please provide specific steps if so, with the sample project.
     
  15. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    Thanks for getting back @JeffDUnity3D . Yes understood that a pending purchase would trigger ProcessPurchase on next app launch, my question is why would Unity IAP informed us that purchase was 'failed with reason user canceled' when in fact it was pending.
     
    domodsc likes this.
  16. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @thingiebox Correct, that is the issue that we are investigating, and is currently not determined. Can you provide steps to reproduce in your situation?
     
  17. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    @JeffDUnity3D based on our users' descriptions and data we've seen, we have repro steps that have to do with attempting purchases under poor network connection.

    Unity Version
    2017.4.11f1

    Unity IAP version
    1.20.1

    Android version
    7.1.2 (probably not relevant)


    1. Initiate purchase on a consumable product, you will see native google play dialogue prompting you to tap to buy
    2. After hitting `Buy` button, immediately enable throttling of the network via Charles Proxy, make the throttling very very bad (e.g. something like single digit bandwidth, 40% reliability etc, can share my settings if needed), at this point, you should see the native purchasing dialogue spin like it is trying to process the purchase. This will go on for a good minute.
    3. You will eventually see a `Error. Connection timed out` message via the native dialogue. Hit `ok' (that's the only option). At this point, in logcat you will see that the `OnPurchaseFailed` event got fired with failureReason UserCanceled.
    4. Disable connection throttling, tap to buy the same product, you will get the `Error. You already own this item` message prompt in the google play native dialogue. Once you hit 'ok' on that, in the logs, you can see that, `OnPurchaseFailed` event got fired again with the reason `DuplicateTransaction`

    The bug is that under this circumstance, user got charged but did not get the item. Restarting the app to reinitiate IAP did not see any pending transactions come through (and call ProcessPurchase) in the above repro.

    We have inconsistent repro on iOS that sometimes such a failed transaction (under poor network) will actually be a pending transaction and inconsistently come through on next app init (as we see ProcessPurchase gets called) even though we use local receipt validation and always set `PurchaseProcessingResult.Complete` never pending.
     
    YujenDev and domodsc like this.
  18. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @thingiebox I have reproduced using the exact same steps, thank you for providing. The IAP team mentioned that they have a fix ready for this issue, due out in the next release. No ETA, but told sometime this first quarter of 2019.
     
  19. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    thank you @JeffDUnity3D for your fast response on this! much appreciated. :)
     
  20. unity_eBJu2WjirvcnYw

    unity_eBJu2WjirvcnYw

    Joined:
    Mar 19, 2018
    Posts:
    5
    Could you suggest any workaround until the fix is ready? Is there a way to deliver the user items he purchased despite Unity never fires ProcessPurchase? And how to unblock these items? One can not buy them again, getting "Already purchased" from google and "User cancelled" from Unity? Reinstalling app didn't unblock these items. Thanks in advance for any advice on this problem.
    Upd: if I refund those blocked tranasaction from GooglePlayConsole, the next time user starts app, Unity sends ProcessPurchase for those items as if they were bought and user receives the content. So I return money to the user and nevertheless he gets the content. But if I don't do refund, the items are blocked forever and user gets nothing. Very strange Unity behavior
     
    Last edited: Jan 16, 2019
  21. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Unfortunately there does not appear to be a work around at this time. Your refund process looks valid.
     
  22. unity_eBJu2WjirvcnYw

    unity_eBJu2WjirvcnYw

    Joined:
    Mar 19, 2018
    Posts:
    5
    Sorry, didn't get why refund process looks valid.
    1. Try buy Item A, switch off internet before Google response received.
    2. Get "No internet" Google error.
    3. Turn internet on again, no processPurchase from Unity. User is charged money, but gets no content
    4. Try buy item A again, get "Already purchased" from Google and "User cancelled" from Unity every time.
    5. Go to Play Console and refund transaction for Item A. Money is returned to user.
    6. Start app again - get ProcessPurchase from Unity on the transaction that was refunded on step 5.
    7. Result - user gets his money back, but the content unlocks because Unity sends successful purchase after refund.

    Why is this behavior valid? Unity sends successful purchase event ONLY when I refund the blocked transaction. So user gets his content that was blocked on steps 1-4 only after getting his money back
     
  23. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    I was referring to your Upd: comment as a valid work around in the meantime.
     
  24. unity_eBJu2WjirvcnYw

    unity_eBJu2WjirvcnYw

    Joined:
    Mar 19, 2018
    Posts:
    5
    What exactly is valid in user getting both money back and paid content for free? I have to refund users' money, because they didn't get content, which is blocked by Uniy bug. And after I refund Unity sends successful purchase on this content. So user gets both money and content. How this can be valid?
     
    Last edited: Jan 16, 2019
  25. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    You are not following me. I simply meant that your Upd comment makes sense, should not create additional issues, is unfortunate but should work, is far from ideal, etc etc. It is a valid WORK AROUND, not a valid solution.
     
  26. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    @JeffDUnity3D just following up, wanted to confirm that regarding the bug I described above, that the fix from the IAP team will be which one of the following?

    Scenario A:
    to not charge player for a transaction that timed out due to poor network correct?

    Scenario B:
    Interrupted transaction become a pending transaction and on next IAP initialization it will be attempted to be completed. AND Unity IAP will always fire `OnPurchaseFailed` event for such a transaction for failureReason.ExistingPurchasePending.


    Asking because in order to know what inventory to award the user, we keep a `pendingPurchasesCache` that contains sku and inventory info for a purchase. As a purchase is initiated, we add to the cache a record of the purchase for what items are bought (our purchases are dynamic). For Scenario B, if the failure reason is something like `User Canceled` (as it currently stands in 1.20), we wouldn't be able to apply the inventory for the user because the purchase is no longer in pending purchase cache. We remove a purchase from the `pendingPurchaseCache` when Unity IAP fires the `OnPurchaseFailed` event (for any failure reason other than `ExistingPurchasePending`).

    So just wanted to clarify on the fix that's coming. thanks!
     
  27. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Hopefully the fix will address both issues.
     
  28. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    @JeffDUnity3D thanks for your reply. Hmm the fix should be either A or B right?

    Also thought maybe worth issuing a bug report on this, is it sufficient to include the standard IAP project with our descriptions of step to repro? I don't think in this specific case our purchasing code has any relevance.
     
  29. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    A bug report is not necessary, we are already working on the update. Regarding B, any pending transactions will trigger ProcessPurchase on next app launch. No failure callback would be expected.
     
  30. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    > any pending transactions will trigger ProcessPurchase on next app launch. No failure callback would be expected.

    Do you mean that at Step 3 of my repro description, we get the `Error: Time out` from Google play native dialogue and then no callback will be fired through Unity IAP at that point? neither success or failure
     
  31. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    No failure callback would be expected at app launch for pending transactions, only ProcessPurchase would be called. You can expect either ProcessPurchase OR OnPurchaseFailed to be called in any situation, but not both.
     
  32. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    > You can expect either ProcessPurchase OR OnPurchaseFailed to be called in any situation, but not both.

    Exactly what I would expect too. The question is what failure reason would be expected for a network connection error.

    Actually may I suggest adding to the documentation what each of the Unity IAP failureReason enums correspond to the native billing error codes?

    i.e this page https://docs.unity3d.com/ScriptReference/Purchasing.PurchaseFailureReason.html
    ideally would also have each enum refer to an error code from https://developer.android.com/google/play/billing/billing_reference
    https://developer.apple.com/documentation/storekit/handling_errors
     
  33. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Understood, we are still discussing how to handle poor networking behavior. We are trying to avoid the need to check the network prior to every call. I will pass along your comments to the IAP team, sorry for the confusion.
     
  34. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
  35. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    Wanted to follow up with one more observation/question: On Android, a timed-out transaction due to poor connectivity (as described in repro I provided above) did get called 'ProcessPurchase' on app/IAP re-launch (with good connectivity) but only after 24 hours - 3 days.

    @JeffDUnity3D any idea why the time frame varies? Would expect it to be immediate when IAP initializes. On iOS this seems more reliably immediate by restarting the app.
     
    unity_jU1dmFHEgjVstw likes this.
  36. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @thingiebox We have no control over this behavior, it's up to the stores to initiate these callbacks. Can you elaborate 24 hours - 3 days? Does it consistently but eventually show up, how many tests did you run?
     
  37. unity_jU1dmFHEgjVstw

    unity_jU1dmFHEgjVstw

    Joined:
    Sep 12, 2018
    Posts:
    4
    Hi there, our team is having the same problem. After about 1-3 days, the iap product finally got consumed, but it's not consistently, it only happened on 1 device.
     
  38. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    @JeffDUnity3D I see. thanks! Yeah on iOS, after relaunching the app in good connectivity, there are always `finish transaction: IDxxxxxxxx` calls to consume the products. On Android, all the many many tests we have done with simulating a 'timeout then already own item' error, will not see the transaction 'finish' call on app relaunch. Sometimes it will occur when restarting after 24 hours, sometimes after a few days.
     
  39. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    We are hoping that the next release will address this issue.
     
  40. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
    Thank you @JeffDUnity3D , any rough timeline for the next release?
     
  41. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  42. ChapsObb

    ChapsObb

    Joined:
    Aug 11, 2015
    Posts:
    2
  43. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    I suspect the issue has always been there, but you are welcome to try with a previous version.
     
  44. thingiebox

    thingiebox

    Joined:
    Feb 23, 2013
    Posts:
    21
  45. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  46. eladleb4

    eladleb4

    Joined:
    Apr 25, 2016
    Posts:
    57
    We are using the latest version 1.22 and still get about 1 in 25 refund requests due to "error number 4". The player is surprised he was charged but did not get the items :(
    This did not happen with earlier versions... Are you still investigating this? It's extremely hurtful for our business...
     
    ahiko-hironori likes this.
  47. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    We would need steps to reproduce. I might suggest trying to disconnect WiFi during a transaction, this is the area we are looking into.
     
  48. eladleb4

    eladleb4

    Joined:
    Apr 25, 2016
    Posts:
    57
    @JeffDUnity3D , we are a three person team and have more tasks than we can handle for our own game, we can't really spend time debugging this but we always try and investigate with our players what happened (when it happens to them).
    One thing we heard was that they took some more time to complete the transaction (chose a different credit card). It might have something to do with network connection but we it's a tricky one to reproduce using our current tools.

    In any case, every player that experiences such an issue is a huge loss for our game since these are obviously the most loyal players and they are getting the worst purchase experience...
     
    ahiko-hironori likes this.
  49. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    So all purchases work OK in your direct tests, in general, using a credit card?
     
  50. Wolar

    Wolar

    Joined:
    Sep 25, 2014
    Posts:
    38
    Hello, we are having similar/same problem we are unable to resolve. We have Unity 2018.3.14, UnityPurchasing 1.22.0, Android Version 9, Galaxy S10 (but it happens on various devices and Android version).

    We are unfortunately unable to find any solid pattern or a way how to reproduce it. We have reports from few of our users and we were able to reproduce it on our test devices few times but no solid pattern found.

    What happens is that purchase is successful (non-consumable product) on GooglePlay, user is charged but ProcessPurchase is not called. It is not called even if app is restarted. If the user tries to purchase it again, the google play will display an error that the user already owns the product but Unity calls back OnPurchaseFailed.

    It seems to be happening on both debug and live environment so with both GooglePlay test card and real card for real users.