我正在Swift 3中开发一个iOS应用程序,并试图按照本教程实施收据验证:http://savvyapps.com/blog/how-setup-test-auto-renewable-subscription-ios-app。但是,本教程似乎是使用早期版本的Swift编写的,因此我必须进行一些更改。这里是我的receiptValidation()函数:在Swift 3中实现收据验证
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:"https://sandbox.itunes.apple.com/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;
。我查了一下,这意味着“收据数据属性中的数据不正确或缺失。”但是,我正在测试的设备拥有该产品的活动沙盒订阅,并且订阅似乎除了此问题以外正常工作。还有什么我仍然需要做,以确保receiptData值将被正确读取和编码,或其他可能导致此问题的问题?
编辑:
我尝试设置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:"https://sandbox.itunes.apple.com/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)
。它甚至不会让它进入catch块,它只是停止做任何事情。从我在网上看到,其他人似乎无法使用JSONSerialization.data来设置Swift 3中的httpBody请求。
请确保您已编码base64编码收据中的任何+字符的%编码。即用+%2b替换+的实例 – Paulw11
我更改了我的代码,在声明后立即对收件人字符串进行了此更改,但仍然看到相同的错误。另外,当我打印出receiptString时,我注意到它包含了很多用于分隔64位长字符串的“/”字符。这是如何正确编码应该看起来? – user3726962
我还应该提到,我尝试删除“/”字符,但我仍然看到21002状态。 – user3726962