Transacciones y comprobación en Xamarin.iOS

Restaurar transacciones pasadas

Si la aplicación admite tipos de producto que se pueden restaurar, debe incluir algunos elementos de interfaz de usuario para permitir a los usuarios restaurar esas compras. Esta funcionalidad permite a un cliente agregar el producto a dispositivos adicionales o restaurar el producto en el mismo dispositivo después de borrarse limpio o quitar y volver a instalar la aplicación. Se pueden restaurar los siguientes tipos de producto:

  • Productos no consumibles
  • Suscripciones renovables automáticas
  • Suscripciones gratuitas

El proceso de restauración debe actualizar los registros que mantiene en el dispositivo para satisfacer los productos. El cliente puede optar por restaurar en cualquier momento en cualquiera de sus dispositivos. El proceso de restauración vuelve a enviar todas las transacciones anteriores para ese usuario; Después, el código de la aplicación debe determinar qué acción realizar con esa información (por ejemplo, comprobar si ya hay un registro de esa compra en el dispositivo y, si no es así, crear un registro de la compra y habilitar el producto para el usuario).

Implementación de la restauración

El botón Restaurar de la interfaz de usuario llama al método siguiente, que desencadena RestoreCompletedTransactions en .SKPaymentQueue

public void Restore()
{
   // theObserver will be notified of when the restored transactions start arriving <- AppStore
   SKPaymentQueue.DefaultQueue.RestoreCompletedTransactions();​​​
}

StoreKit enviará la solicitud de restauración a los servidores de Apple de forma asincrónica.

CustomPaymentObserver Dado que está registrado como observador de transacciones, recibirá mensajes cuando respondan los servidores de Apple. La respuesta contendrá todas las transacciones que este usuario haya realizado en esta aplicación (en todos sus dispositivos). El código recorre en bucle cada transacción, detecta el estado Restaurado y llama al UpdatedTransactions método para procesarlo como se muestra a continuación:

// called when the transaction status is updated
public override void UpdatedTransactions (SKPaymentQueue queue, SKPaymentTransaction[] transactions)
{
   foreach (SKPaymentTransaction transaction in transactions)
   {
       switch (transaction.TransactionState)
       {
       case SKPaymentTransactionState.Purchased:
          theManager.CompleteTransaction(transaction);
           break;
       case SKPaymentTransactionState.Failed:
          theManager.FailedTransaction(transaction);
           break;
       case SKPaymentTransactionState.Restored:
           theManager.RestoreTransaction(transaction);
           break;
​default:
           break;
       }
   }
}

Si no hay ningún producto restaurable para el usuario, UpdatedTransactions no se llama a .

El código más sencillo posible para restaurar una transacción determinada en el ejemplo realiza las mismas acciones que cuando tiene lugar una compra, excepto que la OriginalTransaction propiedad se usa para tener acceso al id. de producto:

public void RestoreTransaction (SKPaymentTransaction transaction)
{
   // Restored Transactions always have an 'original transaction' attached
   var productId = transaction.OriginalTransaction.Payment.ProductIdentifier;
   // Register the purchase, so it is remembered for next time
   PhotoFilterManager.Purchase(productId); // it's as though it was purchased again
   FinishTransaction(transaction, true);
}

Una implementación más sofisticada puede comprobar otras transaction.OriginalTransaction propiedades, como la fecha original y el número de recibo. Esta información será útil para algunos tipos de productos (como suscripciones).

Finalización de la restauración

CustomPaymentObserver Tiene dos métodos adicionales a los que llamará StoreKit cuando el proceso de restauración se haya completado (ya sea correctamente o con un error), que se muestra a continuación:

public override void PaymentQueueRestoreCompletedTransactionsFinished (SKPaymentQueue queue)
{
   Console.WriteLine(" ** RESTORE Finished ");
}
public override void RestoreCompletedTransactionsFailedWithError (SKPaymentQueue queue, NSError error)
{
   Console.WriteLine(" ** RESTORE FailedWithError " + error.LocalizedDescription);
}

