You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity3D+PlayFab验证Google Play IAP收据失败求助

Unity Google Play IAP内购PlayFab验证失败(Invalid receipt)排查方案

问题场景

Unity安卓手游中Google Play IAP购买流程正常完成,但调用PlayFab的ValidateGooglePlayPurchase接口时,返回错误:Invalid receipt(错误码1021,HTTP 400)。

验证代码

[System.Serializable]
public class ReceiptWrapper
{
    public string Store;
    public string Payload;
}

[System.Serializable]
public class GooglePayloadWrapper
{
    public string json;
    public string signature;
}

public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
    int pearlAmount = GetPearlAmount(args.purchasedProduct.definition.id);
    
    Debug.Log($"JHL: Processing purchase for product: {args.purchasedProduct.definition.id}");
    Debug.Log($"JHL: Raw receipt: {args.purchasedProduct.receipt}");
    
    try 
    {
        // Parse the outer receipt wrapper
        var wrapper = JsonUtility.FromJson<ReceiptWrapper>(args.purchasedProduct.receipt);
        Debug.Log($"JHL: Store: {wrapper.Store}");
        Debug.Log($"JHL: Payload: {wrapper.Payload}");

        if (Application.platform == RuntimePlatform.Android)
        {
            // Parse the Google Play specific payload
            var gpDetails = JsonUtility.FromJson<GooglePayloadWrapper>(wrapper.Payload);
            Debug.Log($"JHL: Google JSON: {gpDetails.json}");
            Debug.Log($"JHL: Google Signature: {gpDetails.signature}");

            // The json field is already a JSON string, don't parse it again
            var request = new ValidateGooglePlayPurchaseRequest
            {
                ReceiptJson = gpDetails.json,
                Signature = gpDetails.signature,
                CurrencyCode = args.purchasedProduct.metadata.isoCurrencyCode,
                PurchasePrice = (uint)(args.purchasedProduct.metadata.localizedPrice * 100)
            };

            // Log the complete request for debugging
            Debug.Log($"JHL: Complete request being sent to PlayFab:");
            Debug.Log($"JHL: ReceiptJson: {request.ReceiptJson}");
            Debug.Log($"JHL: Signature: {request.Signature}");
            Debug.Log($"JHL: CurrencyCode: {request.CurrencyCode}");
            Debug.Log($"JHL: PurchasePrice: {request.PurchasePrice}");

            PlayFabClientAPI.ValidateGooglePlayPurchase(request,
                result => {
                    Debug.Log($"JHL: Purchase validation successful!");
                    Player.Instance.AddPearls(pearlAmount);
                    UIFunctions.Instance.ShowMessage($"Purchase successful!\nAdded {pearlAmount} pearls");
                },
                error => {
                    Debug.LogError($"JHL: Failed to validate purchase: {error.ErrorMessage}");
                    Debug.LogError($"JHL: Error details: {JsonUtility.ToJson(error)}");
                    Debug.LogError($"JHL: HTTP code: {error.HttpCode}");
                    Debug.LogError($"JHL: Error code: {error.Error}");
                    UIFunctions.Instance.ShowMessage("Purchase validation failed.\nPlease contact support.");
                });
        }
    }
    catch (System.Exception e)
    {
        Debug.LogError($"JHL: Exception while processing receipt: {e}");
        Debug.LogError($"JHL: Stack trace: {e.StackTrace}");
    }

    return PurchaseProcessingResult.Complete;
}

相关日志

Info Unity JHL: Processing purchase for product: com.pixelfish.pearl100
Info Unity IAPManager:ProcessPurchase(PurchaseEventArgs)
Info Unity UnityEngine.Purchasing.PurchasingManager:ProcessPurchaseIfNew(Product)
Info Unity UnityEngine.Purchasing.Extension.UnityUtil:Update()

Info Unity JHL: Final Receipt JSON being sent: {"orderId":"GPA.3396-9471-9799-74081","packageName":"com.PufferfishStudios.PixelFish","productId":"com.pixelfish.pearl100","purchaseTime":1743075692104,"purchaseState":0,"purchaseToken":"doeklojbfffbgphcipbmflaa.AO-J1OzClvRrlk2HoHz343vYDytID4Cxjx2axF-r9-VcNgCIKtEk5q3gBqatb9DUQPubVGeAYT9dGgxSfJMLYwVCKw8QX2_Lw_3q4PVTRlutjLP0yoLcL8A","quantity":1,"acknowledged":false}
Info Unity IAPManager:ProcessPurchase(PurchaseEventArgs)
Info Unity UnityEngine.Purchasing.PurchasingManager:ProcessPurchaseIfNew(Product)
Info Unity UnityEngine.Purchasing.Extension.UnityUtil:Update()

