2011-02-25 19 views
18

Estoy buscando implementar las nuevas suscripciones de Auto Renewable con la compra In App, pero no estoy seguro de cómo o cuándo verificar si el usuario está actualmente suscrito. Según entiendo, cuando el usuario se suscribe inicialmente, la aplicación puede usar la fecha de compra junto con la fecha de suscripción para calcular cuánto durará su suscripción. ¿Qué sucede después de que esta fecha haya pasado? ¿Cómo verificamos si el usuario se ha renovado o cancelado automáticamente?Cómo registrar la compra de la aplicación La suscripción de renovación automática es válida

Si utilizo restoreCompletedTransactions para obtener una transacción y un recibo por cada renovación, se le pedirá al usuario que ingrese su contraseña de iTunes. ¿Significa esto que si han comprado una suscripción de 7 días, tendrán que ingresar su contraseña cada 7 días cuando la aplicación compruebe si la suscripción sigue siendo válida?

+0

Este enlace https://stackoverflow.com/questions/22680059/auto-renewable-subscription-in-ios7/45220204#45220204 podría ayudar tú. –

Respuesta

7

ver esto por docs:

http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/StoreKitGuide/VerifyingStoreReceipts/VerifyingStoreReceipts.html#//apple_ref/doc/uid/TP40008267-CH104-SW1

si usted quiere comprobar en él desde un servidor web, hacer ping a su API y se devuelve el estado de la suscripción de auto-renovable y la información sobre la última pago.

Si está en el dispositivo, probablemente tenga que llamar a restoreCompletedTransactions, que supongo que solicita la contraseña.

No veo ningún otro método. Supongo que desde el dispositivo puede verificar la suscripción poniéndose en contacto con el mismo servicio web utilizado en el lado del servidor. No sé cómo los pros y los contras de eso.

+1

Creo que el trato es - usted tiene que usar un componente de servidor de todos modos, ya que también debe proporcionar el secreto compartido como un parámetro en la llamada al servidor de Apple al hacer la verificación de validez del recibo. No creo que se suponga que debes poner el secreto compartido en el código del cliente de tu aplicación iOS porque entonces el secreto ya no sería muy secreto ... – Jonny

+0

¿Es necesaria la contraseña secreta compartida para validar el recibo tanto en el entorno limitado como en la producción? modo de suscripciones de renovación automática? @Jonny –

+0

Hola, has dicho "haces ping a su API y devuelve el estado de la suscripción de renovación automática e información sobre el último pago" ¿Qué es la API para verificar el estado en el servidor? – Yohan

3

Estoy comenzando una campaña sobre este tema. Aquí está mi observación y campaña:

Al realizar la renovación automática, el App Store llama al paymentQueue y publica una transacción. La transacción se publica con transaction.transactionState==SKPaymentTransactionStateRestored.

El problema es que, lamentablemente, esto se publica solo en un dispositivo. Un segundo dispositivo no recibe la publicación. Por lo tanto, para detectar la renovación automática, o más bien para detectar la falta de una renovación automática y denegarle al dispositivo una suscripción continua, debe hacer un restoreCompletedTransaction o "http publicar un JSON codificado de 64 bits que contenga la última transacción". Si el primero, el usuario necesita dar su contraseña; eso es intrusivo, como has señalado anteriormente. Si esto último, se requiere mucha codificación adicional. Por lo tanto, mi pregunta es ... ¿por qué no tener un StoreKit comando:

(no existe) - [[SKPaymentQueue defaultQueue] restoreAttachedTransactions:(NSArray *)transactions];

Este comando fluiría al igual que un restoreCompletedTransactions pero sólo restauraría las transacciones adjuntos y, lo más importante, no requeriría el inicio de sesión por parte del usuario. Tiene la misma protección de seguridad que el "HTTP post un JSON codificado de 64 bits que contiene la última transacción" y permite que todo el proceso de Compra en la aplicación se realice en StoreKit en lugar de requerir código de publicación web.

Si esto tiene sentido para usted, por favor sugiera cómo conseguir esto para Apple .... gracias.

+0

Lo que describes parece coincidir con lo que he encontrado con la reproducción posterior, así que he decidido implementar un componente de servidor. Aunque es un problema porque requiere una codificación adicional, el componente del servidor es bastante simple y probablemente valga la pena para el seguimiento de auditoría y la verificación de recibos. –

