Search Unity

Google Play receipt validation issue

Discussion in 'Unity IAP' started by Arvtesh, Dec 22, 2020.

  1. Arvtesh

    Arvtesh

    Joined:
    Aug 16, 2014
    Posts:
    94
    Hello, we use UnityPurchasing v2.2.5 and get a lot of receipt validation failures (for valid purchases). With v2.2.4 we had OnPurchaseFailed called right after ProcessPurchase as well.

    The code we use for purchase validation is:
    Code (CSharp):
    1. try
    2. {
    3.     localValidationResult = false;
    4.  
    5.     var validator = new CrossPlatformValidator(GooglePlayTangle.Data(), AppleTangle.Data(), Application.identifier);
    6.     var result = validator.Validate(args.purchasedProduct.receipt);
    7.  
    8.     if (result != null)
    9.     {
    10.         foreach (var productReceipt in result)
    11.         {
    12.             if (productReceipt != null)
    13.             {
    14.                 if (productReceipt.productID == product.definition.id && productReceipt.transactionID == product.transactionID)
    15.                 {
    16.                     localValidationResult = true;
    17.                     break;
    18.                 }
    19.             }
    20.             else
    21.             {
    22.                 Debug.LogWarning("Purchase receipt is NULL.");
    23.             }
    24.         }
    25.     }
    26.     else
    27.     {
    28.         Debug.LogWarning("Purchase validation result is NULL.");
    29.     }
    30. }
    31. catch (IAPSecurityException e)
    32. {
    33.     Debug.LogWarning(e);
    34. }
    35.  
    36. if (localValidationResult == false)
    37. {
    38.     Debug.LogWarning($"Purchase validation failed for product {product.definition.id}.");
    39. }
    What seems to happen is Validate() call not throwing, but its result is an empty array. The same code worked normally before upgrading UnityPurchasing to v2.2.x.

    Another weird thing is we get this message after a purchase:
    Code (CSharp):
    1. Already recorded transaction jmlbigaaicjhcgdabopnabej.AO-J1Ozaarr6F2vJP1MA0c9xCKJAbW2fheL40tFKdmtXTwmWFbGvjCHRJuUZ5eEDpA3QOWkOgjjdhU2cnlIPbbUc55_AyMLn2Q
    2.     UnityEngine.Purchasing.Extension.UnityUtil:Update()
    Any suggestions?
     
  2. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    We've changed the transactionID so they might not match previous purchases. Please review the recent release notes for 2.2.* You'll want to check for a non-null receipt before using the Validator.
     
  3. Arvtesh

    Arvtesh

    Joined:
    Aug 16, 2014
    Posts:
    94
    Hey @JeffDUnity3D, thank you for the quick response. I did read the release notes, but I still don't understand how transactionID change can break the validation code (assuming all our products are consumables and validation is executed inside ProcessPurchase callback).

    To be clear, we have 2 problems:
    - CrossPlatformValidator.Validate() returning an empty array of receipts for valid consumable purchases;
    - 'Already recorded transaction XXX' message (is this expected?).

    Is this something we can fix on our side?

    P.S. We use Unity 2019.4.15.
     
  4. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  5. Arvtesh

    Arvtesh

    Joined:
    Aug 16, 2014
    Posts:
    94
    @JeffDUnity3D, I used validation code from Unity manual as you suggested. Validation succeeds and there is one receipt (IPurchaseReceipt) in the result array. But IPurchaseReceipt.transactionID property seems to return Google OrderID (GPA.3383-4838-5570-8101), is that expected?

    The other issue I have now is OnPurchaseFailed triggered right after ProcessPurchase with
    Unknown reason:
    Code (CSharp):
    1. onPurchaseFailedEvent({0}): productId:com.wordwarmppb.2 message:Item is not owned by the user. {code: 8, M: GPSFTS.HFT}
    We use latest UnityPurchasing.
     
  6. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    Yes, it's expected. Can you confirm that you are using IAP 2.2.5 (menu Window/Unity IAP/IAP Updates..)
     
  7. Arvtesh

    Arvtesh

    Joined:
    Aug 16, 2014
    Posts:
    94
    Yes, we're using IAP 2.2.5 (+UMP 2.2.1):
    image_2020_12_23T15_22_23_705Z.png
    image_2020_12_23T15_24_04_569Z.png
     
  8. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
  9. Arvtesh

    Arvtesh

    Joined:
    Aug 16, 2014
    Posts:
    94
    The logs are from Android device.The product is consumable. Please find below all purchase-related logs we get (that's for another product, logs with IAPManager tag are ours):
    Code (CSharp):
    1.  
    2.    [Log] [IAPManager] BuyProduct(productId=com.wordwarmpob.2)
    3.    BrainGames.WordFarmScapes.Infrastructure.IAPManager:BuyProduct(String, Boolean, PaymentPageOption)
    4.    BrainGames.WordFarmScapesShared.UI.<>c__DisplayClass24_0:<SetupItem>b__0()
    5.    UnityEngine.EventSystems.StandaloneInputModule:Process()
    6.    
    7.    [Log] purchase({0}): com.wordwarmpob.2
    8.    BrainGames.WordFarmScapesShared.UI.<>c__DisplayClass24_0:<SetupItem>b__0()
    9.    UnityEngine.EventSystems.StandaloneInputModule:Process()
    10.  
    11. // Skipped irrelevant logs.
    12.  
    13.     [Log] [IAPManager] ProcessPurchase(productId=com.wordwarmpob.2)
    14.    BrainGames.WordFarmScapes.Infrastructure.IAPManager:UnityEngine.Purchasing.IStoreListener.ProcessPurchase(PurchaseEventArgs)
    15.    UnityEngine.Purchasing.Extension.UnityUtil:Update()
    16.  
    17. // Skipped irrelevant logs.
    18.  
    19.     [Log] Already recorded transaction kmgibjiijepmebkgldcnocpb.AO-J1Ozsu9TYtDyhzu76QIqfUnikwgC6Q-nqECrieZZpEiFguyob4MepuQnMchumwlAZquaicuxdjAC7yQoW2wqwHdnYT0ApDw
    20.     UnityEngine.Purchasing.Extension.UnityUtil:Update()
    21.  
    22.     [Log] onPurchaseFailedEvent({0}): productId:com.wordwarmpob.2 message:Item is not owned by the user. {code: 8, M: GPSFTS.HFT}
    23.     UnityEngine.Purchasing.Extension.UnityUtil:Update()
    24.  
    25.   [Error] [IAPManager] OnPurchaseFailed: product=com.wordwarmpob.2, reason=Unknown
    26.    BrainGames.WordFarmScapes.Infrastructure.IAPManager:UnityEngine.Purchasing.IStoreListener.OnPurchaseFailed(Product, PurchaseFailureReason)
    27.     UnityEngine.Purchasing.Extension.UnityUtil:Update()
    Steps to reproduce for us is start the app, initialize purchasing and buy the product.

    I'll compare out code to what's in Sample IAP Project and write back.
     
  10. JeffDUnity3D

    JeffDUnity3D

    Joined:
    May 2, 2017
    Posts:
    14,446
    @Arvtesh I don't receive the OnPurchaseFailed callback after a successful purchase when using the code in the Sample IAP Project with IAP 2.2.5/2.2.1 with a consumable. Ensure you are returning Complete from ProcessPurchase.
     
  11. Arvtesh

    Arvtesh

    Joined:
    Aug 16, 2014
    Posts:
    94
    Hey @JeffDUnity3D, I think I figured out the problem. There was a ConfirmPendingPurchase() call inside ProcessPurchase(). Removing it resolved the issue. I know this is not intended usage of the method, still would expect to get a warning (or error) in this case instead of OnPurchaseFailed().

    Thanks for your help!
     
    JeffDUnity3D likes this.