Info Unity JHL: Final Signature being sent: jEBe5C6yXZfN/Ro36+FwtOeXFkhQcTvEHE7/TlJZkOVGfZxT6FKTNXrWqBG0f6Omi5+xz03RUoSN6rnQimM6ANCRe3IKwYfgRA9PkFUGjZ0Eo2c/5yRTlNLmuyEro9VkT/L7VOwl9Vxcvkg7/uQr+6SsAUhSJ7cd5cyKnX8DxvsgZN02zBa9ajOm/JzhyuMJDlNEmQ5YbtGpjxGj8hFiSy/yBrMskkkhSY+MCbUhU/yAvDcT0bOx/NCzqud7Nt5odkbZqKQ8OsPRRh/2sbXJ21oeRde2pASceQqHdeUhRe+O+MuAyWHwxdXmqUFpsDdYsxvudycLLqI9oXnX5Yyg6g==
Info Unity IAPManager:ProcessPurchase(PurchaseEventArgs)
Info Unity UnityEngine.Purchasing.PurchasingManager:ProcessPurchaseIfNew(Product)
Info Unity UnityEngine.Purchasing.Extension.UnityUtil:Update()

Info Unity JHL: Final Currency: GBP
Info Unity IAPManager:ProcessPurchase(PurchaseEventArgs)
Info Unity UnityEngine.Purchasing.PurchasingManager:ProcessPurchaseIfNew(Product)
Info Unity UnityEngine.Purchasing.Extension.UnityUtil:Update()

Info Unity JHL: Final Price: 99
Info Unity IAPManager:ProcessPurchase(PurchaseEventArgs)
Info Unity UnityEngine.Purchasing.PurchasingManager:ProcessPurchaseIfNew(Product)
Info Unity UnityEngine.Purchasing.Extension.UnityUtil:Update()

Error Unity JHL: Failed to validate purchase: Invalid receipt
Error Unity <>c:b__18_1(PlayFabError)
Error Unity PlayFab.Internal.PlayFabUnityHttp:OnResponse(String, CallRequestContainer)
Error Unity PlayFab.Internal.d__12:MoveNext()
Error Unity UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

Error Unity JHL: Error details: {"ApiEndpoint":"/Client/ValidateGooglePlayPurchase","HttpCode":400,"HttpStatus":"BadRequest","Error":1021,"ErrorMessage":"Invalid receipt"}
Error Unity <>c:b__18_1(PlayFabError)
Error Unity PlayFab.Internal.PlayFabUnityHttp:OnResponse(String, CallRequestContainer)
Error Unity PlayFab.Internal.d__12:MoveNext()
Error Unity UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

Error Unity JHL: HTTP code: 400
Error Unity <>c:b__18_1(PlayFabError)
Error Unity PlayFab.Internal.PlayFabUnityHttp:OnResponse(String, CallRequestContainer)
Error Unity PlayFab.Internal.d__12:MoveNext()
Error Unity UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

Error Unity JHL: Error code: InvalidReceipt
Error Unity <>c:b__18_1(PlayFabError)
Error Unity PlayFab.Internal.PlayFabUnityHttp:OnResponse(String, CallRequestContainer)
Error Unity PlayFab.Internal.d__12:MoveNext()
Error Unity UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

排查步骤

  • 核对PlayFab公钥配置
    登录PlayFab后台,进入设置 > 变现 > Google Play,确保填入的RSA公钥和Google Play控制台中应用内结算页面的公钥完全一致,不要包含多余的空格或换行符。

  • 检查包名与产品ID一致性
    日志中收据包名是com.PufferfishStudios.PixelFish,产品ID是com.pixelfish.pearl100,需确认:

    • Google Play控制台应用包名、PlayFab后台配置的包名完全匹配
    • Google Play和PlayFab中配置的产品ID完全一致(Google Play产品ID区分大小写)
  • 处理订单确认状态
    日志显示acknowledged:false,虽然不是直接验证失败原因,但Google Play要求购买后必须调用acknowledgePurchase确认订单,未确认的订单可能引发后续问题。可在验证成功后添加确认逻辑:

    var product = args.purchasedProduct;
    if (product.definition.type is ProductType.Consumable or ProductType.NonConsumable)
    {
        var req = new GooglePlayAcknowledgePurchaseRequest(product.receipt);
        UnityPurchasing.Instance.GooglePlayStore.AcknowledgePurchase(req, 
            success => Debug.Log("订单确认成功"), 
            fail => Debug.LogError("订单确认失败:" + fail));
    }
    
  • 确认收据与签名完整性
    检查日志中Final Receipt JSON和Final Signature是否完整,无字符截断或修改,确保传递给PlayFab的参数和日志中一致。

  • 区分测试与生产环境
    若使用Google Play测试账号,需确保PlayFab后台环境配置对应;正式环境必须使用发布版APK测试,测试账号无法在正式环境中生效。

  • 升级PlayFab SDK
    确保使用最新版PlayFab Unity SDK,旧版本可能存在接口参数兼容问题,同时确认PurchasePrice(最小货币单位)和CurrencyCode(ISO标准代码)参数传递正确(日志中99对应0.99GBP、GBP代码均正确)。

内容的提问来源于stack exchange,提问作者Jonny Holmes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 16:08:09