En el ejemplo, estos métodos no hacen nada, pero una aplicación real puede optar por implementar un mensaje al usuario o a alguna otra funcionalidad.

Protección de compras

En los dos ejemplos de este documento se usa NSUserDefaults para realizar un seguimiento de las compras:

Consumibles : el "saldo" de las compras de crédito es un valor entero simple NSUserDefaults que se incrementa con cada compra.

No consumibles : cada compra de filtro de fotos se almacena como un par clave-valor en NSUserDefaults.

El uso NSUserDefaults de mantiene sencillo el código de ejemplo, pero no ofrece una solución muy segura, ya que puede ser posible que los usuarios con mentalidad técnica actualicen la configuración (pasando el mecanismo de pago).

Nota: Las aplicaciones reales deben adoptar un mecanismo seguro para almacenar contenido comprado que no está sujeto a alteraciones del usuario. Esto puede implicar cifrado u otras técnicas, incluida la autenticación remota del servidor.

El mecanismo también debe diseñarse para aprovechar las características integradas de copia de seguridad y recuperación de iOS, iTunes e iCloud. Esto garantizará que después de que un usuario restaure una copia de seguridad de sus compras anteriores estará disponible inmediatamente.

Consulte la Guía de codificación segura de Apple para obtener instrucciones más específicas de iOS.

Comprobación de recibos y productos de Server-Delivered

Los ejemplos de este documento hasta ahora constan únicamente de la aplicación que se comunica directamente con los servidores de App Store para realizar transacciones de compra, que desbloquean características o funcionalidades ya codificadas en la aplicación.

Apple proporciona un nivel adicional de seguridad de compra al permitir que otro servidor compruebe de forma independiente los recibos de compra, lo que puede ser útil para validar una solicitud antes de entregar contenido digital como parte de una compra (como un libro digital o una revista).

Productos integrados : al igual que los ejemplos de este documento, el producto que se compra existe como funcionalidad enviada con la aplicación. Una compra desde la aplicación permite al usuario acceder a la funcionalidad. Los identificadores de producto están codificados de forma dura.

Productos entregados por el servidor: el producto consta de contenido descargable que se almacena en un servidor remoto hasta que una transacción correcta hace que el contenido se descargue. Algunos ejemplos pueden incluir libros o problemas de revistas. Normalmente, los identificadores de producto se obtienen de un servidor externo (donde también se hospeda el contenido del producto). Las aplicaciones deben implementar una forma sólida de grabación cuando se haya completado una transacción, de modo que si se produce un error en la descarga de contenido, se puede volver a intentar sin confundir al usuario.

productos de Server-Delivered

El contenido de algún producto, como libros y revistas (o incluso un nivel de juego) debe descargarse desde un servidor remoto durante el proceso de compra. Esto significa que se requiere un servidor adicional para almacenar y entregar el contenido del producto después de comprarlo.

Obtener precios para productos de Server-Delivered

Dado que los productos se entregan de forma remota, también es posible agregar más productos a lo largo del tiempo (sin actualizar el código de la aplicación), como agregar más libros o nuevos problemas de una revista. Para que la aplicación pueda detectar estos productos de noticias y mostrarlos al usuario, el servidor adicional debe almacenar y entregar esta información.

Obtener precios para productos de Server-Delivered

  1. La información del producto debe almacenarse en varios lugares: en el servidor y en iTunes Connect. Además, cada producto tendrá archivos de contenido asociados. Estos archivos se entregarán después de una compra correcta.

  2. Cuando el usuario desea comprar un producto, la aplicación debe determinar qué productos están disponibles. Esta información se puede almacenar en caché, pero debe entregarse desde un servidor remoto donde se almacena la lista maestra de productos.

  3. El servidor devuelve una lista de identificadores de producto para que la aplicación analice.

  4. A continuación, la aplicación determina cuáles de estos identificadores de producto se van a enviar a StoreKit para recuperar precios y descripciones.

  5. StoreKit envía la lista de identificadores de producto a los servidores de Apple.

  6. Los servidores de iTunes responden con información de producto válida (descripción y precio actual).

  7. La aplicación SKProductsRequestDelegate se pasa la información del producto para mostrar al usuario.

