IAPs actually validating the receipt (Swift)

后端 未结 3 2040
时光取名叫无心
时光取名叫无心 2021-02-06 17:34

I have been trying to implement receipt validation in my spritekit game. I have been following various tutorial and basically ended up with this code

enum Reques         


        
3条回答
  •  死守一世寂寞
    2021-02-06 17:39

    Here is a solution using Swift version 2.1 following the Apple guide.

    Apple also recommends the following:

    When validating receipts on your server, your server needs to be able to handle a production-signed app getting its receipts from Apple’s test environment. The recommended approach is for your production server to always validate receipts against the production App Store first. If validation fails with the error code “Sandbox receipt used in production”, validate against the test environment instead.

    validateReceipt(NSBundle.mainBundle().appStoreReceiptURL) { (success: Bool) -> Void in
                print(success)
            }
    
    private func receiptData(appStoreReceiptURL : NSURL?) -> NSData? {
    
        guard let receiptURL = appStoreReceiptURL,
            receipt = NSData(contentsOfURL: receiptURL) else {
                return nil
        }
    
        do {
            let receiptData = receipt.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
            let requestContents = ["receipt-data" : receiptData]
            let requestData = try NSJSONSerialization.dataWithJSONObject(requestContents, options: [])
            return requestData
        }
        catch let error as NSError {
            print(error)
        }
    
        return nil
    }
    
    private func validateReceiptInternal(appStoreReceiptURL : NSURL?, isProd: Bool , onCompletion: (Int?) -> Void) {
    
        let serverURL = isProd ? "https://buy.itunes.apple.com/verifyReceipt" : "https://sandbox.itunes.apple.com/verifyReceipt"
    
        guard let receiptData = receiptData(appStoreReceiptURL),
            url = NSURL(string: serverURL)  else {
            onCompletion(nil)
            return
        }
    
        let request = NSMutableURLRequest(URL: url)
        request.HTTPMethod = "POST"
        request.HTTPBody = receiptData
    
        let task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
    
            guard let data = data where error == nil else {
                onCompletion(nil)
                return
            }
    
            do {
                let json = try NSJSONSerialization.JSONObjectWithData(data, options:[])
                print(json)
                guard let statusCode = json["status"] as? Int else {
                    onCompletion(nil)
                    return
                }
                onCompletion(statusCode)
            }
            catch let error as NSError {
                print(error)
                onCompletion(nil)
            }
        })
        task.resume()
    }
    
    public func validateReceipt(appStoreReceiptURL : NSURL?, onCompletion: (Bool) -> Void) {
    
        validateReceiptInternal(appStoreReceiptURL, isProd: true) { (statusCode: Int?) -> Void in
            guard let status = statusCode else {
                onCompletion(false)
                return
            }
    
            // This receipt is from the test environment, but it was sent to the production environment for verification.
            if status == 21007 {
                self.validateReceiptInternal(appStoreReceiptURL, isProd: false) { (statusCode: Int?) -> Void in
                    guard let statusValue = statusCode else {
                        onCompletion(false)
                        return
                    }
    
                    // 0 if the receipt is valid
                    if statusValue == 0 {
                        onCompletion(true)
                    } else {
                        onCompletion(false)
                    }
    
                }
    
            // 0 if the receipt is valid
            } else if status == 0 {
                onCompletion(true)
            } else {
                onCompletion(false)
            }
        }
    }
    

提交回复
热议问题