Search Unity

Unity IAP is not calling IStoreListener.ProcessPurchase if item was already bought on iOS

Discussion in 'Unity IAP' started by AlexeyM-, Apr 22, 2020.

Thread Status:
Not open for further replies.
  1. AlexeyM-

    AlexeyM-

    Joined:
    Sep 17, 2019
    Posts:
    3
    Hello,
    Unity Purchasing is not calling IStoreListener.ProcessPurchase(PurchaseEventArgs e) if an consumable item was already bought but not consumed due to a backend validation during the same session.

    Platform: iOS 12.0.1
    Unity: 2018.4.20f
    Unity Purchasing: 1.23.1

    Steps to reproduce:
    1. Make a normal purchase of a consumable item, when Unity Purchasing calls IStoreListener.ProcessPurchase(PurchaseEventArgs e) return PurchaseProcessingResult.Pending to validate the purchase on your back end.
    2. Mock your server response with validation answer that doesn’t result in purchase being consumed (e.g. something like “validation_in_process”, so that purchase is not consumed and will be recovered on the next Unity Purchasing initialization or user can click again on the same product in the store).
    3. Try to purchase the same product again.
    4. In the native popup iOS notifies you that “This In-App purchase has already been bought. It will be restored for free”. Press OK.
    5. Native popup closes and you return to your app.
    6. Observe that IStoreListener.ProcessPurchase(PurchaseEventArgs e) is not called so you cannot proceed with the purchase.

    The main problem for us is that we show loading overlay so a user cannot interact with the app while transaction is created and purchase being validated on our side. Since there is no call of ProcessPurchase from Purchasing basically we stuck since there is no indication to start validation or just interrupt the purchase due to some error. Of course there can be a lot of different workarounds to handle this, but all of them are ugly and it would be a lot cleaner to follow an expected flow with Purchasing being able to provide UnityEngine.Purchasing.PurchaseEventArgs via ProcessPurchase or OnPurchaseFailed.

    On Android it works as expected, if user clicks the same product again in the same case Unity Purchasing calls IStoreListener.OnPurchaseFailed(Product i, PurchaseFailureReason p) with the same product and reason “DuplicateTransaction“. After that we can simply handle this since the product has a valid receipt, and we try to validate the purchase again and give the user resources.

    I can share the log privately via issue tracker or direct messages, but there are no suspicious entries, it just ends at the point before calling IStoreController.InitiatePurchase(productId, payload) and never triggers log in OnPurchaseFailed methods.
     
  2. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    626
    If a product is not consumed, then ProcessPurchase will be called after the next IAP initialization, and you should use IStoreController.ConfirmPendingPurchase to consume the product at this time.
     
  3. AlexeyM-

    AlexeyM-

    Joined:
    Sep 17, 2019
    Posts:
    3
    Thanks for the answer.
    But the problem is not in the consuming of a product, but in the different behaviour for android and iOS. And not just different, but seems faulty on iOS, since IAP is not calling a method it is supposed to call.
     
  4. SamOYUnity3D

    SamOYUnity3D

    Unity Technologies

    Joined:
    May 12, 2019
    Posts:
    626
    So the problem is that OnPurchaseFailed will not be called on the IOS platform after purchasing a duplicate product. I'll confirm with the team whether this is expected behavior. The current workaround is ConfirmPendingPurchase after the next IAP initialization.
     
  5. AlexeyM-

    AlexeyM-

    Joined:
    Sep 17, 2019
    Posts:
    3
    @SamOYUnity3D Thanks. Will be waiting for your response.
    Yes, we are using this workaround, but we also try to avoid as much as possible blocking UI or restarting the game (so IAP is initialized again) for some of our unsuccessful validation statuses. Also having platform independent code for this case would be great.
     
  6. pwemartinez

    pwemartinez

    Joined:
    Feb 2, 2017
    Posts:
    2
    I have also encountered this problem. OnPurchaseFailed is not called when the purchase fails after "This In-App purchase has already been bought. It will be restored for free." This means that the app receives no indication any error occurred, making handling this case difficult.

    iOS 13.1.2
    Unity 2018.4.22f1
    Un App Purchasing 2.0.6

    Any updates on the status of this @SamOYUnity3D ?
     
    alex_roboto likes this.
  7. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Can you confirm if the previous purchase was left in Pending state? ProcessPurchase can return either Complete or Pending. Granted, OnPurchaseFailed should be called upon the second failed purchase. If a product is left in Pending, the expectation is that ProcessPurchase would be trigger upon next IAP initialization for this first purchase. Regarding same behavior across platforms, that is the goal. However we are just a pass-through service for the respective store APIs, and we may not have control over the transaction behavior.
     
  8. pwemartinez

    pwemartinez

    Joined:
    Feb 2, 2017
    Posts:
    2
    Yes, this happens when a purchase is left in a Pending state.

    This is a real edge case we have trouble contacting our servers. If that happens we will leave the purchase in Pending until we have confirmation our servers have verified the transaction. This could lead someone to try to buy the item again, get this popup, and the app have no way to know the result of the second purchase attempt. The work around I am considering is to record all the pending purchases and never ever call InitiatePurchase on a product that is Pending, preventing the user from ever seeing this message and therefore preventing the app from making a call to InitiatePurchase that will neither fail or succeed.

    Hopefully there is a way in the underlying store that will allow unity to catch this situation. IMO InitiatePurchase should always either result in a call to ProcessPurchase or OnPurchaseFailed.

    Thanks for the reply! If there ends up being a bug/ issue created for this please link it! Or if I can help by filing anything let me know.
     
  9. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Will do! Yes, your work around should work, ideally disable the button so the user can't initiate a purchase.
     
  10. SteveKouts

    SteveKouts

    Joined:
    Aug 23, 2012
    Posts:
    79
    I'm having this issue, but I only just had it recently after creating a new test account because I forgot my old password for the old one. Not sure what happened but now the game crashes after trying to give the coins after purchase saying its already been bought even though its a consumable!
    I read in other older posts there is a way to clear the Appstore cache on mobile, but Ive tried that it doesn't work anymore and I cant find any other way to do it.
     
  11. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Please don't mulitipost, already answered
     
    SteveKouts likes this.
Thread Status:
Not open for further replies.