12

Hoy tengo problemas con este problema.

Siga Apple doc aquí, utilicé esta forma para verificar que la suscripción haya expirado o no. Mi idea: el usuario APPLE RESTO respuesta de la API: (tiempo de solicitud + tiempo expirado) para comprobar expiró o no

+ (BOOL)checkInAppPurchaseStatus 
{ 
    // Load the receipt from the app bundle. 
    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL]; 
    NSData *receipt = [NSData dataWithContentsOfURL:receiptURL]; 
    if (receipt) { 
     BOOL sandbox = [[receiptURL lastPathComponent] isEqualToString:@"sandboxReceipt"]; 
     // Create the JSON object that describes the request 
     NSError *error; 
     NSDictionary *requestContents = @{ 
              @"receipt-data": [receipt base64EncodedStringWithOptions:0],@"password":@"SHARE_SECRET_CODE" 
              }; 
     NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents 
                   options:0 
                   error:&error]; 

     if (requestData) { 
      // Create a POST request with the receipt data. 
      NSURL *storeURL = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"]; 
      if (sandbox) { 
       storeURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"]; 
      } 
      NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL]; 
      [storeRequest setHTTPMethod:@"POST"]; 
      [storeRequest setHTTPBody:requestData]; 

      BOOL rs = NO; 
      //Can use sendAsynchronousRequest to request to Apple API, here I use sendSynchronousRequest 
      NSError *error; 
      NSURLResponse *response; 
      NSData *resData = [NSURLConnection sendSynchronousRequest:storeRequest returningResponse:&response error:&error]; 
      if (error) { 
       rs = NO; 
      } 
      else 
      { 
       NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:resData options:0 error:&error]; 
       if (!jsonResponse) { 
        rs = NO; 
       } 
       else 
       { 
        NSLog(@"jsonResponse:%@", jsonResponse); 

        NSDictionary *dictLatestReceiptsInfo = jsonResponse[@"latest_receipt_info"]; 
        long long int expirationDateMs = [[dictLatestReceiptsInfo valueForKeyPath:@"@max.expires_date_ms"] longLongValue]; 
        long long requestDateMs = [jsonResponse[@"receipt"][@"request_date_ms"] longLongValue]; 
        NSLog(@"%lld--%lld", expirationDateMs, requestDateMs); 
        rs = [[jsonResponse objectForKey:@"status"] integerValue] == 0 && (expirationDateMs > requestDateMs); 
       } 
      } 
      return rs; 
     } 
     else 
     { 
      return NO; 
     } 
    } 
    else 
    { 
     return NO; 
    } 
} 

Esperanza esta ayuda.

+1

Gracias. Complementos recomendados: tutorial de NSURLSession para que pueda hacer una comprobación asincrónica https://www.raywenderlich.com/110458/nsurlsession-tutorial-getting-started y también esto sobre cómo probar las suscripciones de Sandbox (hacia el final): https: // savvyapps .com/blog/how-setup-test-auto-renovable-suscripción-ios-app – Philosophistry

4

Es mejor utilizar una solución local antes de realizar cualquier llamada a la API de Apple. Cada vez que se ejecuta la aplicación, es una buena práctica validar el recibo local y si necesita verificar si un usuario tiene la suscripción activa, primero puede recuperar las compras del recibo local y averiguar si la compra todavía está activa durante el día de hoy. .

He implementado una pequeña biblioteca escrita en Swift para simplificar el trabajo con el recibo en la aplicación localmente. Puede buscar fácilmente el objeto que representa el recibo (InAppReceipt) y recuperar una compra activa/todas las compras.

Siéntase libre de usar. Github link

Aquí es un ejemplo de la solución de su problema:

import TPInAppReceipt 

do { 
    let receipt = try InAppReceiptManager.shared.receipt() 

    //retrive active auto renewable subscription for a specific product and date 
    let purchase = receipt.activeAutoRenewableSubscriptionPurchases(ofProductIdentifier: "ProductName", forDate: Date()) 

    //retrive all auto renewable subscription purchases for a specific product 
    let allAutoRenewableSubscriptionPurchases = receipt.purchases(ofProductIdentifier: "productName").filter({ return $0.isRenewableSubscription }) 
} catch { 
    print(error) 
} 
Cuestiones relacionadas