我正在开发订阅IAP。我设置了所有购买,他们的详细信息很好,我可以在沙箱中购买并获得所有消息。我现在遇到的问题是检查收据。我总是得到一个返回的URL,但是当我尝试读取它时,我不断收到该文件不存在的错误。所以我尝试用SKReceiptRefreshRequest
刷新。再试一次,还是一样的。
我在模拟器和两个真实设备上卸载了应用程序,再次尝试从新安装和同样的问题。有一件事我意识到,其中一个真实设备会在[沙盒]提及时显示密码提示请求。但是,在两次提示(包括接受密码)后,我收到“用户/密码不匹配”消息,而不是购买完成。在模拟器上提示输入iTunes帐户和密码时,它都会通过,但实际的购买确认永远不会到来(我等了4分钟,网络连接稳定)。
这是验证过程(我已经改变了很多次,来自不同的教程和其他人的问题)
let receiptURL = Bundle.main.appStoreReceiptURL
func receiptValidation() {
print("1")
print("2", receiptURL)
do {
print("3")
let receiptData = try Data(contentsOf: receiptURL!, options: .alwaysMapped)
print(receiptData)
let receiptString = receiptData.base64EncodedString(options: [])
let dict = ["receipt-data" : receiptString, "password" : "\(password)"] as [String : Any]
do {
print("4")
let jsonData = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
if let sandboxURL = Foundation.URL(string:"https://sandbox.itunes.apple.com/verifyReceipt") {
print("5")
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
print("6")
if let receivedData = data,
let httpResponse = response as? HTTPURLResponse,
error == nil,
httpResponse.statusCode == 200 {
print("7")
do {
print("8")
if let jsonResponse = try JSONSerialization.jsonObject(with: receivedData, options: JSONSerialization.ReadingOptions.mutableContainers) as? Dictionary<String, AnyObject> {
print(jsonResponse, jsonResponse.count)
// parse and verify the required informatin in the jsonResponse
} else { print("Failed to cast serialized JSON to Dictionary<String, AnyObject>") }
}
catch { print("Couldn't serialize JSON with error: " + error.localizedDescription) }
}
}
print("51")
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 {
let appReceiptRefreshRequest = SKReceiptRefreshRequest(receiptProperties: nil)
appReceiptRefreshRequest.delegate = self
appReceiptRefreshRequest.start()
print("Couldn't read receipt data with error: " + error.localizedDescription) }
}
func requestDidFinish(_ request: SKRequest) {
print("???")
do {
let receipt = try Data(contentsOf: receiptURL!) //force unwrap is safe here, control can't land here if receiptURL is nil
print(receipt)
} catch {
print("WTF NO RECEIPT")
// still no receipt, possible but unlikely to occur since this is the "success" delegate method
}
}
这是运行应用程序的调试输出。 receiptURL在模拟器/真实设备之间有所不同,但除此之外一切都保持不变。
1
2 Optional(file:///Users/apple/Library/Developer/CoreSimulator/Devices/47EA3293-9B13-4808-BD0B-13D884D14BFE/data/Containers/Data/Application/2F1B7E4E-C523-4270-BF46-6D77F7A2220C/StoreKit/receipt)
3
Couldn't read receipt data with error: The file “receipt” couldn’t be opened because there is no such file.
???
WTF NO RECEIPT
???
WTF NO RECEIPT
为什么我无法创建或找到收据?它是一个设备问题,一个错误还是我忘了什么?
答案 0 :(得分:1)
整个IAP流程异步工作,因为除非整个流程已成功完成,否则您将无法收到收据数据。我无法根据您在上述问题中粘贴的内容查看整个代码,但如果您尝试使用按钮或类似内容立即访问收据数据,则无法获得。
访问收据数据的正确方法是尝试根据IAP请求的成功完成处理程序回调来访问收据。提交IAP请求后,有一个服务器端进程负责处理IAP,然后触发IAP SKPaymentTransactionObserver
类的回调处理程序。使用此类中的通知处理程序,您可以将更新发送到ViewController以检查收据数据。
答案 1 :(得分:0)
在进一步研究的同时,我找到了以下文章,解决了这个问题
重要提示:如果您错误地使用沙盒测试程序帐户登录测试设备而非测试环境的生产环境,则沙盒帐户将变为无效,无法再次使用。如果发生这种情况,请使用新的电子邮件地址创建一个新的沙盒测试程序帐户。