Comprar productos Server-Delivered

Dado que el servidor remoto requiere alguna forma de validar que una solicitud de contenido es válida (es decir, se ha pagado), la información de recepción se pasa para la autenticación. El servidor remoto reenvía esos datos a iTunes para su comprobación y, si se ejecuta correctamente, incluye el contenido del producto en la respuesta a la aplicación.

Comprar productos Server-Delivered

  1. La aplicación agrega un SKPayment objeto a la cola. Si es necesario, se le pedirá al usuario su id. de Apple y se le pedirá que confirme el pago.

  2. StoreKit envía la solicitud al servidor para su procesamiento.

  3. Una vez completada la transacción, el servidor responde con un recibo de transacción.

  4. La SKPaymentTransactionObserver subclase recibe la recepción y la procesa. Dado que el producto debe descargarse desde un servidor, la aplicación inicia una solicitud de red al servidor remoto.

  5. La solicitud de descarga va acompañada de los datos de recepción para que el servidor remoto pueda comprobar que está autorizado para acceder al contenido. El cliente de red de la aplicación espera una respuesta a esta solicitud.

  6. Cuando el servidor recibe una solicitud de contenido, analiza los datos de recepción y envía una solicitud directamente a los servidores de iTunes para comprobar que la recepción es para una transacción válida. El servidor debe usar alguna lógica para determinar si se debe enviar la solicitud a la dirección URL del espacio aislado o de producción. Apple sugiere usar siempre la dirección URL de producción y cambiar al espacio aislado si el estado de recepción 21007 (recibo de espacio aislado enviado al servidor de producción). Consulte la Guía de programación de validación de recibos de Apple para obtener más detalles.

  7. iTunes comprobará el recibo y devolverá un estado de cero si es válido.

  8. El servidor espera la respuesta de iTunes. Si recibe una respuesta válida, el código debe buscar el archivo de contenido del producto asociado que se va a incluir en la respuesta a la aplicación.

  9. La aplicación recibe y analiza la respuesta, guardando el contenido del producto en el sistema de archivos del dispositivo.

  10. La aplicación habilita el producto y, a continuación, llama a StoreKit.FinishTransaction Después, la aplicación puede mostrar opcionalmente el contenido comprado (por ejemplo, mostrar la primera página de un libro o una revista comprados).

Una implementación alternativa para archivos de contenido de productos muy grandes podría implicar simplemente almacenar el recibo de transacción en el paso 9 para que la transacción se pueda completar rápidamente y proporcionar una interfaz de usuario para que el usuario descargue el contenido real del producto en algún momento posterior. La solicitud de descarga posterior puede volver a enviar el recibo almacenado para acceder al archivo de contenido del producto necesario.

Escribir Server-Side código de verificación de recibo

La validación de una recepción en el código del lado servidor se puede realizar con una simple solicitud/respuesta HTTP POST que abarca los pasos n.º 5 a 8 del diagrama de flujo de trabajo.

Extraiga la SKPaymentTansaction.TransactionReceipt propiedad en la aplicación. Estos son los datos que se deben enviar a iTunes para su verificación (paso 5).

Codificación base64 de los datos de recibo de transacción (ya sea en el paso 5 o #6).

Cree una carga JSON sencilla como esta:

{
   "receipt-data" : "(base-64 encoded receipt here)"
}

HTTP POST json en https://buy.itunes.apple.com/verifyReceipt para producción o https://sandbox.itunes.apple.com/verifyReceipt para pruebas.

La respuesta JSON contendrá las siguientes claves:

{
   "status" : 0,
   "receipt" : { (receipt repeated here) }
}

Un estado de cero indica un recibo válido. El servidor puede continuar para cumplir el contenido del producto comprado. La clave de recibo contiene un diccionario JSON con las mismas propiedades que el SKPaymentTransaction objeto recibido por la aplicación, por lo que el código del servidor puede consultar este diccionario para recuperar información como el product_id y la cantidad de la compra.

Consulte la documentación de la Guía de programación de validación de recibos de Apple para obtener información adicional.