Help with RedeemGooglePlayPurchaseAsync

Hi, I’m using Economy Beta but regarding IAPs, have been relying on the Sample code provided (4.1.3) I’ve not seen anything regarding Economy integration though e.g. RedeemGooglePlayPurchaseAsync. Prior to trying this I’ve been processing purchases rewards manually e.g. awarding currency.

I’ve tried following another resolved thread regarding the redemption of purchases but am having problems the solution provided. Any insight would be great, thanks. Trying it as suggested within ‘ProcessPurchase’ I get the error ‘get_cloudProjectId can only be called from the main thread.’

To add to this, the Unity docs suggested ‘json’ and ‘signature’ keys link to deprecated '‘Google Play Billing AIDL’ docs:

public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
        {
            _purchaseInProgress = false;
            var iapReturnCode = IAPReturnCode.OK;

            var id = args.purchasedProduct.definition.id.Trim();
            var msg = string.Format("[StorePurchasesHelper] process purchase: PASS. Product: {0}{1}",
                args.purchasedProduct.definition.id, Environment.NewLine);
            Helper.Log(msg);

            //if (validPurchase)
            try
            {
                var receipt = args.purchasedProduct.receipt;
                var wrapper = (Dictionary<string, object>)MiniJson.JsonDecode(receipt);
                if (wrapper == null)
                {
                    throw new Exception();
                }

                // Corresponds to http://docs.unity3d.com/Manual/UnityIAPPurchaseReceipts.html
                var store = (string)wrapper["Store"];
                var payload = (string)wrapper["Payload"]; // For Apple this will be the base64 encoded ASN.1 receipt

                // For GooglePlay payload contains more JSON
                if (_isGooglePlayStoreSelected)
                {
                    var details = (Dictionary<string, object>)MiniJson.JsonDecode(payload);
                    var gpJson = (string)details["json"];
                    var gpSig = (string)details["signature"];

                    var redeemArgs = new Purchases.RedeemGooglePlayStorePurchaseArgs(
                        args.purchasedProduct.definition.id,
                        gpJson,
                        gpSig,
                        (int)(args.purchasedProduct.metadata.localizedPrice * 100),
                        args.purchasedProduct.metadata.isoCurrencyCode);

                    var redeemResult = Task.Run(async () => await Economy.Purchases.RedeemGooglePlayPurchaseAsync(redeemArgs)).Result;

                    if (redeemResult.Verification.Status == GoogleVerification.StatusOptions.VALID)
                    {
                        Helper.Log(string.Format("{0} redeemed successfully.{1}",
                            args.purchasedProduct.definition.id, Environment.NewLine));
                    }
                    else
                    {
                        Helper.Log(string.Format("{0} verification failed with status:{1}.{2}",
                            args.purchasedProduct.definition.id,
                            redeemResult.Verification.Status.ToString(),
                            Environment.NewLine), true, Helper.LogType.Warning);

                        iapReturnCode = IAPReturnCode.FAILED;
                    }
                }
                else
                {
                    // ToDo .....

                    //var redeemArgs = new Purchases.RedeemAppleAppStorePurchaseArgs("PURCHASE_ID", "RECEIPT_FROM_APP_STORE", 0, "USD");
                    //var redeemResult = Task.Run(async () => await Economy.Purchases.RedeemAppleAppStorePurchaseAsync(redeemArgs)).Result;
                }
            }
            catch (Exception e)
            {
                Helper.LogException(e);

                iapReturnCode = IAPReturnCode.FAILED;
            }

            PurchaseCompleteEvent?.Invoke(id, iapReturnCode, PurchaseFailureReason.Unknown);

            return PurchaseProcessingResult.Complete;
        }

Does IAP work as expected when you don’t implement the redeem logic, are you able to make a purchase by just returning PurchaseProcessingResult.Complete with no other code? Also, what Unity docs are you referring to? You pointed to android.com

Hi @JeffDUnity3D , yeah, the actual purchases appear to be fine.

Prior to adding the try-catch RedeemGooglePlayPurchaseAsync code I just used the store Identifier to source the matching RealMoneyPurchaseDefinition then awarded the currency manually (Economy.PlayerBalances.IncrementBalanceAsync). Reading docs again though, I thought I was supposed to actually be using RedeemGooglePlayPurchaseAsync.

Regarding the GooglePlay payload:
https://docs.unity3d.com/Packages/com.unity.purchasing@4.1/manual/GoogleReceipt.html

INAPP_PURCHASE_DATA & INAPP_DATA_SIGNATURE links.

Cheers, s

Can you confirm that you received the system purchase popup on your Android device? Is your user account configured as a tester? If so, they the dialog should say your credit card won’t be charged. Unity IAP is indeed using Google Play Billing v3, so the documentation needs to be updated.

Yeah, I’d see Google’s purchase popups and the error would be thrown after that.

Yeah, I’m registered as a tester and correct, no charge to my card.

Cheers

1 Like

@stu_dious did you got this working? I was always receiving the INVALID_RECEIPT error but I changed to your code and now it’s stuck in the RedeemGooglePlayPurchaseAsync call.

Sorry Tomaz, it’s not something I’ve had the opportunity to go back to. Think we just used Unity’s CrossPlatformValidator to check a purchase receipt was returned then handled the purchase reward locally or in CloudCode.

1 Like