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:
- Unity3D 2019.1.1
- Latest Playfab SDK
- iOS 10.3.3 (Sandbox)
What we checked out:
- Check Apple's add-on settings (OK)
- Check ITC product id and Playfab product id (OK)
- Check receipt with https://sandbox.itunes.apple.com/verifyReceipt (SUCCESS)
- Check request with Postman and ValidateiOSReceipt (SUCCESS)
- Check other playfab functions (SUCCESS)
- Android receipt validation (SUCCESS)
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:
- SFErrorCode = Game Internal Custom Code
- Error Message = PlayfabError.GenerateErrorReport
- CustomErrorCode = PlayfabError.Error (parsed to int)
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()); } }