Alamofire/Stripe中Completion Handler未被调用问题求助
解决方案:Stripe Ephemeral Key Completion Handler 未调用/崩溃问题
1. 最核心的问题:Guard分支遗漏调用Completion
你的createCustomerKey函数里,当从Keychain获取customerId失败时,只打印了日志就直接return,完全没调用传入的completion闭包——这就是为什么你在changePaymentOptionsButtonTapped里的print("ThisIsNeverCalled")永远不执行的根源!
赶紧修复这个分支:
guard let customerId = KeychainWrapper.standard.string(forKey: Stripe_Customer_Id) else { print("Keychain wrapper not retrieving stripe customer Id at MyAPIClient") // 创建自定义错误告知调用方原因,绝对不能直接return let error = NSError(domain: "MyAPIClient", code: -1, userInfo: [NSLocalizedDescriptionKey: "Stripe客户ID未在Keychain中找到"]) completion(nil, error) return }
异步编程里,永远要保证Completion Handler被调用,哪怕是出错场景。
2. 解决completion(nil, nil)导致的崩溃
Stripe的STPJSONResponseCompletionBlock有明确规则:两个参数不能同时为nil。它的内部断言逻辑要求,要么返回有效的临时密钥JSON,要么返回一个错误对象,不允许两者都为空。
所以所有分支都要遵守:
- 成功场景:
completion(合法JSON, nil) - 失败场景:
completion(nil, 合法Error)
绝对不要调用completion(nil, nil),这会直接触发Stripe的内部断言崩溃。
3. 验证Alamofire请求是否真的正常交互
你说后端返回了正确的密钥JSON,但可以加日志确认整个请求链路:
- 打印请求的完整参数,确认参数是否正确传递:
let url = "https://us-central1-foodfactory-813ab.cloudfunctions.net/request_ephemeral_key" let parameters = [ "api_version": apiVersion, "customerId": customerId, ] print("发送临时密钥请求到:\(url),参数:\(parameters)") - 暂时移除
.validate(statusCode: 200..<300),或者打印错误时输出原始响应数据,避免因为后端返回非200状态码导致你看不到真实错误:.responseJSON { responseJSON in switch responseJSON.result { case .success(let json): print("收到临时密钥响应:\(json)") // 用[String: Any]替代[String: AnyObject]更符合Swift 3+规范 completion(json as? [String: Any], nil) case .failure(let error): print("获取临时密钥失败:\(error.localizedDescription)") print("响应原始数据:\(String(data: responseJSON.data ?? Data(), encoding: .utf8) ?? "无数据")") completion(nil, error) } }
通过打印原始响应,你能确认后端是否真的返回了Stripe要求的未修改的临时密钥JSON(不能是包裹在自定义字段里的格式)。
4. 确认后端返回的JSON格式符合Stripe要求
Stripe要求后端必须直接返回从Stripe API拿到的原始临时密钥JSON,不能做任何包装或修改:
✅ 正确格式示例:
{ "id": "ek_test_xxx", "object": "ephemeral_key", "secret": "ek_test_xxx", "created": 1620000000, "expires": 1620003600, "customer": "cus_xxx" }
❌ 错误格式(包裹在自定义字段里):
{ "ephemeral_key": { "id": "ek_test_xxx", ... } }
你自己的解码能解析不代表Stripe的逻辑能识别,一定要确保后端直接返回Stripe API的响应内容。
内容的提问来源于stack exchange,提问作者Alex A
相关产品推荐
相关产品推荐

