You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HTTP POST传多类型参数触发NSInvalidArgumentException问题求助

解析你的NSInvalidArgumentException问题

Hey there, let's break down why you're running into that NSInvalidArgumentException and fix it step by step:

1. 核心触发原因:JSON无法序列化Data类型

Look at your postString dictionary—you're trying to put requestData (a Data object) into it with the key "receiptData".

JSON serialization only supports JSON-compatible types: strings, numbers, arrays, dictionaries, booleans, and null. Binary Data isn't part of the JSON spec, so when JSONSerialization.data(withJSONObject:) tries to process this dictionary, it hits a non-serializable type and throws the exception you're seeing.

2. 额外的请求逻辑问题

You're using uploadTask(with: request, from: requestData) but also setting request.httpBody to the serialized postString data. This creates a conflict: the from parameter in uploadTask will overwrite your pre-set httpBody, so your full parameter set won't be sent to the server. You should use a regular dataTask instead since you're already assembling the full request body.


修正后的代码片段

Here's how to adjust your code to fix both issues:

func receiptValidation() {
    let SUBSCRIPTION_SECRET = mySecretKey
    let defaults = UserDefaults.standard
    
    guard let receiptURL = Bundle.main.appStoreReceiptURL, 
          FileManager.default.fileExists(atPath: receiptURL.path) else {
        print("Receipt file not found")
        return
    }
    
    do {
        let receiptData = try Data(contentsOf: receiptURL, options: .alwaysMapped)
        let base64encodedReceipt = receiptData.base64EncodedString(options: .endLineWithCarriageReturn)
        
        // 直接使用Base64编码后的字符串,而非Data类型
        let postString: [String: Any] = [
            "receiptData": base64encodedReceipt,
            "deviceType": "IOS",
            // 用可选绑定避免强制解包崩溃
            "subscriberId": encodeString(normalString: (defaults.array(forKey: "userDetails")?.first as? String) ?? ""),
            "password": encodeString(normalString: (defaults.array(forKey: "userDetails")?.last as? String) ?? ""),
            "productId": PurchaseManager.instance.productId,
            "code": opcodeDetails["opCode"] ?? ""
        ]
        
        guard JSONSerialization.isValidJSONObject(postString) else {
            print("postString is not valid JSON")
            return
        }
        
        let requestData = try JSONSerialization.data(withJSONObject: postString)
        guard let apiBaseUrl = opcodeDetails["apiProxyBaseUrl"],
              let url = URL(string: "\(apiBaseUrl)/api/validate-receipt-data") else {
            print("Invalid API URL")
            return
        }
        
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = requestData
        
        // 使用dataTask而非uploadTask,因为已设置完整的httpBody
        let task = session1?.dataTask(with: request) { (data, response, error) in
            if let error = error {
                print("Request error: \(error.localizedDescription)")
                return
            }
            
            guard let data = data else {
                print("No data received")
                return
            }
            
            do {
                let appReceiptJSON = try JSONSerialization.jsonObject(with: data)
                print("Success! Receipt response: \(appReceiptJSON)")
            } catch {
                print("JSON parsing failed: \(error.localizedDescription)")
            }
        }
        task?.resume()
        
    } catch {
        print("Error processing receipt: \(error.localizedDescription)")
    }
}

额外建议

  • Avoid force unwraps (!): They're a common source of crashes. Use optional bindings (if let, guard let) or default values like ?? "" to handle nil cases gracefully.
  • Validate all inputs: Double-check that values like opcodeDetails["opCode"] and userDetails exist and are of the correct type before using them.
  • Check JSON validity: Always use JSONSerialization.isValidJSONObject(_:) before attempting to serialize a dictionary to catch issues early.

内容的提问来源于stack exchange,提问作者Priya Sri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:14:56