#Recommended IAP redemption/consumption flow

16 messages · Page 1 of 1 (latest)

naive tide
#

Hey, doing Redeem/Consume purchasing stuff and was curious what other people have been doing. My current approach is to call both PlayFab's RedeemGooglePlayPurchase and Google's ConsumeProduct in an AzureFunction to validate purchases, but wasn't 100% sure if this was the right approach. What is the recommended flow? I'm assuming that the validation is unsafe to call on the client side but I am not sure. There is a lot of outdated information online so I decided to ask here.

opal geode
#

(From the chat thread)

Per the Google Redemption tutorial, you will need to call consume after calling Redeem. We've talked about adding it to the backend (and may still at some point), but both Unity and Unreal will run this step for you so in the general it would be redundant.

https://learn.microsoft.com/en-us/gaming/playfab/features/economy-v2/tutorials/marketplace-redemption/google#step-4-consumption

Also, it's safe to call both RedeemGooglePlayInventoryItems and consume from the client.

Set up a PlayFab bundle that can be purchased from Google Play Store

naive tide
#

Cool, I had no idea that Unity calls consume for us already

#

So all I have to do is call Redeem?

opal geode
#

It does it in a specific way and I don't believe the sample we ship is correct (somebody is currently updating it).

#

Just make sure the Redeem call for the purchase returns a success result asynchronously -before- returning status Complete.

#

This bit is handling unity async callbacks incorrectly.

    RedeemGooglePlayInventoryItemsResponse redeemResponse = new();
    PlayFabEconomyAPI.RedeemGooglePlayInventoryItems(request, result => {
        redeemResponse = result;
        Debug.Log("Processed receipt validation.");
    },
        error => Debug.Log("Validation failed: " + error.GenerateErrorReport()));
    if (redeemResponse?.Failed.Count > 0)
    {
        Debug.Log("Validation failed for " + redeemResponse.Failed.Count + " receipts.");
        Debug.Log(redeemResponse.Failed.Serialize().ToSafeString());
        return PurchaseProcessingResult.Pending;
    }
    else
    {
        Debug.Log("Validation succeeded!");
    }

    return PurchaseProcessingResult.Complete;
naive tide
#

Thank you, it makes sense now that I know Unity consumes it automativally

naive tide
#

I'm a bit surprised that redeem and consume can be called client side. When something is fully client side I just assume that it is hackable by the client

opal geode
#

All the Redeem APIs are designed to be callable by the client (that's the primary use case). We have protections in the system design that make them safe.

naive tide
#

What I meant is that calling Redeem and then telling Google that it isnt consumed yet

#

So not a PlayFab exploit but more of a Google one

#

But if its a widely used workflow I'll trust it

opal geode
#

If you don't consume an entitlement, we do 2 things:

  1. Check whether we've already seen the receipt. If not, grant. If so, dedupe.
  2. Tell you what we did.

There are lots of response options based on the input, but it's always safe.

naive tide
#

For anyone looking at this in the future: Should be like

        public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e) {
            GooglePurchase googlePurchase = GooglePurchase.FromJson(e.purchasedProduct.receipt);
            string productId = googlePurchase.PayloadData.JsonData.productId;
            string token = googlePurchase.PayloadData.JsonData.purchaseToken;

            RedeemGooglePlayInventoryItemsRequest request = new RedeemGooglePlayInventoryItemsRequest() {
                Entity = , //EntityKeyHere
                Purchases = new List<GooglePlayProductPurchase>() {
                    new GooglePlayProductPurchase() {
                        ProductId = productId,
                        Token = token
                    }
                }
            };
            PlayFabEconomyAPI.RedeemGooglePlayInventoryItems(request,
                result => {
                    _storeController.ConfirmPendingPurchase(e.purchasedProduct);
                },
                error => {
                    Debug.LogError($"Failed to redeem purchase. {error.GenerateErrorReport()}");
                });
            return PurchaseProcessingResult.Pending;
        }