Hello,
We are trying to validate iOS receipt, but ValidateIOSReceipt function always returns error.
Request Type or Compress API Data settings not helping.
Project Id: 4140
Environment:
What we checked out:
Request:
{ "CurrencyCode": "RUB", "PurchasePrice": 149, "ReceiptData": "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" }
Response:
Purchase Failed UnityEngine.Logger:Log(LogType, Object) SP.Services.Purchases.<>c__DisplayClass50_0:<Purchase>b__1(SFError) SP.Services.Purchases.<>c__DisplayClass72_0:<OnTransactionUpdated>b__1(PlayFabError) PlayFab.Internal.<Post>d__12:MoveNext() UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr) (Filename: ./Runtime/Export/Debug/Debug.bindings.h Line: 48) { "SFErrorCode": -1, "CustomErrorCode": 1123, "ErrorMessage": "/Client/ValidateIOSReceipt: Request timeout" }
Response Glossary:
How it works?
public void OnTransactionUpdated(ISN_SKPaymentTransaction transaction) { //Transactions have been updated. //Let's act accordinaly SFDebug.Log("transaction JSON: " + JsonUtility.ToJson(transaction)); SFDebug.Log("OnTransactionComplete: " + transaction.ProductIdentifier); SFDebug.Log("OnTransactionComplete: state: " + transaction.State); SFDebug.Log(transaction.Product.Dump()); switch (transaction.State) { case ISN_SKPaymentTransactionState.Purchasing: //No actions is reuiredhere, we probably don't even have a ProductIdentifier //but we can use this callback to show preloader for example, //since we know that user is currently //working on this transaction break; case ISN_SKPaymentTransactionState.Purchased: case ISN_SKPaymentTransactionState.Restored: //Our product has been succsesly purchased or restored //So we need to provide content to our user depends on productIdentifier SFDebug.Log("Validation of IOS Reciept"); var receipt = ISN_SKPaymentQueue.AppStoreReceipt; var request = new ValidateIOSReceiptRequest { CurrencyCode = transaction.Product.PriceLocale.CurrencyCode, PurchasePrice = (int) transaction.Product.Price, ReceiptData = receipt.AsBase64String }; SFDebug.Log(request.Dump()); PlayFabClientAPI.ValidateIOSReceipt(request, result => { SFDebug.Log("Validation Completed"); onPurchaseCompleted?.Invoke(); }, error => { SFDebug.Log("Validation Failed"); onPurchaseFailed?.Invoke(new SFError((int) error.Error, error.GenerateErrorReport())); }); ISN_SKPaymentQueue.FinishTransaction(transaction); break; case ISN_SKPaymentTransactionState.Deferred: //iOS 8 introduces Ask to Buy, which lets parents approve any //purchases initiated by children //You should update your UI to reflect this deferred state, //and expect another Transaction Complete to be called again //with a new transaction state //reflecting the parent’s decision or after the transaction times out. //Avoid blocking your UI or gameplay while waiting //for the transaction to be updated. break; case ISN_SKPaymentTransactionState.Failed: //Our purchase flow is failed. //We can unlock intrefase and repor user that the purchase is failed. SFDebug.Log("Transaction failed, code: " + transaction.Error.Code); SFDebug.Log("Transaction failed, description: " + transaction.Error.Message); onPurchaseFailed?.Invoke(new SFError(transaction.Error.Code, transaction.Error.Message)); //at this point we just need to finish the transaction ISN_SKPaymentQueue.FinishTransaction(transaction); break; } if (transaction.State == ISN_SKPaymentTransactionState.Failed) { SFDebug.Log("Error code: " + transaction.Error.Code + "\n" + "Error description:" + transaction.Error.Message); } else { SFDebug.Log("product " + transaction.ProductIdentifier + " state: " + transaction.State.ToString()); } }
Answer by Marcus Nixon · May 14, 2019 at 05:57 PM
Unity 2019 was released last month and we are in the midst of testing it with the PlayFab SDK. In order to circumvent this issue, our recommendation is to stay with Unity 2018 until our team has had a chance to complete validation testing on the SDK and make any changes needed. I am also opening up a bug report for this issue so that it will be tracked. Thanks for bringing this to our attention.
Answer by Marcus Nixon · May 08, 2019 at 06:44 PM
Hi secretplacestudio,
The request timeout error is usually related to an API call that took too much time to complete. Can you confirm back how many items are in your receipt and how much time the API call took before it failed?
Answer by secretplacestudio · May 08, 2019 at 10:29 PM
Hey @Marcus Nixon,
It's 1 consumable item and It takes about 1-2 minutes.
Answer by Marcus Nixon · May 09, 2019 at 07:20 PM
1 consumable item for 1-2 minutes is most likely causing the timeout. Let me investigate what the best options are to resolve this.
Answer by Marcus Nixon · May 09, 2019 at 08:32 PM
Your call to VerifyReceipt was successful, but can you confirm that you did not receive a status code like the ones referenced at this site? https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html#//apple_ref/doc/uid/TP40010573-CH104-SW2
It was empty response 200 OK. Then I tried to send request 2nd Time and I got error code and message that this receipt was already used
Also I saw play stream event in postman's playfab account
Answer by Marcus Nixon · May 10, 2019 at 02:12 PM
Sounds like the issue was the receipt itself. Our API report also shows that your ValidateIOSReceipt calls are taking about .5 seconds to complete, so doesn't seem to be an issue from that perspective.
Yes. I thought that it might be issue in Compress Api Data toggle. I tried different approaches but nothing works(
Answer by Marcus Nixon · May 10, 2019 at 04:08 PM
Can you try stepping through these troubleshooting steps for validation problems with iTunes receipts and let me know your results? https://community.playfab.com/questions/124/205469588-Validation-problems-with-iTunes-receipts.html
Do u have an email where i can share info I collected?
Answer by secretplacestudio · May 10, 2019 at 06:22 PM
Answer by Marcus Nixon · May 10, 2019 at 09:43 PM
Can you confirm that you are passing the correct data into the ValidateIOSReceipt call? You can reference it here. https://docs.microsoft.com/en-us/rest/api/playfab/client/platform-specific-methods/validateiosreceipt?view=playfab-rest
The ReceiptData param should receive the string that is passed back by the App Store as a result of a successful purchase.
Yes. In postman it works. You can see how this request looks above .But when I'm sending same request from iOS device it gives me error
Answer by secretplacestudio · May 13, 2019 at 02:35 PM
@Marcus Nixon Hello. We cant resolve this problem. Can we sync with to see which data do u recieve from iphone. I have no idea why through the postman api call works and through ios device - no :/