我正在开发Swift 3中的iOS应用程序并尝试按照本教程实现收据验证: savvyapps/blog/how-setup-test-auto-renewable-subscription-ios-app 。但是,该教程似乎是使用早期版本的Swift编写的,因此我不得不进行一些更改。这是我的receiptValidation()函数:
I am developing an iOS app in Swift 3 and trying to implement receipt validation following this tutorial: savvyapps/blog/how-setup-test-auto-renewable-subscription-ios-app. However, the tutorial seems to have been written using an earlier version of Swift, so I had to make several changes. Here is my receiptValidation() function:
func receiptValidation() { let receiptPath = Bundle.main.appStoreReceiptURL?.path if FileManager.default.fileExists(atPath: receiptPath!){ var receiptData:NSData? do{ receiptData = try NSData(contentsOf: Bundle.main.appStoreReceiptURL!, options: NSData.ReadingOptions.alwaysMapped) } catch{ print("ERROR: " + error.localizedDescription) } let receiptString = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)) let postString = "receipt-data=" + receiptString! + "&password=" + SUBSCRIPTION_SECRET let storeURL = NSURL(string:"sandbox.itunes.apple/verifyReceipt")! let storeRequest = NSMutableURLRequest(url: storeURL as URL) storeRequest.httpMethod = "POST" storeRequest.httpBody = postString.data(using: .utf8) let session = URLSession(configuration:URLSessionConfiguration.default) let task = session.dataTask(with: storeRequest as URLRequest) { data, response, error in do{ let jsonResponse:NSDictionary = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary let expirationDate:NSDate = self.expirationDateFromResponse(jsonResponse: jsonResponse)! self.updateIAPExpirationDate(date: expirationDate) } catch{ print("ERROR: " + error.localizedDescription) } } task.resume() } }问题出现了当我尝试调用expirationDateFromResponse()方法时。事实证明,传递给此方法的jsonResponse仅包含: status = 21002; 。我查了一下,这意味着收据数据属性中的数据格式错误或丢失。但是,我正在测试的设备有一个活动的沙盒订阅产品,除了这个问题,订阅似乎正常工作。我还需要做些什么来确保receiveData值被正确读取和编码,或者其他一些可能导致此问题的问题?
The problem shows up when I try to call the expirationDateFromResponse() method. It turns out that the jsonResponse that gets passed to this method only contains: status = 21002;. I looked this up and it means "The data in the receipt-data property was malformed or missing." However, the device I'm testing on has an active sandbox subscription for the product, and the subscription seems to work correctly aside from this issue. Is there something else I still need to do to make sure the receiptData value will be read and encoded correctly, or some other issue that might be causing this problem?
编辑:
我尝试了另一种设置storeRequest.httpBody的方法:
I tried an alternate way of setting storeRequest.httpBody:
func receiptValidation() { let receiptPath = Bundle.main.appStoreReceiptURL?.path if FileManager.default.fileExists(atPath: receiptPath!){ var receiptData:NSData? do{ receiptData = try NSData(contentsOf: Bundle.main.appStoreReceiptURL!, options: NSData.ReadingOptions.alwaysMapped) } catch{ print("ERROR: " + error.localizedDescription) } let receiptString = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)) //.URLEncoded let dict = ["receipt-data":receiptString, "password":SUBSCRIPTION_SECRET] as [String : Any] var jsonData:Data? do{ jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted) } catch{ print("ERROR: " + error.localizedDescription) } let storeURL = NSURL(string:"sandbox.itunes.apple/verifyReceipt")! let storeRequest = NSMutableURLRequest(url: storeURL as URL) storeRequest.httpMethod = "POST" storeRequest.httpBody = jsonData! let session = URLSession(configuration:URLSessionConfiguration.default) let task = session.dataTask(with: storeRequest as URLRequest) { data, response, error in do{ let jsonResponse:NSDictionary = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary let expirationDate:NSDate = self.expirationDateFromResponse(jsonResponse: jsonResponse)! self.updateIAPExpirationDate(date: expirationDate) } catch{ print("ERROR: " + error.localizedDescription) } } task.resume() } }然而,当我使用此代码运行应用程序,它会在到达 jsonData = try JSONSerialization.data(withJSONObject:dict,options:.prettyPrinted)行时挂起。它甚至没有进入捕获块,它只是停止做任何事情。从我在网上看到的,其他人似乎在使用JSONSerialization.data在Swift 3中设置请求httpBody时遇到了麻烦。
However, when I run the app with this code, it hangs upon reaching the line jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted). It doesn't even make it to the catch block, it just stops doing anything. From what I've seen online, other people seem to have trouble using JSONSerialization.data to set the request httpBody in Swift 3.
推荐答案它与Swift 4正常工作
Its working correctly with Swift 4
func receiptValidation() { let SUBSCRIPTION_SECRET = "yourpasswordift" let receiptPath = Bundle.main.appStoreReceiptURL?.path if FileManager.default.fileExists(atPath: receiptPath!){ var receiptData:NSData? do{ receiptData = try NSData(contentsOf: Bundle.main.appStoreReceiptURL!, options: NSData.ReadingOptions.alwaysMapped) } catch{ print("ERROR: " + error.localizedDescription) } //let receiptString = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)) let base64encodedReceipt = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions.endLineWithCarriageReturn) print(base64encodedReceipt!) let requestDictionary = ["receipt-data":base64encodedReceipt!,"password":SUBSCRIPTION_SECRET] guard JSONSerialization.isValidJSONObject(requestDictionary) else { print("requestDictionary is not valid JSON"); return } do { let requestData = try JSONSerialization.data(withJSONObject: requestDictionary) let validationURLString = "sandbox.itunes.apple/verifyReceipt" // this works but as noted above it's best to use your own trusted server guard let validationURL = URL(string: validationURLString) else { print("the validation url could not be created, unlikely error"); return } let session = URLSession(configuration: URLSessionConfiguration.default) var request = URLRequest(url: validationURL) request.httpMethod = "POST" request.cachePolicy = URLRequest.CachePolicy.reloadIgnoringCacheData let task = session.uploadTask(with: request, from: requestData) { (data, response, error) in if let data = data , error == nil { do { let appReceiptJSON = try JSONSerialization.jsonObject(with: data) print("success. here is the json representation of the app receipt: \(appReceiptJSON)") // if you are using your server this will be a json representation of whatever your server provided } catch let error as NSError { print("json serialization failed with error: \(error)") } } else { print("the upload task returned an error: \(error)") } } task.resume() } catch let error as NSError { print("json serialization failed with error: \(error)") } } }更多推荐
在Swift 3中实现收据验证
发布评论