Cómo verificar la disponibilidad de la oferta introductoria en iOS

Si utiliza ofertas introductorias en su solicitud de suscripción (prueba, pago por uso o prepago), antes de mostrar el precio en la pantalla de pago, debe determinar la disponibilidad de la oferta introductoria para el usuario. Si el usuario ya ha elaborado una versión de prueba, debe mostrar el precio completo de la misma.


imagen


Hola a todos, estoy en contacto con Renat de Apphud , un servicio que simplifica el trabajo con suscripciones en aplicaciones iOS. Hoy te diré cómo determinar si un solo usuario tiene derecho a activar una oración introductoria o no.


La oferta introductoria es válida dentro del mismo grupo de suscripción. Esto significa que el usuario puede emitir una suscripción semanal regular sin una prueba, darse de baja y luego emitir una prueba para una suscripción mensual.


La documentación de Apple tiene un diagrama que muestra cuándo una oración introductoria está disponible para el usuario:



Resulta que el usuario puede usar la oración introductoria si:


  • no había usado una frase introductoria antes

Y


  • la suscripción no se ha emitido o ha expirado

Para verificar la disponibilidad de la oración introductoria, debe realizar 3 pasos:


1) Valide la comprobación de App Store y extraiga la matriz de transacciones. Si no hay transacciones, entonces no verificamos nada, hay una oración introductoria disponible. Si hay transacciones, realice los siguientes dos pasos.


2) Verifique si la oración introductoria se utilizó anteriormente


3) Verifique el estado actual de la suscripción


Consideremos estos pasos con más detalle.


1. Validación de la comprobación de App Store


