La validación de recibo le ayuda a usted prevenir a los usuarios que accedan contenido que no hayan comprado.
Es mejor práctica validar el recibo en el punto donde se distribuye el contenido de su aplicación.
Si el contenido que el usuario está comprando ya existe en el dispositivo, la aplicación simplemente tiene que tomar una decisión sobre si desbloquearlo.
Unity IAP proporciona herramientas para ayudarle a ocultar contenido y validar y parse recibos a través de las tiendas de Google Play y Apple.
La validación de recibo es realizada utilizando unas claves de cifrado; para su aplicación, esta es una llave pública cifrada de Google Play, y/o el certificado raíz de Apple.
Si un usuario puede remplazar estas, entonces pueden ganarle a sus revisiones de validación de recibo, por lo que es importante hacerlas difícil para el usuario para que fácilmente encuentre y modifique estás llaves.
Unity IAP proporciona una herramienta que le pueda a ayudar a ofuscar sus llaves de cifrado dentro de su Aplicación. Esto confunde o desordena las llaves para que sea más difícil para un usuario accederlas. En la barra del menú de Unity, ir a Window_ > Unity IAP > IAP Receipt Validation Obfuscator.
Esta ventana codifica tanto el certificado raíz de Apple (que se incluye con Unity IAP) como la llave pública de Google Play (desde la página Google Play Developer Console’s Services & APIs de la aplicación) en dos archivos C# files: AppleTangle y GooglePlayTangle. Estos se agregan a su proyecto para su uso en la siguiente sección.
Tenga en cuenta que no tiene que proporcionar una llave pública de Google Play si solo tiene como objetivo las tiendas de Apple y viceversa.
Utilice la clase CrossPlatformValidator
para la validación a través de las tiendas de Google Play y Apple.
Debe proporcionar esta clase con su llave pública de Google Play o con el certificado raíz de Apple o ambos si desea validar en ambas plataformas.
El CrossPlatformValidator
realiza dos comprobaciones:
Tenga en cuenta que el validador sólo valida los recibos generados en las plataformas Google Play y Apple. Los recibos generados en cualquier otra plataforma, incluidas las falsas generadas en el Editor, lanzan una IAPSecurityException.
Si intenta validar un recibo para una plataforma que no ha proporcionado una llave secreta, se lanzará 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;
}
Es importante que compruebe no sólo que el recibo es válido, sino también qué información contiene. Una técnica común de los usuarios que intentan acceder a contenido sin comprar es suministrar recibos de otros productos o aplicaciones. Estos recibos son genuinos y pasan la validación, por lo que debe tomar decisiones basadas en los ID de producto analizados por CrossPlatformValidator.
Las diferentes tiendas tienen diferentes campos en sus recibos de compra. Para acceder a los campos específicos de la tienda, IPurchaseReceipt
puede reducirse a dos subtipos diferentes:` GooglePlayReceipt
y 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);
}
}
Utilice la clase AppleValidator
para extraer información detallada sobre un recibo de Apple. Tenga en cuenta que esta clase sólo funciona con los recibos de la aplicación de iOS desde la versión 7.0 en adelante, no los recibos de transacciones obsoletos de 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<IAppleConfiguration>();
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
El tipo AppleReceipt
modela el formato de recibo de Apple ASN1 receipt format. Mire la documentación de Apple para una explicación de sus campos.