question

nick-3 avatar image
nick-3 asked

Error when using RedeemGooglePlayInventoryItems

Hey there, We are currently moving over from V1 to V2. I'm struggling to get in app purchases using real money working as in V1. I am able to make a successful purchase on the google play store. The app switches over to google play's overlay; I purchase the product; and then receive a success on the Unity IAP side.

At this point, I am making the assumption that I need to call RedeemGooglePlayInventoryItems end point in the economy api list. So this is what I am doing. My code is as follows:

     public override void ValidateReceipt(PurchaseEventArgs eventArgs, 
         Action<PlayFabResultCommon> successCallback, 
         Action<PlayFabError> failedCallback)
     {
         GooglePlayReceiptDataObject receiptData = new GooglePlayReceiptDataObject();
         receiptData.Purchase = GooglePlayReceiptDataObject.GooglePurchase.FromJson(eventArgs.purchasedProduct.receipt);
            
         List<GooglePlayProductPurchase> purchases = new List<GooglePlayProductPurchase>(1);
         purchases.Add(new GooglePlayProductPurchase
         {
             ProductId = eventArgs.purchasedProduct.definition.id,
             Token = receiptData.Purchase.PayloadData.signature
         });
            
         RedeemGooglePlayInventoryItemsRequest request = new RedeemGooglePlayInventoryItemsRequest
         {
             Purchases = purchases,
             Entity = new PlayFab.EconomyModels.EntityKey
             {
                 Id = PlayFabSettings.staticPlayer.EntityId,
                 Type = "title_player_account"
             }
         };
         PlayFabEconomyAPI.RedeemGooglePlayInventoryItems(request, successCallback, failedCallback);
     }

The json request body generated by this is the following:

{ "CollectionId": null, "CustomTags": null, "Entity": { "Id": "9RemovedTheseCharactersB", "Type": "title_player_account" }, "Purchases": [{ "ProductId": "gold_pack_100", "Token": "ZmPtdNTJE9YeSfgAvRahpFmLyDheTsIP0A12WWXaqaWiS5DjX40ui/Up7ohtW8ETsGbHCxoT5NwqbY3REmovedSomeCharacters+jO6FFkV2+ko6cKkuhV9Q9WzaRnMzqQDwbLiZIuVyFE/0XPy13B0N0q9JTW0Q8AHR+C4vVs6yav6dq6j2GZ/8tYOVMIxbntCOY008ytZaErU/g6PLolU4sEarwW7bH8pFL/ZNYxvVl4yf1xVaWCcmPkLMEjQiO9nblYY/Fv405/Lm+wZQw76ZXtFlPzQhzvlJrdvy0p6Jg==" }], "AuthenticationContext": null }

The response I get back is: { "code": 400, "status": "BadRequest", "error": "InvalidRequest", "errorCode": 1071, "errorMessage": "GetInAppPurchasesFailure: Failed to get purchases from GooglePlay \nReason:Error deserializing JSON credential data." }

I feel like I'm missing something very important here and hoping someone can call out what I might be doing wrong. I should mention that GooglePlayReceiptDataObject is the equivalent of the data objects found in this documentation: https://learn.microsoft.com/en-us/gaming/playfab/features/economy-v2/tutorials/getting-started-with-unity-and-android With the above documentation being noted as incorrect, I'm unclear on if that data object is even desired?

Also, its important that I am attempting to purchase a bundle and not a store item. The Marketplace ids and friendly ids all match up. In this case is "gold_pack_100", and I am actually able to purchase this item, just not redeem it.

I would REALLY appreciate any help on resolving this as it is a critical piece of the application.

Thanks, ~Nick Thompson

supportdocumentation
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Gosen Gao avatar image
Gosen Gao answered

I've found similar error messages in this thread when setting a malformed service account key: RedeemGooglePlayInventoryItems comes back with OK for bundle but empty content. You can follow Use a service account to create a service account. And then follow Create and delete service account keys to add a Service Account Key. In this process, you can create a private key. The private key is downloaded to your machine and is the only copy of this key. This private key is what we need. Please enter the whole JSON into Service Account Key section. When it is saved successfully, you should be able to see the private key id in Game Manager.

Google OAuth Client ID and the Google OAuth Client Secret are not required if you don't use Google login.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Gosen Gao avatar image
Gosen Gao answered

You need to get purchaseToken from receipt and then use it as the Token. You can refer to Receipt Obfuscation | In App Purchasing | 4.7.0 (unity3d.com).

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

nick-3 avatar image nick-3 commented ·

