IAP Validation
Introduction
Cheaters and invalid IAP transactions can cause Adjust & Looker dashboards to display inaccurate values and the UA networks to train their algorithms on bad data. This can lead to the contamination of UA algorithms' decision-making process and incorrect game design choices.
LionSDK offers static methods for IAP receipt validation to help reduce or eliminate the negative impacts of cheaters’ IAP transactions.
What does the package do?
When configured correctly:
Fires an
inapp_purchaseevent to the backend for every purchase.Includes a
ValidationStatusfield indicating whether the purchase is valid.
Fires a network-specific revenue event
iap_purchasefor Adjust, depending on the validation result.
Requirements
LionSDK package installed.
Unity In-App Purchasing 4.x.x , installed and configured.
For external validators (i.e Adjust or Nakama), additional setup is required. This setup is explained in their own page as explained in next section.
Selecting desired Validator in Lion Settings.
Validators
The behaviour of the system is determined by the selected Validator in the Lion Settings:

Adjust Validator Uses Adjust purchase verification APIs to validate receipts and fires Adjust revenue events for valid purchases.
Nakama Validator Uses nakama purchase verification APIs to validate receipts and fires Adjust event events for valid purchases.
The Nakama validator will be removed in the future, with validation being moved to the Adjust Validator as the sole Validator.
No Validator Performs no real validation; always treats purchases as “not verified” while still allowing your game to send IAP events.
Remove Events (if applicable)
LionSDK will automatically fire the required Adjust and Analytics IAP events. In your Unity Project, you should remove these events from your game code to prevent duplication and overcounting:
Remove any existing Adjust IAP-related events (iap_purchase, purchase_failed, purchase_unknown and purchase_notverified)
Remove any existing calls to LionAnalytics.InAppPurchase
Implementation
Call IAPValidation.ValidateAndLog()
IAPValidation.ValidateAndLog()If you use Unity Purchasing, you typically want to call IAPValidation.ValidateAndLog() in your ProcessPurchase method. This will send your receipt to our remote receipt validation service and log the results to both Lion Analytics and Adjust.
Parameters:
Productproduct: this is theUnityEngine.Purchasing.Productobject that Unity Purchasing provides in theProcessPurchasefunction’sPurchaseEventArgsparameter’spurchasedProductfield.IAPGameplayInfoiapGameplayInfo: This object contains information required by LionAnalytics, including details about the in-game rewards. These include:ListReceivedItemsListReceivedCurrenciesStringPurchaseLocation
ActiononSuccess(optional): This callback, if provided, will be raised if the receipt is valid.ActiononFailure(optional): This callback, if provided, will be raised if the receipt has not been validated. TheValidationStatuswill provide the reason for the failure to validate.Dictionary<string, object>additionalData(optional): This info will be stamped on to the Lion Analytics InAppPurchase and LionDebug events that get fired after validation is complete.
Examples:
Simple inline call:
using LionStudios.Suite.Purchasing;
IAPValidation.ValidateAndLog(
purchaseEventArgs.purchasedProduct,
new IAPGameplayInfo(
new List<Item>()
{
new Item("NoAds", 1),
new Item("SpecialWeapon", 1),
new Item("BonusCards", 10)
},
new List<VirtualCurrency>()
{
new VirtualCurrency("coins", "normal", 10000),
new VirtualCurrency("gems", "special", 10)
},
"shop"));
Inline call with additional data:
using LionStudios.Suite.Purchasing;
IAPValidation.ValidateAndLog(
purchaseEventArgs.purchasedProduct,
new IAPGameplayInfo(
new List<Item>()
{
new Item("NoAds", 1),
new Item("SpecialWeapon", 1),
new Item("BonusCards", 10)
},
new List<VirtualCurrency>()
{
new VirtualCurrency("coins", "normal", 10000),
new VirtualCurrency("gems", "special", 10)
},
"shop"),
additionalData : new Dictionary<string, object>()
{
{ "PlayerRank", GameManger.PlayerRank },
{ "Difficulty", GameManger.Difficulty }
});
Full OnPurchaseConfirmed Example (Unity IAP 5.x.x)
using LionStudios.Suite.Purchasing;
PurchaseProcessingResult IStoreListener.ProcessPurchase(PurchaseEventArgs purchaseEventArgs)
{
/// Your code
Product product = purchaseEventArgs.purchasedProduct;
IAPGameplayInfo gameplayInfo;
switch (product.definition.id)
{
case "com.company.game.noads":
gameplayInfo = new IAPGameplayInfo(
new List<Item>(){ new Item("NoAds", 1) },
new List<VirtualCurrency>(),
"ingame");
break;
case "com.company.game.noadsspecial":
gameplayInfo = new IAPGameplayInfo(
new List<Item>(){ new Item("NoAds", 1) },
new List<VirtualCurrency>() { new VirtualCurrency("coins", "normal", 1000) },
"specialpopup");
break;
case "com.company.game.coinpack1":
gameplayInfo = new IAPGameplayInfo(
new List<Item>(),
new List<VirtualCurrency>() { new VirtualCurrency("coins", "normal", 1000) },
"iapshop");
break;
case "com.company.game.coinpack2":
gameplayInfo = new IAPGameplayInfo(
new List<Item>(),
new List<VirtualCurrency>() { new VirtualCurrency("coins", "normal", 5000) },
"iapshop");
break;
default:
gameplayInfo = new IAPGameplayInfo(null, null, "unknown");
break;
}
IAPValidation.ValidateAndLog(product, gameplayInfo);
// Your code for rewarding the player
}
Conditional reward
In some rare cases, you’ll want to reward the player only if the receipt is valid. This is not normal behaviour and should be reserved for multiplayer games where cheaters can harm the experience of other players.
In this case, you can do as shown in the example below
IAPValidation.ValidateAndLog(
product,
gameplayInfo,
() => GiveReward(product.definition.id),
DisplayError);
void GiveReward(string productId)
{
// Your code for rewarding the player
}
void DisplayError(ValidationStatus status)
{
// Your code for displaying an error message to the player
}
private void GiveReward(string productId)
{
// Your reward logic
}
private void DisplayError(ValidationStatus status)
{
// Show message to player/log error
}
Validation
If the package is implemented correctly, for each purchase, two events will be fired:
inapp_purchase: a LionAnalytics event used for analytics on Looker.iap_purchase: a native Adjust event used by Adjust for revenue metrics.
Make sure that these events are received by following either of the paths below:
If you have access to Looker, for each relevant event, check the following:
The event name appears [ref]
If you do not have access to Looker, please use the LionAnalytics QA Tool following the instructions here: Event Validation
.png?alt=media)
In Looker,inapp_purchase events have a ValidationStatus parameter that can be:
Success: The receipt is valid.Failure: The receipt is invalid. Probably a cheater.Error: Something went wrong when trying to validate the receipt, so we can’t define if the receipt is valid.
TroubleShooting
Many (or all) transactions showing
Error validating IAP/Failurein Looker.Explanation: This kind of failure indicates an error communicating with Google, leading to a
Failurestatus and a validation message,Error validating IAP.Cause: All games published in Lion Studios Google Play account(s) should already have the correct API Service Account credentials in place for all games, so while this is the most common cause for the error, it is not common for our games.
The cause we see most often is a bug in Google Play that occurs when your IAP bundles are created before linking your API Service Account on Google Play Console. Google assumes you first linked your API Service account, then added your various IAP packages. If you did this out of order, Google won’t recognize your existing IAP bundles.
Resolution: Go to your IAP bundle in your Google Play Console and edit some details such as
descriptionof the IAP and save it again. We usually add aspace, save changes, then remove the addedspaceand save again. Any change made to the IAP bundle will trigger Google to reread IAP bundles, and should fix the bug so these bogus failures go away.
FAQ
I’m seeing the error:
Library\\PackageCache\\com.lionstudios.beta.iap@0.1.0-b9\\Runtime\\IAPValidation.cs(128,25): error CS0103: The name ‘STORE NAME’ does not exist in the current contextPlease switch Unity Build Settings to iOS or Android platform.
Integration of Voxel Buster’s Essential Kit
If you are using this package for your IAPs, follow the steps below to integrate with our IAP Validation module:
There is a PurchaseData class which provides information about Receipt.
To resolve the mismatch, use the method below:
public string ReceiptAsUnityIAPJson() { var jsonObject = new { Payload = Transaction.Receipt, Store = HardwareUtils.IsIosBuild() ? "AppleAppStore" : "GooglePlay", TransactionID = Transaction.Id }; return JsonConvert.SerializeObject(jsonObject); }
Last updated
Was this helpful?