Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

(iOS) OnPurchaseFailed followed by ProcessPurchase

Discussion in 'Unity IAP' started by JKimJC, Feb 7, 2020.

  1. JKimJC

    JKimJC

    Joined:
    Oct 14, 2019
    Posts:
    3
    1. Single InitiatePurchase is triggered.
    2. OnPurchaseFailed is called with PurchaseFailureReason.Unknown.
      ITransactionHistoryExtensions tells me the following message: "APPLE_Cannot connect to iTunes Store"
    3. After some time (up to 2~3 minutes) ProcessPurchase is called.
    We could not reproduce this behavior in-house, but this is what I am seeing from our custom logs.
    While this only happens for a very small fraction of our total purchases, they still make up most of our purchase issues.

    My question is:
    1. Is it wrong to assume that 1 InitiatePurchase means 1 OnPurchaseFailed or 1 ProcessPurchase?
    2. Is there an internal logic inside Unity IAP that retries failed purchase attempts?
    3. What is the recommended way to handle such cases?
     
  2. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    Very interesting. We have heard reports of this behavior but have not been able to reproduce. Yes, typically a single purchase either results in only Success or Failure, but not both. This would be an issue the the store API most likely, and would probably also happen if you coded IAP natively. If you can reproduce, we would be most interested. What custom logs are you referring to? Are these logs from internal testing?
     
  3. JKimJC

    JKimJC

    Joined:
    Oct 14, 2019
    Posts:
    3
    Edit: sorry I misread your comment about the store API

    We have our own custom analytics stack. We are seeing this problem on production builds, with real customers.
    Currently, log events are triggered when the purchase is attempted (InitiatePurchase), when the purchase succeeds (ProcessPurchase), and when the purchase fails (OnPurchaseFailed).
     
  4. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    Yes, I was referring to the Apple Storekit API https://developer.apple.com/in-app-purchase/ What version of IAP and Unity are you using? The latest IAP is 1.23.1. Is the issue specific to any iOS device model?
     
  5. JKimJC

    JKimJC

    Joined:
    Oct 14, 2019
    Posts:
    3
    We are using 1.23.0. I read the changelog for 1.23.1 and I don't think there were any specific fixes for iOS yet. If you think upgrading may fix the problem we will definitely try that as well.
    I need to double check our analytics, but it happens across various OS versions (12 and 13) and multiple device types.
     
  6. JeffDUnity3D

    JeffDUnity3D

    Unity Technologies

    Joined:
    May 2, 2017
    Posts:
    14,446
    Yes please try with 1.23.1, 1.23.0 was less stable. But correct, we did not specifically address this issue, we would need to reproduce first.
     
  7. chrismarch

    chrismarch

    Joined:
    Jul 24, 2013
    Posts:
    468
    We seem to have a very similar repro, so far once in production, but with Google Play Store, Unity IAP 4.7
    Has this issue been addressed in Unity IAP 4.8? I don't see a mention of it in the changelog.

    In our case, the call to ProcessPurchase was less than a tenth of a second after the call to OnPurchaseFailed
    Google reported that the user was charged for this consumable in this case.
    The transactionID was null in the call to ProcessPurchase.
    I don't believe we have access to the Unity IAP logs, which were on the client, and in version 4.7, the
    PurchaseFailureDescription was not exposed, and our usage of
    ITransactionHistoryExtensions to extract it was futile due to the apparent usage of
    FakeTransactionHistoryExtensions in the Google Play store implementation.
     
  8. Yannick_D

    Yannick_D

    Unity Technologies

    Joined:
    Feb 21, 2022
    Posts:
    218
    Hello chrismarch,

    I don't think this is the same issue, since these 2 stores have different behaviours.
    Also, other than the PurchaseFailureDescription, there's nothing new that should affect this.

    A few questions regarding your specific case:
    -Was the application backgrounded and foregrounded while the initial purchase attempt was ongoing?
    -Was there a successful call to ProcessPurchase before the one with the transactionID null?
    -Is there a possibility that your code called ConfirmPendingPurchase?
    -Do you have more details on the call to OnPurchaseFailed (the PurchaseFailureReason)?

    I've taken a look at the code and the transactionId is provided directly by Google in every case.
    The 2 cases that might be responsible for this are the product retrieval (when foregrounding the application) or the ConfirmPendingPurchase since they can remove the transactionID, but these would have to happen with a very precise timing while a product is being purchased, but before it goes through the ProcessPurchase.

    To better understand the impact of this, was the user granted the purchased consumable? When fetching purchases again (reboot or foregrounding the app), was it granted properly?