0

我只有一个订阅组,它有 3 种产品:

1 week
1 month
1 year
  • 在自动续订订阅中,如果用户降级到另一个方案,新的降级计划将在下一次续订中激活。(完成目前的高等方案后)

  • 对于升级,新升级的计划在取消旧的降级计划后立即激活,并退还之前的降级计划。

  • 对于取消,如果用户取消了一个计划,那么 latest_receipt_info我们会通过这个名称获得当天的日期 cancellation_date。通常这里不会显示。

基于这 3 个条件,我正在处理isSubscriptionActive 升级、降级和取消状态的状态。

在这里,我在(购买产品)和(恢复产品)委托的receiptValidation每笔成功交易后调用该函数。updatedTransactionspaymentQueueRestoreCompletedTransactionsFinished

receiptValidation函数内部获得 JSON 响应后,这就是我检查升级、降级和取消订阅的方式。

  1. latest_receipt_info在一个单独的函数中,我从该 JSON中创建了一个所有可用的对象数组。在这里我也添加cancellation_date属性如果它在latest_receipt_info字典中可用。这是因为此属性仅在用户从苹果支持取消订阅时才会出现。正常响应不包含此内容。

  2. 然后在另一个函数中,我传递这个数组并根据这些检查返回一个布尔值(isSubscriptionActive):

     a) Get the highest `expire_date` from that `latest_receipt_info` object array and find out that object.
     b) Compare the `expire_date` of this object with `current_date` 
     c) If it is greater or equal to `current_date` then set `isSubscriptionActive = true` otherwise `isSubscriptionActive = false`
     d) If it's true then check if the `cancel_date` of that object is `nil` or not.
     e) If its `nil` then `isSubscriptionActive = true` otherwise `isSubscriptionActive = false`
    

代码:
latest_receipt_info对象:

struct LatestReceiptInfo {
    var productId: String?
    var expiresDate: Date? = nil
    var isInIntroOffer_period: Bool?
    var isTrialPeriod: Bool?
    var cancellationDate: Date? = nil
}

func receiptValidation

func receiptValidation(completion: @escaping(_ isPurchaseSchemeActive: Bool, _ error: Error?) -> ()) {
    let receiptFileURL = Bundle.main.appStoreReceiptURL
    guard let receiptData = try? Data(contentsOf: receiptFileURL!) else {
        //This is the First launch app VC pointer call
        completion(false, nil)
        return
    }
    let recieptString = receiptData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
    let jsonDict: [String: AnyObject] = ["receipt-data" : recieptString as AnyObject, "password" : AppSpecificSharedSecret as AnyObject]
    
    do {
        let requestData = try JSONSerialization.data(withJSONObject: jsonDict, options: JSONSerialization.WritingOptions.prettyPrinted)
        let storeURL = URL(string: self.verifyReceiptURL)!
        var storeRequest = URLRequest(url: storeURL)
        storeRequest.httpMethod = "POST"
        storeRequest.httpBody = requestData
        let session = URLSession(configuration: URLSessionConfiguration.default)
        let task = session.dataTask(with: storeRequest, completionHandler: { [weak self] (data, response, error) in
            do {
                if let jsonResponse = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary {
                    //print("json response \(jsonResponse)")
                    //1. Get all latestInfoReceiptObjects in an array
                    //2. Get the object of highest expire_date from latestInfoReceiptObjects array
                    //3. Compare this highest expire_date with current time
                    //4. If it is greater or equal to current time then set isActivePurchase = true otherwise isActivePurchase = false
                    //5. If it's true then check if the cancel_date of that object which has highest expire date is nil. If its nil then isActivePurchase = true otherwise isActivePurchase = false

                    //1. Get all latestInfoReceiptObjects in an array
                    if let latestInfoReceiptObjects = self?.getLatestInfoReceiptObjects(jsonResponse: jsonResponse) {
                        let purchaseStatus = self?.isPurchaseActive(latestReceiptInfoArray: latestInfoReceiptObjects)
                        completion(purchaseStatus!, nil)
                    }
                }
            } catch let parseError {
                completion(false, parseError)
            }
        })
        task.resume()
    } catch let parseError {
        completion(false, parseError)
    }
}

制作一个数组latest_receipt_info

