GooglePlayReceipt transactionId is not matching with PurchasedProduct transactionId

Hi after updating the IAP package to 2.3.0 from 1.23.1 (Unity 2018.4.23). GooglePlayReceipt transactionId is not matching with PurchasedProduct transactionId.

Validation code

public bool Validate(PurchaseEventArgs e, out IPurchaseReceipt productReceipt)
{
    var receipt = e.purchasedProduct.receipt;
    var productId = e.purchasedProduct.definition.storeSpecificId;
    var transactionId = e.purchasedProduct.transactionID;

    productReceipt = null;

    try
    {
        var purchaseReceipts = _crossPlatformValidator.Validate(receipt);

        foreach (var purchaseReceipt in purchaseReceipts)
        {
            if (purchaseReceipt.productID == productId && purchaseReceipt.transactionID == transactionId)
            {
                productReceipt = purchaseReceipt;
                break;
            }
        }
    }
    catch (IAPSecurityException)
    {
        return false;
    }

    return true;
}

We use the purchaseToken now, search for purchaseToken on this page for the history https://discussions.unity.com/t/632966 page-2

I can second to this issue, while the unity IAP API gave us an interface with the purchasedProduct as an event (via the
PurchaseEventArgs param) we could match the e.purchasedProduct.transactionId with the receipt.transactionId easily, now those two are diffrent on the android platform (e.purchasedProduct.TransactionId is now being provided as the GoogleBilling v3 purchase token as @JeffDUnity3D stated, while the receipt transactionId stayed in the old format (GPA.xxxxx)).

Please note that this behaviour is clearly wrong on the android side of thinks since the iOS side of things we can still exactly match the e.purchasedProduct.transactionId with the receipts TransactionId

Hi Jeff, Yes I’m aware of that change, but the current implementation is very counterintuitive. A field value must return the same value for all implementations. And also without casting interface to GooglePlayReceipt, it’s impossible to compare.

I do your suggestion as a temporary workaround however this shouldn’t be recommended/suggested way.

For reference, this is my current implementation

if (purchaseReceipt.productID == productId
    && ((purchaseReceipt as GooglePlayReceipt)?.purchaseToken == transactionId
        || (purchaseReceipt as AppleReceipt)?.transactionID == transactionID))
{
    productReceipt = purchaseReceipt;
    break;
}

Hi @JeffDUnity3D (or anyone),

I’m jumping aboard IAPs for the first time with In App Purchasing 4.1.3.

Should I just be storing Product.transactionID for persistence these days?

I don’t have any legacy changes to deal with…
So I don’t need to check against GooglePlayReceipt.purchaseToken at all, is that correct?

I can just store Product.transactionID for both Apple and Google without worry?

What are you using it for? Just checking, if you are not using it then you of course don’t need to store it. And what do you mean by legacy changes? IAP does indeed now use the purchaseToken. Google has not been consistent in this area, and we are hoping for improvements in the upcoming Google Billing Libraries 4 and 5.

That’s good to know, thank you.

For my game, for online co-op sessions (allowing a party to quit and resume their game later), I’m storing some sort of unique ID from Unity’s IAP info after the player purchases a one-time IAP, so my servers know which player is which when resuming.

At first, I thought receipts would be unique, but no.

TransactionID seems to be consistent between sessions and devices at least.

If TransactionID changes later in the future, I’ll handle it, but I can see the Google purchaseToken is used for now. And Apple transactionIDs seem consistent.

Trying my hardest to not bother the user about creating a special account for my game, as I’d have to create my own account system! Just requiring them to sign into Google Play or Game Center, then linking to their purchase, is good enough if I can help it.