Search Unity

[Closed] Properly Handling a Refunded/Cancelled Non-Consumable Item on Android(Google Play)

Discussion in 'Unity IAP' started by gauravku, Feb 4, 2018.

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

    gauravku

    Joined:
    Dec 16, 2017
    Posts:
    1
    Hi,
    So I checked the forums about how to go about updating the Local Data status of a Refunded/Cancelled Non-Consumable Item on Android(Google Play). Looks like the only way do this is using the Product.hasReceipt

    Here's the code how i update my local data for a refunded product
    Code (CSharp):
    1. public void OnInitialized (IStoreController controller, IExtensionProvider extensions){
    2.         this.controller = controller;
    3.         this.extensions = extensions;
    4.         updateIAPStatus ();
    5. }
    6.  
    7.     //TODO: In IOS parse reciept, hasReciept is transient in ios so cant be used
    8.     void updateIAPStatus(){
    9.         Product product = controller.products.WithID(kProductNameGooglePlaySubscription);
    10.         if (product != null && product.hasReceipt) {
    11.             //product purchase is valid
    12.                 setItemStatus(PURCHASED);
    13.             Debug.Log ("Has Reciept");
    14.         } else {
    15.             // product purchase in invalid, reasons include not purchased, refunded, cancelled
    16.             setItemStatus(NOT_PURCHASED);
    17.             Debug.Log ("No Reciept");
    18.         }
    19.     }
    20.  
    But the issue is that once the item is purchased, hasReceipt returns true always....So, is this correct way to go about it or am i missing something?

    Weird thing is that even after uninstall and re-install the result is the same. Due to this i am unable to reset the items for which Refunds/Cancellation was made!

    Or is it because of some sort of delay from the Google Play Server or Unity IAP Server and this condition is temporary?!

    Using Unity 2017.3.0p3

    Any help will be greatly appreciated! Thanks in Advance!
     
    Last edited: Feb 4, 2018
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    If the Google Play product is no longer active (cancelled, subscription expired, etc), it won't be returned in the list of products during initialization, and there is no need to check the receipt.
     
  3. plindberg

    plindberg

    Joined:
    Nov 25, 2016
    Posts:
    18
    I'm also having the same issue as OP, and I'm not quite sure what you mean. What list of products are you referring to? IStoreController.Products contains all products, not just those you own, and the only other list of products I can see is the previous purchases that you receive upon initialising purchasing after a reinstall, which does not help if you're looking to find refunded non-consumables at runtime.
     
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Yes, the list of products at initialization is what you are looking for. If the product has been refunded and no longer available, it won't appear in the list even if purchased previously. If you are seeing different behavior, it would probably best to open a support ticket at https://analytics.cloud.unity3d.com/support
     
  5. plindberg

    plindberg

    Joined:
    Nov 25, 2016
    Posts:
    18
    Please be more specific about which list you're referring to.
     
  6. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @plindberg So you are seeing invalid (refunded) subscriptions show in the list of previous purchases that you receive upon initializing purchasing?
     
  7. plindberg

    plindberg

    Joined:
    Nov 25, 2016
    Posts:
    18
    No, but you don't get a list of previous purchases when initializing unless it's the first time after a reinstall, so it's not helpful.
     
  8. plindberg

    plindberg

    Joined:
    Nov 25, 2016
    Posts:
    18
    For OP and anyone else who has the same question:

    Product.hasReceipt should reflect the ownership status of a non-consumable product on Android. It will be true if the customer has bought the item, false if they have not, and also false if they have received a refund. (source: https://forum.unity.com/threads/solved-query-owned-products.429603/)

    Google Play caches the customer's receipts on the device, so changes will not take effect immediately. If you want to test, you can clear the google play cache by using the android debug bridge with the following command:

    adb shell pm clear com.android.vending.

    BEWARE though: if the user has multiple Google Play accounts on their device, Product.hasReceipt will reflect the status of the account that is currently active in the Google Play app, which means it's not possible to distinguish between an account change and a refund. If you use the value of Product.hasReceipt to disable refunded items, you must also be ready to activate them if hasReceipt returns true again.

    ALSO beware that Product.hasReceipt does not work the same on iOS. There, it will only return true during the session which a product was bought (unless this has been changed recently), so you must parse the receipt instead. That's covered in the IAP manual.
     
    andymads likes this.
  9. andymads

    andymads

    Joined:
    Jun 16, 2011
    Posts:
    1,614
    Is this true for Android in general or just Google Play?
     
  10. Muzlu

    Muzlu

    Joined:
    Feb 4, 2015
    Posts:
    12
    My unity IAP is still restoring refunded item.
    I refunded item on google play dashboard, however product still got recipe and IAP restoring it.
    Currently i am using:
    Code (CSharp):
    1. public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    2.         {
    3.             m_StoreController = controller;
    4.             m_StoreExtensionProvider = extensions;
    5.         if (m_StoreController.products.WithID(NO_ADS).hasReceipt)
    6.         {
    7. //purchased
    8. }else{
    9. //noAds not purchased handle
    10. }
    NO_ADS is my item id in google store. (it is non-consumable item)
    Am i doing something wrong? this always return true.

    EDIT:
    i just checked on my other device (same google account) -> all works as it should there.
    How long takes for google/android system to update device? Or should i download new metadata for all products before checking.... or something?

    EDIT2:
    controller.products.WithID(NO_ADS).availableToPurchase
    returns true....

    EDIT3:
    tooks 48h - first device is showing no recipe correctly now..... is there a way to update this quicker?
     
    Last edited: Feb 13, 2018
  11. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    This is behavior on the Google side, we are a pass through service. Is this in Alpha/Beta, or in release?
     
  12. Muzlu

    Muzlu

    Joined:
    Feb 4, 2015
    Posts:
    12
    It is in Alpha,

    One more thing i found is:
    When my first device is "locked" with refund (refunded but hasRecipe=true), i cant save game data from my other device where hasRecipe =false.... It is saving with success but when i load it -> it is always last save i made on "locked" device...
    However i can save on first device...
    It is making me nuts... is there any workaround for that?

    If it is google -> why device i made purchase is blocked, and other one (same google play account email) it is not?
    is there way to force recipes update on device?
     
    Last edited: Feb 13, 2018
  13. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    This may be behavior in the Alpha/Beta environment only, and should be tested in a Released version of the app.
     
  14. Muzlu

    Muzlu

    Joined:
    Feb 4, 2015
    Posts:
    12
    I can't release with bug like that :D
    I will try to test on other devices to.
     
  15. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Understood, I suspect the update time is faster in their Release environment, so I wouldn't call it a bug yet.
     
  16. plindberg

    plindberg

    Joined:
    Nov 25, 2016
    Posts:
    18
    Did you try clearing the google play cache after refunding the purchase?

    Open a terminal window in android SDK platform-tools folder and type:

    adb shell pm clear com.android.vending
     
  17. Muzlu

    Muzlu

    Joined:
    Feb 4, 2015
    Posts:
    12
    thing is -> people who downloaded my app will probably not make that...
    So far i noticed it is resetting all back after 24h +, maybe, as Jeff said it is alpha/beta behavior.
     
  18. darkmoose1

    darkmoose1

    Joined:
    Mar 7, 2018
    Posts:
    1
    I am having similar problems. I want to test the purchases on BETA but I cannot because even though google refunded those transactions (beta purchases) unity Istorecontroller or whatever still thinks they have receipts. This has been going on for months.
     
  19. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @darkmoose1 Can you elaborate how this is impacting your testing? We don't track refunds, since they are done outside the Unity application.
     
Thread Status:
Not open for further replies.