func getLatestInfoReceiptObjects(jsonResponse: NSDictionary) -> [LatestReceiptInfo]? {
    if let receiptInfo: NSArray = jsonResponse["latest_receipt_info"] as? NSArray {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV"
        
        var latestReceiptInfoArray = [LatestReceiptInfo]()

        for receiptInf in receiptInfo {
            let recInf = receiptInf as! NSDictionary

            var productId: String?
            if let product_id = recInf["product_id"] as? String {
                productId = product_id
            } else {
                productId = nil
            }

            var expiresDate: Date? = nil
            if let expires_date = recInf["expires_date"] as? String {
                expiresDate = formatter.date(from: expires_date)!
            } else {
                expiresDate = nil
            }

            var isInIntroOfferPeriod: Bool? = nil
            if let is_in_intro_offer_period = recInf["is_in_intro_offer_period"] as? String {
                if is_in_intro_offer_period.contains("true") {
                    isInIntroOfferPeriod = true
                } else {
                    isInIntroOfferPeriod = false
                }
            } else {
                isInIntroOfferPeriod = nil
            }

            var isTrialPeriod: Bool? = nil
            if let is_trial_period = recInf["is_trial_period"] as? String {
                if is_trial_period.contains("true") {
                    isTrialPeriod = true
                } else {
                    isTrialPeriod = false
                }
            } else {
                isTrialPeriod = nil
            }

            var cancelDate: Date? = nil
            if let cancellation_date = recInf["cancellation_date"] as? String {
                cancelDate = formatter.date(from: cancellation_date)!
            } else {
                cancelDate = nil
            }
            
            latestReceiptInfoArray.append(LatestReceiptInfo(productId: productId, expiresDate: expiresDate, isInIntroOffer_period: isInIntroOfferPeriod, isTrialPeriod: isTrialPeriod, cancellationDate: cancelDate))
        }
        return latestReceiptInfoArray
    } else {
        return nil
    }
}

a), b), c), d), e) 检查:

func isPurchaseActive(latestReceiptInfoArray: [LatestReceiptInfo]) -> Bool {
    var isSubsActive = true
    //2. Get the object of highest expire_date from latestInfoReceiptObjects array
    //3. Compare this highest expire_date with current time
    //4. If it is greater or equal to current time then set isActivePurchase = true otherwise isActivePurchase = false
    //5. If it's true then check if the cancel_date of that object which has highest expire date is nil. If its nil then isActivePurchase = true otherwise isActivePurchase = false

    //2. Get the object of highest expire_date from latestInfoReceiptObjects array
    let latestReceiptInfoForHighestExpireDate = latestReceiptInfoArray
        .filter { $0.expiresDate != nil }
        .max { $0.expiresDate! < $1.expiresDate! }

    isIntroductoryOfferActive = latestReceiptInfoForHighestExpireDate?.isInIntroOffer_period
    //3. Compare this highest expire_date with current time
    let currDate = Date()
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss VV"
    let currentDateString = formatter.string(from: currDate)
    let currentDate = formatter.date(from: currentDateString)

    print("expireDate \(String(describing: latestReceiptInfoForHighestExpireDate?.expiresDate))")
    print("currentDate \(String(describing: currentDate!))")

    //4. If it is greater or equal to current time then set isActivePurchase = true otherwise isActivePurchase = false
    if currentDate!.compare((latestReceiptInfoForHighestExpireDate?.expiresDate)!) == .orderedAscending {
        isSubsActive = true
    } else if currentDate!.compare((latestReceiptInfoForHighestExpireDate?.expiresDate)!) == .orderedDescending {
        isSubsActive = false
    } else if currentDate!.compare((latestReceiptInfoForHighestExpireDate?.expiresDate)!) == .orderedSame {
        isSubsActive = true
    }

    //5. If it's true then check if the cancel_date of that object which has highest expire date is nil. If its nil then isActivePurchase = true otherwise isActivePurchase = false
    if isSubsActive == true {
        if latestReceiptInfoForHighestExpireDate?.cancellationDate == nil {
            isSubsActive = true
        } else {
            isSubsActive = false
        }
    }
    return isSubsActive
}

我知道如果我只使用苹果通知会容易得多,但现在我需要像上面那样做。请分享你的想法。
谢谢!

4

0 回答 0