Para validar el cheque, debe enviar una solicitud a Apple, pasando receiptData y sharedSecret . Reemplace el valor sharedSecret con el suyo. Si no conoce su sharedSecret , se describe aquí dónde obtenerlo.


 func isEligibleForIntroductory(callback: @escaping (Bool) -> Void){ guard let receiptUrl = Bundle.main.appStoreReceiptURL else { callback(true) return } #if DEBUG let urlString = "https://sandbox.itunes.apple.com/verifyReceipt" #else let urlString = "https://buy.itunes.apple.com/verifyReceipt" #endif let receiptData = try? Data(contentsOf: receiptUrl).base64EncodedString() let sharedSecret = "YOUR_SHARED_SECRET" let requestData = ["receipt-data" : receiptData ?? "", "password" : sharedSecret, "exclude-old-transactions" : false] as [String : Any] var request = URLRequest(url: URL(string: urlString)!) request.httpMethod = "POST" request.setValue("Application/json", forHTTPHeaderField: "Content-Type") let httpBody = try? JSONSerialization.data(withJSONObject: requestData, options: []) request.httpBody = httpBody URLSession.shared.dataTask(with: request) { (data, response, error) in // continue here }.resume() } 

El ejemplo anterior usa la macro #if DEBUG para determinar el tipo de suscripción: sandbox o production . Si usa otras macros, deberá actualizar el código en este lugar.

2. Compruebe si se ha usado una oración introductoria antes


Después de recibir una respuesta de Apple, la traducimos al Dictionary y obtenemos una variedad de transacciones:


 // paste this code after "continue here" comment guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String : AnyHashable], let receipts_array = json["latest_receipt_info"] as? [[String : AnyHashable]] else { callback(true) return } // continue here 

is_trial_period el conjunto de transacciones y observamos los valores de is_trial_period y is_in_intro_offer_period . Si uno de los valores es true , el usuario ya ha redactado una oración introductoria. Estos valores vienen como una cadena, por lo que, para mayor fiabilidad, intentaremos convertir el valor tanto en Bool como en cadena.


 // paste this code after "continue here" comment var latestExpiresDate = Date(timeIntervalSince1970: 0) let formatter = DateFormatter() for receipt in receipts_array { let used_trial : Bool = receipt["is_trial_period"] as? Bool ?? false || (receipt["is_trial_period"] as? NSString)?.boolValue ?? false let used_intro : Bool = receipt["is_in_intro_offer_period"] as? Bool ?? false || (receipt["is_in_intro_offer_period"] as? NSString)?.boolValue ?? false if used_trial || used_intro { callback(false) return } // continue here 

3. Verificación del estado actual de la suscripción


Para conocer el estado actual de la suscripción, necesitamos encontrar la última fecha de expires_date y compararla con la fecha actual. Si la suscripción no ha expirado, la oferta introductoria no está disponible:


 // paste this code after "continue here" comment formatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV" if let expiresDateString = receipt["expires_date"] as? String, let date = formatter.date(from: expiresDateString) { if date > latestExpiresDate { latestExpiresDate = date } } } if latestExpiresDate > Date() { callback(false) } else { callback(true) } 

Puede encontrar un enlace al código completo del método al final del artículo, sin embargo, hay mucho "Pero" en este método.


Trampas


  • En este ejemplo, solo miramos el caso de un grupo de suscripción. Si utiliza más de un grupo de suscripción en la aplicación, debe pasar el identificador del grupo de suscripción a este método y verificarlo por el valor de subscription_group_identifier en la receipt .


  • En este ejemplo, el caso de los reembolsos de suscripción no se tiene en cuenta. Para hacer esto, verifique la presencia del campo cancellation_date :


     if receipt["cancellation_date"] != nil{ // if user made a refund, no need to check for eligibility callback(false) return } 

  • Y aquí no se tiene en cuenta el período de gracia (Período de gracia de facturación). Si el usuario se encuentra en el período de gracia en el momento en que se valida el cheque, pending_renewal_info tendrá el campo grace_period_expires_date . En este caso, usted como desarrollador debe proporcionar una funcionalidad premium al usuario sin mostrar una pantalla de pago. Y en consecuencia, no tiene sentido verificar la disponibilidad de la oración introductoria.


  • Hay un problema al verificar la fecha de vencimiento. La hora del sistema en el dispositivo iOS se puede desenroscar y luego nuestro código dará un resultado incorrecto: la suscripción se considerará activa.


  • Apple no recomienda la validación de un control en el dispositivo en sí. Hablaron sobre esto varias veces en WWDC (desde las 5:50) y esto se indica en la documentación . Esto no es seguro porque un atacante puede interceptar datos mediante un ataque de hombre en el medio. Apple recomienda usar su servidor para validar las comprobaciones.



Verificar la disponibilidad de una oferta promocional


La condición para la disponibilidad de la oferta promocional es más simple: lo principal es que el usuario tenga una suscripción activa o caducada. Para hacer esto, busque la presencia de pending_renewal_info para su grupo de suscripción.


Cómo se implementa en Apphud SDK


Es suficiente llamar a un método, pasando su product , que le devolverá el resultado:


 Apphud.checkEligibilityForIntroductoryOffer(product: myProduct) { result in if result { // User is eligible to purchase introductory offer } } 

Y de manera similar para la oferta promocional:


 Apphud.checkEligibilityForPromotionalOffer(product: myProduct) { result in if result { // User is eligible to purchase promotional offer } } 

También hay métodos para verificar la disponibilidad de varios productos a la vez en una sola llamada:


 func checkEligibilitiesForIntroductoryOffers(products: [SKProduct], callback: ApphudEligibilityCallback) func checkEligibilitiesForPromotionalOffers(products: [SKProduct], callback: ApphudEligibilityCallback) 

Conclusión


El código completo del método se puede descargar aquí .


En Apphud ya hemos implementado un control sobre la disponibilidad de ofertas introductorias y promocionales en un conveniente SDK de código abierto. Apphud también lo ayuda a rastrear el estado de la suscripción, analizar métricas clave, ofrecer automáticamente descuentos a usuarios no suscritos y mucho más. Si experimenta dolor mientras trabaja con suscripciones, pruebe nuestra solución de forma gratuita.

Source: https://habr.com/ru/post/471492/


All Articles