Swift集成Apple Pay:didAuthorizePayment代理支付服务端验证疑问
Apple Pay Swift集成:支付验证与服务器交互实现
在Apple Pay的集成流程中,客户端并不直接与Apple支付服务器交互验证,而是需要将Apple生成的支付令牌提交给你的后端服务,由后端完成与Apple支付系统的验证和后续扣款逻辑。以下是具体实现方案:
一、客户端提取支付令牌并提交到服务器
在didAuthorizePayment代理方法中,核心是获取PKPayment对象里的支付令牌,再通过HTTP请求发送到你的后端接口。更新后的代码示例:
func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) { // 显示加载状态 loader.startAnimating() lblLoading.isHidden = false // 提取支付令牌并转为可传输格式 guard let paymentData = payment.token.paymentData as? [String: Any], let tokenData = try? JSONSerialization.data(withJSONObject: paymentData, options: []), let tokenBase64 = tokenData.base64EncodedString(options: .endLineWithLineFeed) else { let error = NSError(domain: "PaymentError", code: 1001, userInfo: [NSLocalizedDescriptionKey: "支付令牌解析失败"]) completion(PKPaymentAuthorizationResult(status: .failure, errors: [error])) loader.stopAnimating() lblLoading.isHidden = true return } // 组装请求参数(根据业务需求添加订单ID、用户信息等) let requestParams: [String: Any] = [ "paymentToken": tokenBase64, "totalAmount": totalAmount, "currencyCode": paymentRequest.currencyCode, "orderId": "ORDER_20240520_001" // 替换为你的唯一订单ID ] // 构造服务器请求 guard let url = URL(string: "https://你的后端域名/api/apple-pay/verify") else { let error = NSError(domain: "NetworkError", code: 1002, userInfo: [NSLocalizedDescriptionKey: "无效的服务器地址"]) completion(PKPaymentAuthorizationResult(status: .failure, errors: [error])) loader.stopAnimating() lblLoading.isHidden = true return } var urlRequest = URLRequest(url: url) urlRequest.httpMethod = "POST" urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type") urlRequest.httpBody = try? JSONSerialization.data(withJSONObject: requestParams, options: []) // 发起网络请求 let task = URLSession.shared.dataTask(with: urlRequest) { [weak self] data, response, error in DispatchQueue.main.async { self?.loader.stopAnimating() self?.lblLoading.isHidden = true guard let self = self else { return } // 处理网络错误 if let error = error { completion(PKPaymentAuthorizationResult(status: .failure, errors: [error])) return } // 处理服务器响应状态码 guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { let error = NSError(domain: "ServerError", code: 1003, userInfo: [NSLocalizedDescriptionKey: "服务器验证失败"]) completion(PKPaymentAuthorizationResult(status: .failure, errors: [error])) return } // 解析服务器返回的验证结果 if let data = data { do { if let result = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let isSuccess = result["success"] as? Bool, isSuccess { // 验证成功,通知Apple Pay完成授权 completion(PKPaymentAuthorizationResult(status: .success, errors: nil)) // 这里可添加订单成功后的页面跳转逻辑 } else { let error = NSError(domain: "PaymentError", code: 1004, userInfo: [NSLocalizedDescriptionKey: "支付验证未通过"]) completion(PKPaymentAuthorizationResult(status: .failure, errors: [error])) } } catch { let error = NSError(domain: "ParseError", code: 1005, userInfo: [NSLocalizedDescriptionKey: "结果解析失败"]) completion(PKPaymentAuthorizationResult(status: .failure, errors: [error])) } } else { let error = NSError(domain: "ServerError", code: 1006, userInfo: [NSLocalizedDescriptionKey: "服务器未返回有效数据"]) completion(PKPaymentAuthorizationResult(status: .failure, errors: [error])) } } } task.resume() }
二、后端验证流程说明
你的后端服务需要完成以下步骤:
- 接收客户端发送的支付令牌和业务参数
- 向Apple的支付验证端点发起请求:测试阶段使用沙箱环境端点,正式上线切换为生产环境端点
- 提交格式为
{"payment-token": "客户端传来的base64令牌"}的JSON参数 - 解析Apple返回的响应:若
status字段为0,则表示令牌有效,此时可执行扣款、更新订单状态等操作;非0值则表示验证失败 - 将验证结果(成功/失败)返回给客户端
三、关键注意事项
- HTTPS强制要求:所有支付相关网络请求必须使用HTTPS协议,防止敏感数据泄露
- 环境区分:测试时使用Apple沙箱账号,上线前务必切换到生产环境的验证端点
- 错误覆盖:要处理令牌解析失败、网络异常、服务器错误、Apple验证失败等所有可能的异常场景,给用户明确提示
- 订单幂等性:确保订单ID唯一,避免重复提交导致的重复扣款问题
内容的提问来源于stack exchange,提问作者Saravanan
相关产品推荐
相关产品推荐

