Подтверждение получения помогает предотвратить доступ пользователей к контенту, который они не приобрели.
Точка проверки
Рекомендуется проверять квитанцию в точке распространения контента вашего приложения.
- Локальная проверка: для контента на стороне клиента, где весь контент содержится в приложении и активируется после покупки, проверка должна выполняться на целевом устройстве без необходимости подключения к удаленному серверу. Unity IAP поддерживает локальную проверку в вашем приложении. Дополнительную информацию см. в разделе Локальная проверка ниже.
- Удаленная проверка: для содержимого на стороне сервера, где содержимое загружается после покупки, проверка должна выполняться на сервере до того, как содержимое будет выпущено. Unity не поддерживает проверку на стороне сервера; однако доступны сторонние решения, такие как проект IAP Нобуёри Такахаши.
Локальная проверка
Важно. Хотя Unity IAP предоставляет локальный метод проверки, локальная проверка более уязвима для мошенничества. Проверка конфиденциальных транзакций на стороне сервера, где это возможно, считается лучшей практикой. Для получения дополнительной информации см. Apple и Документация для Android по предотвращению мошенничества.
Если контент, который покупает пользователь, уже существует на устройстве, приложению просто нужно принять решение о его разблокировке.
Unity IAP предоставляет инструменты, помогающие скрывать контент, а также проверять и анализировать квитанции в магазинах Google Play и Apple.
Запутывание ключей шифрования
Проверка получения выполняется с использованием известных ключей шифрования. Для вашего приложения это зашифрованный открытый ключ Google Play и/или корневой сертификат Apple.
Если пользователь может их заменить, он может обойти ваши проверки подтверждения получения, поэтому важно затруднить пользователю простой поиск и изменение этих ключей.
Unity IAP предоставляет инструмент, который может помочь вам запутать ваши ключи шифрования в вашем приложении. Это сбивает с толку или путает ключи, так что пользователю гораздо труднее получить к ним доступ. В строке меню Unity выберите Окно > Unity IAPСокращение Unity In App Купить
См. в Словарь > Обфускатор проверки получения IAP.
В этом окне кодируется как корневой сертификат Apple (в комплекте с Unity IAP), так и ваш открытый ключ Google Play (из Службы и API консоли разработчика Google Play) на два разных файла C#: AppleTangle и GooglePlayTangle. Они будут добавлены в ваш проект для использования в следующем разделе.
Обратите внимание, что вам не нужно предоставлять открытый ключ Google Play, если вы ориентируетесь только на магазины Apple, и наоборот.
Проверка квитанций
Используйте класс CrossPlatformValidator
для проверки в магазинах Google Play и Apple.
Вы должны предоставить этому классу либо свой открытый ключ Google Play, либо корневой сертификат Apple, либо и то, и другое, если вы хотите пройти проверку на обеих платформах.
CrossPlatformValidator
выполняет две проверки:
- Подлинность квитанции проверяется с помощью проверки подписи.
- Идентификатор пакета приложения в квитанции сравнивается с идентификатором в вашем приложении. Исключение InvalidBundleId возникает, если они не совпадают.
Обратите внимание, что валидатор проверяет только квитанции, созданные на платформах Google Play и Apple. Квитанции, сгенерированные на любой другой платформе, включая подделки, сгенерированные в редакторе, выдают IAPSecurityException.
При попытке проверить квитанцию для платформы, для которой вы не предоставили секретный ключ, возникает MissingStoreSecretException.
public PurchaseProcessingResult ProcessPurchase (PurchaseEventArgs e)
{
bool validPurchase = true; // Presume valid for platforms with no R.V.
// Unity IAP's validation logic is only included on these platforms.
#if UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_OSX
// Prepare the validator with the secrets we prepared in the Editor
// obfuscation window.
var validator = new CrossPlatformValidator(GooglePlayTangle.Data(),
AppleTangle.Data(), Application.bundleIdentifier);
try {
// On Google Play, result has a single product ID.
// On Apple stores, receipts contain multiple products.
var result = validator.Validate(e.purchasedProduct.receipt);
// For informational purposes, we list the receipt(s)
Debug.Log("Receipt is valid. Contents:");
foreach (IPurchaseReceipt productReceipt in result) {
Debug.Log(productReceipt.productID);
Debug.Log(productReceipt.purchaseDate);
Debug.Log(productReceipt.transactionID);
}
} catch (IAPSecurityException) {
Debug.Log("Invalid receipt, not unlocking content");
validPurchase = false;
}
#endif
if (validPurchase) {
// Unlock the appropriate content here.
}
return PurchaseProcessingResult.Complete;
}
Важно проверить не только действительность квитанции, но и информацию, содержащуюся в ней. Обычный метод пользователей, пытающихся получить доступ к контенту без покупки, заключается в предоставлении квитанций от других продуктов или приложений. Эти квитанции являются подлинными и проходят проверку, поэтому вам следует принимать решения на основе идентификаторов продуктов, проанализированных с помощью CrossPlatformValidator.
Подробности о магазине
Разные магазины имеют разные поля в квитанциях о покупках. Для доступа к полям, специфичным для магазина, IPurchaseReceipt
можно преобразовать в два разных подтипа: GooglePlayReceipt
и AppleInAppPurchaseReceipt
.
var result = validator.Validate(e.purchasedProduct.receipt);
Debug.Log("Receipt is valid. Contents:");
foreach (IPurchaseReceipt productReceipt in result) {
Debug.Log(productReceipt.productID);
Debug.Log(productReceipt.purchaseDate);
Debug.Log(productReceipt.transactionID);
GooglePlayReceipt google = productReceipt as GooglePlayReceipt;
if (null != google) {
// This is Google's Order ID.
// Note that it is null when testing in the sandbox
// because Google's sandbox does not provide Order IDs.
Debug.Log(google.transactionID);
Debug.Log(google.purchaseState);
Debug.Log(google.purchaseToken);
}
AppleInAppPurchaseReceipt apple = productReceipt as AppleInAppPurchaseReceipt;
if (null != apple) {
Debug.Log(apple.originalTransactionIdentifier);
Debug.Log(apple.subscriptionExpirationDate);
Debug.Log(apple.cancellationDate);
Debug.Log(apple.quantity);
}
}
Анализ необработанных чеков Apple
Используйте класс AppleValidator
для извлечения подробной информации о чеке Apple. Обратите внимание, что этот класс работает только с iOSмобильной операционной системой Apple. Подробнее
См. в Словарь квитанции приложений, начиная с версии 7.0, а не устаревшие квитанции Apple о транзакциях.
#if UNITY_ANDROID || UNITY_IOS || UNITY_STANDALONE_OSX
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
// Get a reference to IAppleConfiguration during IAP initialization.
var appleConfig = builder.Configure();
var receiptData = System.Convert.FromBase64String(appleConfig.appReceipt);
AppleReceipt receipt = new AppleValidator(AppleTangle.Data()).Validate(receiptData);
Debug.Log(receipt.bundleID);
Debug.Log(receipt.receiptCreationDate);
foreach (AppleInAppPurchaseReceipt productReceipt in receipt.inAppPurchaseReceipts) {
Debug.Log(productReceipt.transactionIdentifier);
Debug.Log(productReceipt.productIdentifier);
}
#endif
Тип AppleReceipt
моделирует формат чеков Apple ASN1. См. от Apple. документацию для объяснения его полей.