0

我有一个支持订阅以及按需付费功能的应用程序。我在服务器端遇到收据验证问题。如果

  1. 用户尚未订阅并尝试使用按需付费下载内容我收到 21002 错误(传递共享密钥进行验证)
  2. 如果用户订阅并且它已过期。现在用户尝试下载随用随付,然后响应为 21004(未传递共享密钥)

我不明白什么时候应该将共享密钥传递给苹果服务器。由于我们只有一张包含消耗品和订阅收据信息的苹果收据。

有什么帮助吗?

4

2 回答 2

1

Code 21002表示JSON您要发送给苹果的内容有您的共享秘密,并且您的收据数据“格式错误”或不是苹果想要的格式。

在此处输入图像描述

还尝试从收据中删除字符'\n''\r'替换'+'为,'%2B'然后再将其发送到服务器。像这样的东西:

 NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
 NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];
 NSString *receiptDataString = [receipt base64EncodedStringWithOptions:0];
 receiptDataString=[receiptDataString stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"];
 receiptDataString=[receiptDataString stringByReplacingOccurrencesOfString:@"\n" withString:@""];
 receiptDataString=[receiptDataString stringByReplacingOccurrencesOfString:@"\r" withString:@""];
 NSString *postDataString = [NSString stringWithFormat:@"receipt-data=%@", receiptDataString];
 NSString *length = [NSString stringWithFormat:@"%lu", (unsigned long)[postDataString length]];
 [request setValue:length forHTTPHeaderField:@"Content-Length"];
 [request setHTTPBody:[postDataString dataUsingEncoding:NSASCIIStringEncoding]];

参考

Code 21004这意味着您的代码中有逻辑错误,在这种情况下您没有传递密钥

于 2017-03-08T13:47:55.260 回答
0
func receiptValidation() {

    let SUBSCRIPTION_SECRET = "secret"
    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 base64encodedReceipt = receiptData?.base64EncodedString(options: NSData.Base64EncodingOptions.endLineWithCarriageReturn)
        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 = "https://sandbox.itunes.apple.com/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 queue = DispatchQueue(label: "itunesConnect")
            queue.async {
                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, options: .allowFragments) as? NSDictionary
                            print("success. here is the json representation of the app receipt: \(appReceiptJSON)")    
                        } catch let error as NSError {
                            print("json serialization failed with error: \(error)")
                        }
                    } else {
                        print("the upload task returned an error: \(error ?? "couldn't upload" as! Error)")
                    }
                }
                task.resume()
            }

        } catch let error as NSError {
            print("json serialization failed with error: \(error)")
        }
    }
}
于 2018-09-13T07:26:16.330 回答