@Gosen Gao, thanks for getting back to me. I am getting the same error after following the instructions from that post. Left a longer, more detailed post below.

Thanks again, ~N

0 Likes 0 ·
nick-3 avatar image
nick-3 answered

Hey @Gosen Gao. Thanks for getting back to me in such a timely manner. Much appreciated!

I updated our IAP lib and followed the instructions on that link you posted. I am still getting the same error. Hoping you know what might be going on here.

New Code: // Called from Our IStoreListener class ProcessPurchase method public override void ValidateReceipt(PurchaseEventArgs eventArgs, Action successCallback, Action failedCallback) { CrossPlatformValidator validator = new CrossPlatformValidator(GooglePlayTangle.Data(), AppleTangle.Data(), Application.identifier); IPurchaseReceipt[] receipts = validator.Validate(eventArgs.purchasedProduct.receipt);

         List<GooglePlayProductPurchase> purchases = new List<GooglePlayProductPurchase>(1);
         foreach (IPurchaseReceipt receipt in receipts)
         {
             GooglePlayReceipt google = receipt as GooglePlayReceipt;
             purchases.Add(new GooglePlayProductPurchase
             {
                 ProductId = google.productID,
                 Token = google.purchaseToken
             });
         }

         RedeemGooglePlayInventoryItemsRequest request = new RedeemGooglePlayInventoryItemsRequest
         {
             Purchases = purchases,
             Entity = new PlayFab.EconomyModels.EntityKey
             {
                 Id = PlayFabSettings.staticPlayer.EntityId,
                 Type = PlayFabSettings.staticPlayer.EntityType
             }
         };
         Debug.Log(JsonConvert.SerializeObject(request));
         PlayFabEconomyAPI.RedeemGooglePlayInventoryItems(request, successCallback, failedCallback);
     }

The request body json is as follows:

{ "CollectionId":null, "CustomTags":null, "Entity":{"Id":"9-REPLACED-B","Type":"title_player_account"}, "Purchases":[{"ProductId":"gold_pack_500","Token":"ommgioggjafdaklollneaiik.AO-J1OxsSVpgZdVO5DU1aEaTGP72dZgXB_gG6wUWDpFcv4FyuolQJfvWcllI-rMGFUR_ADIQUa3oO_5q2Eg7RjuyiMwqWkult_-REPLACED-"}], "AuthenticationContext":null }

In adb this is the error I am getting, which is the same error unfortunately. 8(

InvalidRequest: GetInAppPurchasesFailure: Failed to get purchases from GooglePlay Reason:Error deserializing JSON credential data.

I should mention this is a bundle within our Economy V2. Maybe I am missing a very simple step? Maybe I have some bit of code wrong? Maybe something is configured incorrectly with our Bundle setup? Any help would be greatly appreciated.

Here is what our bundle setup looks like: Friendly ID: gold_pack_500 ContentType: Bundle Type: bundle Prices: 499 USD Where USD is a Currency Type Items: Title = "gl" | Type = Currency | Quantity = 500 Markeplace Mapping MarkeptPlace = GooglePlay | MarketplaceID = gold_pack_500

Thank you, ~N

6 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Gosen Gao avatar image Gosen Gao commented ·

Have you set the service account key in add-on page?

0 Likes 0 ·
nick-3 avatar image nick-3 Gosen Gao commented ·

@Gosen Gao, good question. In PlayerSettings->In-App Purchasing, we have the service key in the Options text area. However, in the "Receipt Validation Obfuscator" #2 "Paste the key here:", it looks like that key clears out whenever we close the menu. Do you know if this is the default behavior? I've pasted the key in that menu, then selected the Obfuscate Google Play License Key button. Unity reloads the assemblies. But yeah, when we close the menu and reopen it, the text area for the key goes away. Let me try and make a build with this window open and get back to you. Thanks again. Really appreciate the help.

0 Likes 0 ·
Gosen Gao avatar image Gosen Gao nick-3 commented ·

I am not an expert on Unity, so you may contact the Unity forum for professional support. For the service account key I mentioned above, I mean the Google Add-on in PlayFab Game Manager. 5784-image.png

0 Likes 0 ·
image.png (30.5 KiB)
Show more comments
Show more comments
nick-3 avatar image
nick-3 answered

For anyone who might read this in the future. The TL;DR is in the google play services website, you'll need to follow these instructions: https://cloud.google.com/iam/docs/keys-create-delete to add a Service Account Key. Once you do it will create a json object for you. Copy and paste that Object into the PlayFab GooglePlay Addon Service Account Key text field and save.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.