Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

IAP Android with refunds

Discussion in 'Unity IAP' started by drizztfun, Apr 8, 2018.

Thread Status:
Not open for further replies.
  1. drizztfun

    drizztfun

    Joined:
    Jul 2, 2013
    Posts:
    25
    hello,

    i am having a problem with refunds on android test purchases. I strongly suspect the problem to be on google side, but maybe somebody has some idea:

    1. Release on alpha/beta channel, with not consumable product. Assigned Testbuyer, License testing : respond_normally
    2. Install app, Buy item, in app : .hasreceipt
    3. Issue refund, status at google : refunded
    4. IAP says i still own the item
    5. wait 24h+ : same result, still owned
    6. use adb shell pm clear com.android.vending -> NOT owned, but trying to purchase will say "Duplicate Transaction"
    7. after some minutes IAP will say again i own it, even its clearly refunded...

    If i check the receipt, it will say "purchasestate : 0".. meaning purchased

    To me it looks like unity IAP is working well, but google keeps telling my device that the item is owned...
    Could anybody direct me to a solution to this? Because i cannot purchase the item anymore for testing the process unless i keep making new products...

    - Unity 2018.1.0b12
    - IAP 1.18.0
    - HTC U11, Android 8, Stock rom, no root
    - used google account for purchasing is registered as tester, but not same like publisher account

    Apr 6 2018 21:18:51 UTC+2
    Payment pending
    Google received a new order.

    Apr 6 2018 21:18:51 UTC+2
    Chargeable
    The customer's form of payment was authorised for €0.00 and passed all risk checks. (Expires Friday, 13 April 2018 12:18:51 o'clock PDT).

    Apr 6 2018 21:23:52 UTC+2
    Charged
    The customer's form of payment was successfully charged for €0.00.

    Apr 7 2018 16:21:37 UTC+2
    Refunding
    A refund of €1.99 was initiated on this order. Reason: buyer's remorse.

    Apr 7 2018 16:26:37 UTC+2
    Refunded
    Google processed your request and applied a refund of €1.99 to this order.
     
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    I suspect this is behavior in the Google test environment, but I will check with others in the IAP team.
     
  3. kobyle

    kobyle

    Joined:
    Feb 23, 2015
    Posts:
    92
    It started to happen to me too after switching from iAP 1.16.0 to 1.18.0 so maybe it does have to do with the Unity api?
     
  4. drizztfun

    drizztfun

    Joined:
    Jul 2, 2013
    Posts:
    25
    I moved to production release with my game.
    The issue still persists sadly..
     
  5. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @drizztfun In Step 4 above, "IAP says i still own the item", can you elaborate how you are making this check?
     
  6. drizztfun

    drizztfun

    Joined:
    Jul 2, 2013
    Posts:
    25
    @Jeff
    I simply check
    .hasreceipt
    if that works, i even tried the receipt validation, and it returns a success.
    The CrossPlatformValidator, as described in the documentation.
    If i look at the receipt data, i will still see "purchasestate : 0"

    What i tried now:
    1. Remove my second account from the tester list (no alpha/beta available anymore, just release anyway)
    2. factory reset my test phone
    3. install the game

    Its still saying i bought it.. heh.. i am lost

    p.s. since my game is an epic fail anyway :p there is no rush for me now anymore.. just wondering if others have the problem too like kobyle

    Thats my first time to use unity iap. so i cannot say if the issue is new or related to the 1.18 iap
     
  7. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @drizztfun What process did you follow to issue the refund? We will test here also.
     
  8. drizztfun

    drizztfun

    Joined:
    Jul 2, 2013
    Posts:
    25
    @JeffDUnity3D
    I used the google play console
    Order management
    And there i issued a refund and had to give a reason too.

    I just attached a screenshot of the order, maybe it helps
     

    Attached Files:

  9. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Upon discussion with the IAP team, Google refunds is not something that we currently support. I have brought it up with the team as a feature request, and hopefully we will see it supported in a future release, no ETA at this time. Apologies on the inconvenience. We will be looking at parsing the receipt and see if there is sufficient information contained within it to determine if a refund has been issued.
     
  10. Etsai

    Etsai

    Joined:
    Sep 12, 2014
    Posts:
    24
    Hi,
    Any progress in this area?
    I mean, is still possible to buy a non-consumable product through Unity IAP, then request a refund to Google and still take advantage of the product for free?
     
    EduardRagimov likes this.
  11. JuicyPixels

    JuicyPixels

    Joined:
    Sep 18, 2018
    Posts:
    4
    I'm having the same problem, I purchased a product "remove_ads" and it was marked as non-consumable. Now I'd like to remove that purchase and I'm stuck. I already refunded purchase 14 days ago but it is still persistent, I was also searching for a way to force consume a product but I couldn't find any references for doing that. Does anyone have any suggestions what can I do about that?
     
  12. Etsai

    Etsai

    Joined:
    Sep 12, 2014
    Posts:
    24
    In my case, when I request the receipt for the refunded product through Unity IAP (as I understand, directly from Google), the receipt has the field purchaseState set to 0. According to Google reference this means product is purchased (and always will be 0), but I read somewhere else it may be also 1 (cancelled) or 2 (refund).

    And this is the only field I think has something to do with purchase states in Unity IAP, there are other 3rd party assets that apparently have better interaction with Google native purchasing/billing API out there...
     
  13. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    So you're refunding the user, AND want to remove their product? Isn't that a return instead of a refund in the real world? Generally after a refund, the polite thing to do for the customer is to let them keep the product and give them their money back. Also in reality, no one is likely going to pay to remove ads, then want a refund so they can then view ads. It is an isolated test scenario only. With that being said, I will be discussing the topic of refunds with the IAP team today and will convey your concerns. Also, it is common practice to create multiple test users instead of creating additional non-consumable products. Either way works.
     
  14. Etsai

    Etsai

    Joined:
    Sep 12, 2014
    Posts:
    24
    I don´t understand the difference between a refund and a return (when you want your money back you also lose your purchase). If a user regrets after paying to remove ads from the game, and claims a refund to google, he should again watch ads in the game... at least this is what I want in my game.
     
  15. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @Etsai Unfortunately there is not a refund API that is exposed by the stores that we can call. On Android devices, one technique that you could use during your testing is to clear the Google Play cache on your device which may clear the receipt for refunded purchases. Google search for the specific process on your device model. If your users contact you, you could recommend this approach to them also. But there is no programmatic solution at this time.
     
    Etsai likes this.
  16. JuicyPixels

    JuicyPixels

    Joined:
    Sep 18, 2018
    Posts:
    4
    A year ago I was using Prime31 plugin, where I was able to consume non-consumable products, after they were bought, and when I consumed it, I was again able to purchase another same non-consumable item. This is a usual path to test IAPs so I'm guessing that something can be done about that. Also clearing cache does not work, you always get purchases back. It would be kinda strange that there's not way to properly test IAPs on Android devices.
     
  17. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @JuicyPixels This thread is specific to the refund process. If you are concerned about a separate issue with not being able to consume a non-consumable, please open a new thread.
     
  18. Etsai

    Etsai

    Joined:
    Sep 12, 2014
    Posts:
    24
    I´ve been reading about Google´s voided purchases API, is used to have a real time refunded products info. But only in server side, it shouldn't be used directly in the app due to 500 queries per day limitation (and 30 queries during any 30-second period). Info here
     
  19. Friend123

    Friend123

    Joined:
    Sep 16, 2012
    Posts:
    19
    Same problem: refunded product (in Google Play) marked as "owned" ("SKU is owned..." when application start).
     
  20. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @Friend123 How about when you reinstall? Keep in mind, as in the real world, when you provide a refund for a product, the user still keeps the product. Otherwise, it's a return.
     
  21. Friend123

    Friend123

    Joined:
    Sep 16, 2012
    Posts:
    19
    In Google Play string of product (receipt i mean) marked as "Payment refunded." When I start the application, I check the purchased products, and for some reason this product is marked as “purchased”, although the buyer received the money for it - this is not logical. How can I check the status of receipt?
     
  22. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    When are you receiving the receipt with Payment refunded? How are you checking for purchased products?
     
  23. Friend123

    Friend123

    Joined:
    Sep 16, 2012
    Posts:
    19
    Via Android SDK Monitor tool i see logs when application loading. Among the strings, it shows what products are purchased ("SKU is owned..." log). Here are CS code, where i check owned products:

    Code (CSharp):
    1.  
    2. public bool IsPackBuyedInStore(string p_productID) {
    3.     bool s_result = false;
    4.  
    5.     if (IsInitialized()) {
    6.         Product s_product = m_StoreController.products.WithID(p_productID);
    7.         s_result = (s_product != null && !string.IsNullOrEmpty(s_product.receipt)) ? true : false;
    8.     }
    9.  
    10.     return s_result;
    11. }
    12.  
     
  24. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @Friend123 Please see my previous comments. Also, please try a reinstall, and see if an updated receipt is returned during the Restore process
     
    Last edited: Dec 28, 2018
  25. Friend123

    Friend123

    Joined:
    Sep 16, 2012
    Posts:
    19
    I reinstalled the application several times, but nothing has changed.
    I repeat once again - when IAP plugin loads, he writes me that the product is purchased (SKU is owned... in logs).
     
  26. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @Friend123 Please see previous posts for the state of the issue and potential workarounds.
     
  27. Ebonicus

    Ebonicus

    Joined:
    Oct 31, 2016
    Posts:
    158
    In the real world, you must return product for a full refund, not sure what you are referring to. You cannot buy a car, say you are unhappy and want a refund, and get a refund while keeping your car. Return of goods, and reversal of monies is implied with any cancellation FULL refund.

    Except in rare cases, like food.:)

    If 100 users purchase IAP to remove ads, then 100 request refunds, and the app remains unlocked, all 100 get the app for free, and the developer makes no money.

    This is asking for abuse.

    I believe is due to Google API no longer returns CANCELLED or REFUNDED. They did this to prevent abuse of consumable items that are purchased, used in app, then refunded. In doing doing so, they have created an opportunity for abuse for every single non-consummable IAP.

    Everyone with a non-consumable IAP on Google needs to email them to have them address this. A separate server side Voided Transaction API with limited calls is simply not acceptable. NO developers will make any money if this is abused, and that includes impacting Google revenue.

    So my question for Unity is:
    Does Unity IAP offer a better solution which supports refund cancellation to be notified to local app on receipt verification properly.

    For example, on a non-consumable "Unlock ads" IAP.When purchased, local app can detect:
    1. receipt of purchase and unlock ads.
    2. receipt showing purchase then refunded, and developer can display ads again.
    3. transaction history of buy/refund then they decide to buy again....app will unlock no-ad version, because latest transaction is a purchase, regardless of previous refunds.

    If you can do what Google cannot support, I will likely switch to Unity IAP.
     
    EduardRagimov and Svintaj like this.
  28. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @Ebonicus Fair enough. It is our understanding that it is Google policy to only provide a single refund. Regarding your comment "If you can do what Google cannot support, I will likely switch to Unity IAP", we do not handle any of the transactions, we are only a pass through for the Google API (and other stores). We don't implement additional API's. It is up to the respective stores how they handle the refund process. https://support.google.com/googleplay/answer/2479637
     
  29. sdalex

    sdalex

    Joined:
    Dec 17, 2014
    Posts:
    21
    I also thought having a problem with the refund since after the refund my test user was still accessing the IAP.
    But I didn't notice the "revoke" checkbox in the refund form. If you don't click this checkbox, the user will be refund and still own the purchased IAP.
     
  30. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @sdalex Keep in mind that even if you select this checkbox, the user will still have the purchased IAP in their game. It just won't show up during a Restore operation during reinstall. But depending on how you store your purchase information on the device, you won't know that you need to remove the product.
     
  31. Ebonicus

    Ebonicus

    Joined:
    Oct 31, 2016
    Posts:
    158
    Thanks I will try that and see if Google returns REFUNDED in the restore purchases process.
     
  32. BeoBeo1

    BeoBeo1

    Joined:
    Apr 19, 2013
    Posts:
    18
    refunded Non-consumable item still passed as ProcessPurcahse parameter, even if I reinstall the app.
    so I can't test purchase Non-consumable item anymore.
    how to solve it????
     
  33. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @GRE Did you check the receipt? At any rate, to test non-consumables, you either need multiple products or multiple test accounts to test repeated purchases.
     
  34. BeoBeo1

    BeoBeo1

    Joined:
    Apr 19, 2013
    Posts:
    18
    I'm testing to user refunding scenarios.
    And receipt, yes I checked it, it has the receipt.
    Can I find refunded information from receipt?
     
  35. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Not to my knowledge
     
  36. BeoBeo1

    BeoBeo1

    Joined:
    Apr 19, 2013
    Posts:
    18
    yes I checked the receipt, and it is same to "no refunded receipt"
    And this test is to refund scenarios of non-consumable item, u mean non-consumables item never cancel even if refund it?
     
  37. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    It's our understanding that the receipts for refunds (and the inability to repurchase) will eventually go away, but may take some time. It's up to the store.
     
  38. BeoBeo1

    BeoBeo1

    Joined:
    Apr 19, 2013
    Posts:
    18
    Yes, you are right.
    Refunded Non-Consumable Item is not passing by ProcessPurcahse after 10 hours
     
    Last edited: Feb 14, 2019
  39. sdalex

    sdalex

    Joined:
    Dec 17, 2014
    Posts:
    21
    @JeffDUnity3D Actually, I'm not storing it. So when not connected to the internet, hasReceipt() return null. I just check hasReceipt() is not null everytime the app is started!

    Doing a refund with "revoke" is not enough. I must remove my google account and re-add it after. And then, I can buy it again without reinstalling the app!
     
  40. sdalex

    sdalex

    Joined:
    Dec 17, 2014
    Posts:
    21
    Don't forget that the refund take 5 minutes to be processed!
    But actually, there is an error when I try to buy it again! It seems the only way is to have multiple test accounts.
     
  41. Olivier356

    Olivier356

    Joined:
    Sep 14, 2015
    Posts:
    12
    Is it also the case when your app is in beta stage or it must be in production ? I can't see anything about refunded product, neither in API nor in the product receipt.
     
  42. MikeGDev

    MikeGDev

    Joined:
    Dec 19, 2017
    Posts:
    53
    If the IAP gets refunded is there any way to refresh the receipt when the app is resumed? (without doing a complete restart)

    I noticed when testing with two accounts one which had bought the IAP and another one which had not that if I launched the game with the account that didn't buy the IAP it would not have a receipt. But if I switched to the account which had the IAP the receipt would be present. The issue came when switching back to the first account, as the receipt was still present. I tried to initialize the store on every resume to get the correct receipt for each account, but it seems it keeps accessing a local cache and never refreshes the products?

    On restarting the app I get the correct result, but I want to make sure the player doesn't refund the game and then keeps playing for free simply by avoiding a restart.
     
    Last edited: Sep 13, 2019
  43. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    You can attempt to re-initialize IAP at any time during game play. What correct result are you looking for, when you restart your app?
     
  44. MikeGDev

    MikeGDev

    Joined:
    Dec 19, 2017
    Posts:
    53
    When I restart the app if the current Google Play account has the IAP it has an receipt on initialize.
    If I start the app up with an account which doesn't have the IAP then the receipt is null as expected.

    However, if I switch accounts while the app is suspended and re initialize the store on resume, then no mather if the account has the IAP or not the receipt will always be present if it was loaded from a previous account.

    This was just a test to see if I could update the product receipt (in case of a refund, account switch etc.)

    Is both UnityPurchasing.Initialize and FetchAdditionalProducts expected to update the receipt as well?
     
  45. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    How do you switch accounts while the app is suspended? Please provide specific steps. For devices that allow you to switch users, it has a Users section under the Android Settings and opens a brand new device session when you switch. This is separate from Accounts under Settings which only allows for multiple email accounts.
     
  46. MikeGDev

    MikeGDev

    Joined:
    Dec 19, 2017
    Posts:
    53
    The way I did it was to go into Google Play and in the left top menu switch to the other Google account which was signed in. As it did give me a receipt when picking the account which I had bought the IAP with, it gave me the impression that Unity detected the current Google Play account.
     
  47. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    That is correct. You need to be signed in with the user that purchased the product.
     
  48. MikeGDev

    MikeGDev

    Joined:
    Dec 19, 2017
    Posts:
    53
    Ok so just to clarify, is the intention that the receipt gets refreshed when calling the function UnityPurchasing.Initialize again or FetchAdditionalProducts? Or is it handled differently under the hood?
     
    karthikveeramani likes this.
  49. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    You are correct, refreshed when calling Initialize. I haven't tested when calling FetchAdditionalProducts.
     
    MikeGDev likes this.
  50. wcoastsands

    wcoastsands

    Joined:
    Sep 30, 2011
    Posts:
    44
    Hey, Jeff. Have there been any new developments related to this?

    I've hit a wall, and could use some help. Problem is that when performing receipt validation, the purchase state is still returning "purchased" instead of "refunded" or "canceled". If I attempt to purchase the non-consumable again after having issued a refund, the purchase attempt results in an error saying that I already own the product.

    Google has requested that we support a reversion flow. Meaning basically that we purchase the non-consumable, refund the purchase, and the non-consumable is then no longer available.

    I appreciate any advice or suggestions you can offer.

    Thanks,

    Nikko
     
Thread Status:
Not open for further replies.