gpt4 book ai didi

swift - IAP 实际验证收据 (Swift)

转载 作者:搜寻专家 更新时间:2023-10-31 21:52:34 26 4
gpt4 key购买 nike

我一直在尝试在我的 spritekit 游戏中实现收据验证。我一直在关注各种教程,基本上以这段代码结束

enum RequestURL: String {
case production = "https://buy.itunes.apple.com/verifyReceipt"
case sandbox = "https://sandbox.itunes.apple.com/verifyReceipt"
case myServer = "my server address"
}

enum ReceiptStatusCode: Int {

// Not decodable status
case unknown = -2

// No status returned
case none = -1

// valid status
case valid = 0

// The App Store could not read the JSON object you provided.
case JSONNotReadable = 21000

// The data in the receipt-data property was malformed or missing.
case malformedOrMissingData = 21002

// The receipt could not be authenticated.
case receiptCouldNotBeAuthenticated = 21003

// The shared secret you provided does not match the shared secret on file for your account.
// Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions.
case sharedSecretNotMatching = 21004

// The receipt server is currently not available.
case receiptServerUnavailable = 21005

// This receipt is valid but the subscription has expired. When this status code is returned to your server, the receipt data is also decoded and returned as part of the response.
// Only returned for iOS 6 style transaction receipts for auto-renewable subscriptions.
case subscriptionExpired = 21006

// This receipt is from the test environment, but it was sent to the production environment for verification. Send it to the test environment instead.
case testReceipt = 21007

// This receipt is from the production environment, but it was sent to the test environment for verification. Send it to the production environment instead.
case productionEnvironment = 21008
}

func validateReceipt(forTransaction transaction: SKPaymentTransaction) {

guard let receiptURL = NSBundle.mainBundle().appStoreReceiptURL else { return }

guard let receipt = NSData(contentsOfURL: receiptURL) else { return }

let receiptData = receipt.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
let payload = ["receipt-data": receiptData]

var receiptPayloadData: NSData?

do {
receiptPayloadData = try NSJSONSerialization.dataWithJSONObject(payload, options: NSJSONWritingOptions(rawValue: 0))
}
catch let error as NSError {
print(error.localizedDescription)
return
}

guard let payloadData = receiptPayloadData else { return }
guard let requestURL = NSURL(string: RequestURL.sandbox.rawValue) else { return }

let request = NSMutableURLRequest(URL: requestURL)
request.HTTPMethod = "POST"
request.HTTPBody = payloadData

let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { (data, response, error) in
if let error = error {
print(error.localizedDescription)
return
}
guard let data = data else { return }

do {
let jsonData = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves) as? NSDictionary

guard let json = jsonData else { return }

// Correct ?
guard let status = json["status"] as? Int where status == ReceiptStatusCode.valid.rawValue else { return }

// Unlock product here?
// Other checks needed?
}

catch let error as NSError {
print(error.localizedDescription)
return
}
}

task.resume()
}

这是漂亮的样板代码,可以按预期工作。我现在的问题是我不知道如何在最后一步(标记线)实际验证收据。我想我现在必须携带 5 张左右的支票来验证收据。我只是不知道它们中的大部分是如何快速完成的。大多数教程要么是旧的,不包括此步骤,要么不是用 swift 编写的。

如果任何成功使用收据验证的人可以帮助我朝着正确的方向前进,我们将不胜感激。非常感谢

更新:

在 JSA986I 和 cbartel 给出了很好的答案后,我把它变成了 github 上的一个帮助程序。非常感谢您的帮助

https://github.com/crashoverride777/SwiftyReceiptValidator

最佳答案

这是在 Apple guide 之后使用 Swift 2.1 版的解决方案.

苹果也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)
}
}
}

关于swift - IAP 实际验证收据 (Swift),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32291701/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com