Search Unity

How to support PurchaseFailureReason.Unknown?

Discussion in 'Unity IAP' started by eppz, Mar 6, 2018.

  1. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    Hi,

    some of my users encountered PurchaseFailureReason.Unknown, and contacted me what is wrong. I'm clueless what should I say to them, as UNITY IAP DO NOT PROVIDE DETAILS on this error of any kind.

    ---

    I can't really say them what you have on documentation: "A catch-all for unrecognized purchase problems."
    I can picture something like: "Dear user, it could be anything, really. Have a good day." - just kidding.

    If a marker recognition is flickering, or some Ad fails to load, I can accept that easily. But when one of my users recognize value in my game and WANT TO PLACE AN ACTUAL PURCHASE, I think it should work. If it does not, at least we should know why.

    Please help, WHAT IS THE ERROR, how can the user resolve it.

    For inspiration, you people really should take a look at a typical NSError on iOS. It has: an error domain, a description, an array (!) of recovery options, a recovery suggestion, and a failure reason. All localized, full sentences. On every error. Errors happen, but information do help.

    @ap-unity @JeffDUnity3D
    (wow, seemingly you supported Remote Settings as well yesterday, thanks for that, but maybe you should expand the team, just a thought)
     
    Last edited: Mar 6, 2018
    CharBodman likes this.
  2. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    In UnityPurchasing.m, Unity IAP SWALLOW ALMOST EVERY ERROR INFORMATION from the NSError, keeping error codes only. Keeping 3 error codes only out of 9.

    Code (CSharp):
    1. - (NSString*)purchaseErrorCodeToReason:(NSInteger) errorCode {
    2.     switch (errorCode) {
    3.         case SKErrorPaymentCancelled:
    4.             return @"UserCancelled";
    5.         case SKErrorPaymentInvalid:
    6.             return @"PaymentDeclined";
    7.         case SKErrorPaymentNotAllowed:
    8.             return @"PurchasingUnavailable";
    9.     }
    10.  
    11.     return @"Unknown";
    12. }
    If you take a look on StoreKit documentation, you can see these:

    SKErrorUnknown
    Error code indicating that an unknown or unexpected error occurred.

    SKErrorClientInvalid
    Error code indicating that the client is not allowed to perform the attempted action.

    SKErrorPaymentCancelled
    Error code indicating that the user cancelled a payment request.

    SKErrorPaymentInvalid
    Error code indicating that one of the payment parameters was not recognized by the App Store.

    SKErrorPaymentNotAllowed
    Error code indicating that the user is not allowed to authorize payments.

    SKErrorStoreProductNotAvailable
    Error code indicating that the requested product is not available in the store.

    SKErrorCloudServicePermissionDenied
    Error code indicating that the user has not allowed access to Cloud service information.

    SKErrorCloudServiceNetworkConnectionFailed
    Error code indicating that the device could not connect to the network.

    SKErrorCloudServiceRevoked
    Error code indicating that the user has revoked permission to use this cloud service.

    I am UNABLE TO DIFFERENTIATE between these error, and the only reason is because I'm using Unity IAP. I'm clueless, my customer is clueless. Unity IAP is a stream of frustration, to be honest.
     
    CharBodman likes this.
  3. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    Are you serious?
    I took a deeper look, and it seems most of these failure reasons in your documentation simply are NOT HOOKED UP:

    PurchasingUnavailable The system purchasing feature is unavailable.
    ExistingPurchasePending A purchase was already in progress when a new purchase was requested.
    ProductUnavailable The product is not available to purchase on the store.
    SignatureInvalid Signature validation of the purchase's receipt failed.
    UserCancelled The user opted to cancel rather than proceed with the purchase.
    PaymentDeclined There was a problem with the payment.
    DuplicateTransaction A duplicate transaction error when the transaction has already been completed successfully.
    Unknown A catch-all for unrecognized purchase problems.

    You have to stop what you are doing. I'll contact Unity directly.
     
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @eppz Thank you for the feedback, I will bring this up with the IAP team today, and will update this thread.
     
    CharBodman and eppz like this.
  5. ap-unity

    ap-unity

    Unity Technologies

    Joined:
    Aug 3, 2016
    Posts:
    1,519
    @eppz,
    I completely agree that we should provide as much information as possible. I will pass this feedback along to the team.

    I was able to find all of these error codes used in the UnityPurchasing.m file, with the exception of SignatureInvalid and ExistingPurchasePending, which is expected. (As you know, Unity IAP is cross-platform, so not all of the errors listed on the PurchaseFailureReason will be relevant for iOS.)

    Taking a look at the SKError list, three of them are concerning Cloud Services which our IAP plugin does not use. Of the remaining six, we are only catching four; SKErrorStoreProductNotAvailable and SKErrorClientInvalid are not caught and would be marked as Unknown. However, before we initiate the purchase on the StoreKit side, we are checking if the product is available and if purchasing is allowed. If not, the relevant error will be thrown. So we are not catching those SKError specifically, but we should be handling those situations.

    The vast majority of the time, if Unity IAP shows an Unknown error, it's because StoreKit returned an Unknown error. The response we get from StoreKit is always available in the device log. I understand that if this happens on a customer's device, then it makes it even more difficult to track down the exact cause.

    We have brought your concerns to the IAP team and they will reevaluate how they are handling iOS errors and whether we can provide more information to developers.
     
    eppz likes this.
  6. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    Thanks for getting back!

    I looked into my analytics: ~20% of my purchase attempt events end up on this "Unknown" error. Which is a huge number. And only 1% of them attempted to retry and manage to place the purchase. I'm actually losing revenue, and have not idea why.

    It affects 0,3% of all users, but 7% of users with purchasing events (every iOS from 10.3.2+, ). Lost revenue, without any explanation.

    I would like to fix it actually instead of support it, but I have no starting point at all.

    You should make analytics campaign to log these type of errors. Given that Unity has an enormous user base, tracking it down / correlate with factors would be easier for you. I could not move the needle even if I try to patch Unity IAP.
     
    Last edited: Mar 16, 2018
  7. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @eppz The Unknown error is returned to us by Apple in most cases, and we have no control over this.
     
  8. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    Well, today I have another customer message, saying: "I like the game, but I can't buy <SOME_IAP>, please help".

    I told her that I'll look into analytics, but I'm pretty sure it will be unknown error. She has her payment details right, also she can purchase other stuff in other games. This is eternally frustrating.

    Am I the only person experiencing this issue?
    Why you people just pretending that this is all normal?
     
  9. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    She could not purchase a particular product (A).
    She could successfully purchase other products in the game.
    Others can purchase the particular product (A) just fine.

    I'll patch Unity IAP, and make analytics every error message.
    Is there any additional factor I should make analytics of?
     
  10. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    The error message they are receiving would be helpful, if it is possible to obtain. Is this the only user not able to buy product (A)?
     
  11. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    It seems not product dependent, as I can see every product purchased in my analytics.

    I can get the error message by
    -Patch Unity IAP to pass on every NSError property,
    -Dispatch the values to Analytics,
    -Release an Update to the App Store.

    So it will take time. :(
    And further lost profits.

    Since then, she added: "...it is quite frustrating when you getting the hang of the game, then you have to accept that you can't buy more levels...". This is a nightmare. Reading emails like is devastating.
     
  12. tim-unity

    tim-unity

    Joined:
    Feb 22, 2013
    Posts:
    15
    Just to add : we are seeing the same issues as described here in our live builds also (Unity 2018.1.0b11 + Unity IAP 1.17.0). I am able to repeat this 100% of the time with my personal Apple ID in our app. The issue does not occur for other users here using the same live build - it seems somewhat account specific. Purchasing from any other apps using my personal Apple ID works fine.
     
    eppz likes this.
  13. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    We are continuing to look into this. I am investigating a possible scenario where the user is logged into the iTunes store vs not logged in, prior to an in-app purchase.
     
  14. tim-unity

    tim-unity

    Joined:
    Feb 22, 2013
    Posts:
    15
    Update: my account is now able to purchase without problem and the issue appears to have resolved - something must have changed externally as we have made no changes on our side.
     
  15. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  16. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    So I should advise the users to simply log out, log in, then retry?
     
  17. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @eppz That is a possible approach, but is not guaranteed to help if it is an ongoing issue with Apple. One article mentions the need to confirm iTunes Terms and Conditions if a recent update was performed. We are continuing to discuss here also. It is difficult to diagnose without a consistent repro scenario that we can test with here.
     
    eppz likes this.
  18. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    @JeffDUnity3D Wow, Terms and Conditions update seems kind of fit the symptoms. Not everyone experiences, not every time, no product or account dependency.

    Terms and Conditions update seems a good fit, but for testing, it would be great to know when the next update will be performed. The corresponding tests could be carried out then.
     
  19. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Agreed, you would want to ask Apple about their schedule with regard to iTunes updates. But keep in mind this is only a theory, and an iTunes update can happen for any user at any time if they haven't used their phone for awhile, for example. If you have a user that can confirm T&C behavior, it would be helpful to know.
     
  20. tperry523

    tperry523

    Joined:
    Jan 17, 2016
    Posts:
    6
    I am also seeing this issue. I have a device that repros this 100% of the time, but only a small section of my users are seeing the issue.
     
  21. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @tperry523 Can you try logging out and back in with your AppleID on this device and see if it makes a difference?
     
  22. tperry523

    tperry523

    Joined:
    Jan 17, 2016
    Posts:
    6
    That did not work, but logging in with a sandbox account did work did allow purchases. It seems like it's tied to the account.
     
  23. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  24. tperry523

    tperry523

    Joined:
    Jan 17, 2016
    Posts:
    6
    I have two accounts. One is a wild production account that I borrowed from a local friend. The other is a sandbox account.

    The build is loaded from XCode.

    The wild account gives PurchaseFailureReason.Unknown, but the sandbox account looks like it did everything perfectly.
     
  25. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  26. tperry523

    tperry523

    Joined:
    Jan 17, 2016
    Posts:
    6
    What part of that is expected?
     
  27. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Two reasons. First, if you're testing on TestFlight and subsequently side loading from XCode (you haven't specified), you'll need to use registered test users as previously mentioned. It's not clear if your Sandbox user is registered as a test user. Second and more importantly, we are just a pass through service for the respective stores. We do not do any account level checking. We are simply passing the error that Apple gives to us. Apple does all the user-level authentication and handles the transaction. So if Apple is not allowing the user to purchase, you would want to contact Apple regarding the behavior. If you could provide the logs for both cases during a debug session from XCode, it would be helpful.
     
  28. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    I should add, we are continuing to investigate, specifically looking at our handling of iOS error codes. We want this fixed as much as you do! It is not in the best interest of Unity nor our developers to point fingers at Apple without due diligence. There are a few layers of the Apple purchase API, and if a user has a declined purchase because of a bad credit card or similar, it appears that Apple ultimately returns the Unknown error to us. This is the area we are still investigating.
     
    Last edited: Mar 30, 2018
    eppz likes this.
  29. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    @JeffDUnity3D Good to know, however, I had a USER MAIL AGAIN today, saying that he can't purchase. Still, 16% (!!!) of my Purchase button presses ends up on this. Which is an updated figure for the last month.

    This is devastating. I advised him to log in / out, saying that perhaps iTunes updated their policy, but I felt like an idiot, as currently, I create an will to purchase in my users, then I don't let them purchase.

    I work for companies using Unity, and personally, I advise them not to use Unity IAP.

    You say it is Apple, but every user mail I received so far said that they can purchase just fine in other games.
     
  30. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    We are hoping to add improved handling for store-specific errors in the next IAP release (possibly the release after), with the plan to include additional information with regard to the Unknown error.
     
    eppz likes this.
  31. eppz

    eppz

    Joined:
    Aug 2, 2014
    Posts:
    172
    This can be implementation issue as well, with concurrent transactions in transaction queue, or duplicate / stuck transactions canceled transactions, etc.

    I did not inspect the actual Unity IAP source, but it could be at least reviewed, and make it sure that it is all implemented according to Official Apple Documentation and Waiting for the App Store to Process Transactions in particular.
     
  32. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @eppz Yes the code will be reviewed during the investigation. In addition to the Unknown error, we have a separate task to investigate the stuck transaction behavior.
     
    eppz likes this.
  33. jreed-curious

    jreed-curious

    Joined:
    Jul 24, 2017
    Posts:
    10
    @eppz Looks like the latest version of Unity IAP (1.19.0) is out and has support for additional store specific error information (notes here). Thanks for leading the charge on this issue

    Thank you @JeffDUnity3D for getting this new feature out. Hopefully it will help shed some light on whats causing some of our purchase failures.

    There doesn't appear to be any official documentation on how to use it yet. From my own testing it can be used in your
    IStoreListener.OnPurchaseFailed
    implementation:
    Code (CSharp):
    1. public class IAPManager : IStoreListener {
    2.     IExtensionProvider Extensions { get; set; }
    3.  
    4.     public IAPManager() {
    5.         ConfigurationBuilder builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
    6.         builder.AddProduct("PROD1", ProductType.NonConsumable);
    7.         UnityPurchasing.Initialize(this, builder);
    8.     }
    9.  
    10.     public void OnInitialized(IStoreController controller, IExtensionProvider extensions) {
    11.         Extensions = extensions;
    12.     }
    13.  
    14.  
    15.     public void OnInitializeFailed(InitializationFailureReason error) {
    16.         ...
    17.     }
    18.  
    19.     public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args) {
    20.         ...
    21.     }
    22.  
    23.     public void OnPurchaseFailed(Product product, PurchaseFailureReason reason) {
    24.         var transactionHistory = Extensions.GetExtension<ITransactionHistoryExtensions>();
    25.         Debug.LogWarning(string.Format(
    26.             "Purchase of '{0}' failed (Reason-{1}; StoreError-{2}): '{3}'",
    27.             product.definition.id,
    28.             reason,
    29.             transactionHistory.GetLastStoreSpecificPurchaseErrorCode(),
    30.             transactionHistory.GetLastPurchaseFailureDescription().message
    31.         ));
    32.     }
    33. }
    That code produces the following log message when testing on an Android device by cancelling the purchase from the Google Play dialog:
    Purchase of 'PROD1' failed (Reason-UserCancelled; StoreError-IABHELPER_USER_CANCELLED): 'GOOGLEPLAY_User canceled. (response: -1005:User cancelled)'
     
    Last edited: May 25, 2018
    _Adriaan and eppz like this.
  34. d_sharov

    d_sharov

    Joined:
    Dec 24, 2021
    Posts:
    23
    @JeffDUnity3D
    Hello.
    Is it possible to test purchases of inaps of a subscription through a testflight?
    When buying a tester, we get an error
    APPLE_An unknown error occurred storeSpecificErrorCode: SKErrorUnknown)

    At the same time, all other expendable inaps work correctly, they are bought through a testflight
     
  35. d_sharov

    d_sharov

    Joined:
    Dec 24, 2021
    Posts:
    23
    The problem turned out to be that the subscription store did not have a duration selected.
    Unfortunately, the error from the logs does not guess about this.