如何在iOS中检查介绍性产品的可用性

如果在订阅应用程序中使用介绍性优惠(试用,使用时付款或预付款),那么在付款屏幕上显示价格之前,您需要确定介绍性优惠对用户的可用性。 如果用户已经草拟了试用版,那么您必须显示其全价。


图片


大家好,我与Apphud的 Renat 联系 ,该服务简化了iOS应用程序中的订阅工作。 今天,我将告诉您如何确定单个用户是否有权激活介绍性句子。


促销优惠在同一订阅组中有效。 这意味着用户可以在不进行试用的情况下发布常规的每周订阅,可以取消订阅,之后再发布对每月订阅的试用。


Apple文档中有一个图表,显示用户何时可以使用介绍性句子:



事实证明,在以下情况下,用户可以使用介绍性句子:


  • 他以前没有用过开场白


  • 订阅尚未发出或已过期

要检查介绍性句子的可用性,您需要执行3个步骤:


1)验证App Store-检查并拉出交易数组。 如果没有交易,那么我们不检查任何内容,可以使用介绍性句子。 如果存在事务,请执行以下两个步骤。


2)检查介绍性句子是否曾经被使用过


3)检查当前订阅状态


让我们更详细地考虑这些步骤。


1.验证App Store支票


要验证支票,您需要向Apple发送一个请求,并传递receiptDatasharedSecret 。 用您自己的值替换sharedSecret值。 如果您不知道sharedSecret ,则在此处说明如何获取它。


 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() } 

上面的示例使用#if DEBUG宏来确定订阅类型: sandboxproduction 。 如果使用其他宏,则需要在此位置更新代码。

2.检查之前是否使用过介绍性句子


收到Apple的回应后,我们将其翻译成Dictionary并获得了一系列交易:


 // 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_periodis_in_intro_offer_period的值。 如果值之一为true ,则用户已经草拟了一个介绍性句子。 这些值以字符串形式出现,因此出于可靠性考虑,我们将尝试同时转换Bool和string中的值。


 // 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.检查订阅的当前状态


要了解订阅的当前状态,我们需要找到最新的expires_date并与当前日期进行比较。 如果订阅尚未过期,则该促销优惠不可用:


 // 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) } 

您可以在文章末尾找到该方法的完整代码的链接,但是,此方法中有很多“ But”。


陷阱


  • 在此示例中,我们仅查看一个订阅组的情况。 如果在一个应用程序中使用多个订阅组,则必须将订阅组标识符传递给此方法,并通过subscription_group_identifier中的subscription_group_identifier的值进行验证。


  • 在此示例中,不考虑订阅退款的情况。 为此,请检查cancellation_date字段是否存在:


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

  • 在此不考虑宽限期(计费宽限期)。 如果用户在检查通过时处于宽限期,则pending_renewal_info将具有grace_period_expires_date字段。 在这种情况下,您作为开发人员必须在不显示付款屏幕的情况下向用户提供高级功能。 因此,检查介绍性句子的可用性是没有意义的。


  • 检查到期日期存在问题。 可以拧松iOS设备上的系统时间,然后我们的代码将给出错误的结果:订阅将被视为活动状态。


  • 苹果不建议对设备本身进行检查验证。 他们在WWDC (从5:50开始)多次谈论了这一点,并且在文档中对此进行了说明 。 这是不安全的,因为攻击者可以使用中间人攻击来拦截数据。 Apple建议使用您的服务器来验证检查。



查看促销优惠的可用性


提供促销优惠的条件比较简单-主要是用户具有有效或过期的订阅。 为此,请为您的订阅组查找pending_renewal_info


如何在Apphud SDK中实现


调用一个方法,将您的product传递给其中,这将足以将结果返回给您:


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

以及类似的促销优惠:


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

还有一种可以一次检查多个产品可用性的方法:


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

结论


完整的方法代码可在此处下载。


Apphud的我们已经在便利的开源SDK中对导入和促销优惠的可用性进行了检查。 Apphud还可以帮助您跟踪订阅状态,分析关键指标,自动为未订阅的用户提供折扣等等。 如果您在使用订阅时遇到麻烦,请免费试用我们的解决方案

Source: https://habr.com/ru/post/zh-CN471492/


All Articles