iOS in App purchase - auto renewal subscription

2.2k Views Asked by At

dears ,

i have a question regarding iOS in app purchase , specific for "auto renewal Subscription" i develops app contains Free features & Paid features : the paid features based on "Monthly subscription & user have a free 1 week trial"

and all process is fine : we will fetch products & user can buy & we will validate receipt (I know recipe contains flags for “is_trial..” & “Purchase_date” …)…..

kindly note : I call “validate recipe” just after buy or after restore

but i have a the below problems : how can i know the below :

1- if user open app for second time, how i know if user still in trial Period ?

2- if user open app after 1 month : how I can know if subscription expired or not … (so if subscription expired I will the buy call again …)

, is the solution I will call “validate recipe” every time when user open app , so I can know if user in trail of in paid or after paid period (expired)…

Or I will save purchase date locally (ex : user default) & when user open app I will compare the current date with purchase date , really I don’t see this a true answer because user may be change the device date ….

Please advice …

the code belwo :

so now when open app : i request product :

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

when receive products :

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


            list.append(product)
        }
}

Now when user press on by button :

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

        }
    }

the the method bellow will call

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

& i will Validate the receipt :

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

There are 1 best solutions below

2
On

Highly recommended you store the user premium state and do receipt validation server-side. This way YOU keep meta-data about the user, their subscription expiration, free trial status etc. on your server and just refresh THAT on startup. You can then setup intelligent polling to Apple's servers for receipt validation/expiration checks (should also be done server-side) based on the users start/end dates. This will maintain their premium or non-premium state and allow you trigger the necessary client UI.