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

Question Detect Refund via local receipt validation Unity IAP IOS

Discussion in 'Unity IAP' started by keshav_4146, Mar 16, 2023.

  1. keshav_4146

    keshav_4146

    Joined:
    Aug 10, 2016
    Posts:
    3
    Hello all,

    I've been looking at various other threads trying to decipher this, but there don't seem to be clear answers.

    My question is the following: if I want to develop an app with In-App Purchases, but I want to know when those IAPs were refunded, how can I do that? My plan was to validate the receipt locally and to keep checking with Apple's servers if a refund is initiated

    However, it's not clear from the documentation how I can tell by a receipt, that an IAP was refunded. I read here about the cancellation_time field:

    https://developer.apple.com/library.../apple_ref/doc/uid/DTS40016228-CH1-RECEIPTURL


    however, I have a few questions.


    1. The link mentions that "This field is set when a customer contacts Apple customer support for a refund and the transaction is canceled." Does this happen if a user in the EU cancels an IAP with no questions asked, within the first 14-day window after purchase?
    2. According to the link, cancellation_date might appear in various places, I tried checking that but since the receipt itself is old the date is also not updated.
    3. * I am using a combination of codeless IAP of unity. the purchase and restoration works as expected.
    4. the app is not live in ios, so I am using the sandbox version. I am clearing the transactions from the users and testers tab.
    5. Can anyone guide me on what am i missing?
     
  2. Baroni

    Baroni

    Joined:
    Aug 20, 2010
    Posts:
    3,256
    Hi!

    If you are serious about handling refunds, you would not let the client app determine whether a purchase has been refunded or not by doing a local validation. In fact, local validation is pretty much useless for any more advanced requirements such as handling refunds.

    You have two options to handle refunds:
    1. A refunded transaction should not be returned to Unity IAP anymore after a minor delay. You can easily check this using a call to controller.products.WithID("yourProductID").hasReceipt in Unity IAP's OnInitialized method. When allowing access to your paid content, always check hasReceipt before doing so. There is no need to duplicate that functionality by setting a "product PlayerPref" locally or anything like that. This means if the purchase is refunded, hasReceipt returns false, and your user cannot access your paid content anymore. For Google Play this approach works, for Apple it might work when Unity implements StoreKit 2 support.
    2. Using professional server side notifications from the Apple App Store. Apple will then inform your server about any refunds, via a notification with the notificationType REFUND. The notification contains the originalTransactionID, which allows removing the transaction from your user's inventory on your server - yes, you have to maintain user inventory on your own server for this too.

    Note that for option 2, your app has to reach a very big audience to be worth the effort. Since Apple usually only allows one refund per app and sometimes also looks into the user's history of refunds to deny mass refunding, this should not be your number 1 concern. If you would like to go the way of server side receipt validation but do not want to reinvent the wheel or set up your own servers, I am offering a service for this on my website.

    Not necessarily. As mentioned above, Apple checks the user's refund history and might even deny a refund. In most cases, users are only allowed to refund one transaction per app at maximum.

    Yes, that is one part where local validation fails. The receipt does not refresh itself or gets downloaded automatically to the device when it changes on the server. There are server side notifications used for this instead.

    As written on the Apple Developer dashboard, when clearing a tester's purchase history in the popup it says that it could take up to 24 hours before the test user's transactions are deleted.
     
  3. keshav_4146

    keshav_4146

    Joined:
    Aug 10, 2016
    Posts:
    3
    Hello

    Thanks for the feedback,

    I tried the "has_receipt" approach and waited for 24 hours after clearing the transaction history from apple connect. The receipt is still passing and is valid.

    Here is the piece of code Is there anything else that i need to take care?

    Code (CSharp):
    1. #if UNITY_IOS
    2.                 if (!item.hasReceipt)
    3.                 {
    4.                     UI_Manager.ui.SetPurchase(false);
    5.                  }
    6. #endif
    Here the item is object, which gets value from looping controller.products.all
     
    DankalApps likes this.