Покупка iOS в приложении - автоматическое продление подписки

дорогие ,

У меня есть вопрос, касающийся покупки приложения для iOS, в частности для «Подписки с автоматическим продлением». Я разрабатываю приложение, которое содержит бесплатные и платные функции: платные функции основаны на «Ежемесячной подписке и пользователю предоставляется бесплатная пробная версия на 1 неделю»

и весь процесс в порядке: мы получим продукты, и пользователь может их купить, и мы проверим квитанцию ​​(я знаю, что рецепт содержит флаги для «is_trial ..» и «Purchase_date»…)… ..

обратите внимание: я называю «проверить рецепт» сразу после покупки или после восстановления

но у меня есть следующие проблемы: как я могу узнать следующее:

1- если пользователь откроет приложение во второй раз, как я узнаю, что пользователь все еще находится в пробном периоде?

2- если пользователь откроет приложение через 1 месяц: как я могу узнать, истекла ли подписка или нет… (так что, если срок подписки истек, я снова позвоню на покупку…)

, это решение, которое я буду называть «проверять рецепт» каждый раз, когда пользователь открывает приложение, чтобы я мог знать, находится ли пользователь в оплаченном или после оплаченного периода (истекший)…

Или я сохраню дату покупки локально (например, пользователь по умолчанию), и когда пользователь откроет приложение, я сравню текущую дату с датой покупки, на самом деле я не вижу это верного ответа, потому что пользователь может изменить дату устройства….

Пожалуйста посоветуй …

код belwo:

Итак, теперь, когда открываю приложение: я запрашиваю продукт:

SKPaymentQueue.default().add(self)
        if(SKPaymentQueue.canMakePayments()) {
            print("IAP is enabled, loading")


            let productID: NSSet = NSSet(objects: "test.test1.test2.11")



            let request: SKProductsRequest = SKProductsRequest(productIdentifiers: productID as! Set<String>)
            request.delegate = self
            request.start()
        } else {
            print("please enable IAPS")
        }

при получении продукции:

  func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
        print("product request")
        let myProduct = response.products
        for product in myProduct {


            list.append(product)
        }
}

Теперь, когда пользователь нажимает кнопку:

for product in self.list {
        let prodID = product.productIdentifier
        if(prodID == "test.test1.test2.11") {
            self.p = product
            self.buyProduct()

        }
    }

метод ниже вызовет

 func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        print("add payment")

        for transaction: AnyObject in transactions {
            let trans = transaction as! SKPaymentTransaction

            switch trans.transactionState {
            case .purchased:
                receiptValidation()
                queue.finishTransaction(trans)

                break
            case .failed:
                print("buy error")
                queue.finishTransaction(trans)
                break
            default:
                print("Default")
                break
            }
        }
    }

& я проверю квитанцию:

func receiptValidation() {
        if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
            FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {

            do {
                let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)

                let receiptString = receiptData.base64EncodedString(options: [])
                let dict = ["receipt-data" : receiptString, "password" : "xxxxxxxxxxx"] as [String : Any]

                do {
                    let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)

                    if let sandboxURL = Foundation.URL(string:"https://sandbox.itunes.apple.com/verifyReceipt") {
                        var request = URLRequest(url: sandboxURL)
                        request.httpMethod = "POST"
                        request.httpBody = jsonData
                        let session = URLSession(configuration: URLSessionConfiguration.default)
                        let task = session.dataTask(with: request) { data, response, error in
                            if let receivedData = data,
                                let httpResponse = response as? HTTPURLResponse,
                                error == nil,
                                httpResponse.statusCode == 200 {
                                do {
                                    if let jsonResponse = try JSONSerialization.jsonObject(with: receivedData, options: JSONSerialization.ReadingOptions.mutableContainers) as? Dictionary<String, AnyObject> {

        } else { print("Failed to cast serialized JSON to Dictionary<String, AnyObject>") }
                                }
                                catch { print("Couldn't serialize JSON with error: " + error.localizedDescription) }
                            }
                        }
                        task.resume()
                    } else { print("Couldn't convert string into URL. Check for special characters.") }
                }
                catch { print("Couldn't create JSON with error: " + error.localizedDescription) }
            }
            catch { print("Couldn't read receipt data with error: " + error.localizedDescription) }
        }
    }

person Ahmad    schedule 18.12.2017    source источник


Ответы (1)


Настоятельно рекомендуется сохранять статус премиум-класса пользователя и выполнять проверку квитанций на стороне сервера. Таким образом, ВЫ храните метаданные о пользователе, истечении срока его подписки, статусе бесплатной пробной версии и т. Д. На своем сервере и просто обновляете ЭТО при запуске. Затем вы можете настроить интеллектуальный опрос серверов Apple для проверки подтверждения / истечения срока действия (также должны выполняться на стороне сервера) на основе дат начала / окончания пользователей. Это сохранит их состояние премиум или не премиум и позволит вам запускать необходимый клиентский интерфейс.

person Andrew Geisthardt    schedule 18.12.2017
comment
чтобы я сохранял дату покупки локально, а затем сравнивал ее с текущей датой на стороне сервера? - person Ahmad; 20.12.2017
comment
Выполните все проверки квитанций на стороне сервера в соответствии с документация:. Вы должны отправлять клиентские квитанции на свой сервер, чтобы безопасно реализовать проверку квитанций. Вы можете сохранить необходимые даты покупки / пробной версии / подписки из проверенной квитанции в своей (-ых) таблице (-ах) для удобства или загружать и проверять квитанцию ​​клиента при каждом запуске, если необходимо. Не храните данные о покупках локально. Используйте только квитанцию ​​от клиента. - person Andrew Geisthardt; 24.12.2017