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

SwiftUI接入Checkout.com Apple Pay时支付中关闭页面无法获取结果怎么办

问题根因

你当前遇到的异常是因为PKPaymentAuthorizationController的关闭回调(paymentAuthorizationControllerDidFinish)和你调用Checkout接口的异步处理逻辑是并行的:当用户在Checkout接口返回前主动关闭支付控制器,你现有的逻辑会直接在关闭时给startPayment的回调返回false,但此时Checkout的处理还在进行,后续拿到成功结果时已经没有可以触发的回调通知View层了。

解决方案

你可以通过保留待触发的回调、标记支付处理状态的方式,实现无论用户是否提前关闭支付控制器,都能返回真实的支付结果,具体修改如下:

1. 为支付处理类新增状态存储属性

首先在你的PaymentHandler类中增加属性,用来保存待触发的支付回调、标记当前是否有正在处理的支付请求:

class PaymentHandler: NSObject, PKPaymentAuthorizationControllerDelegate {
    // 原有属性保持不变
    var checkoutFailure = false
    var failureMsg = ""
    var paymentID = ""
    // 新增属性:存储待触发的支付完成回调
    private var pendingPaymentCompletion: ((Bool) -> Void)?
    // 新增属性:标记是否有正在处理的Checkout支付请求
    private var isProcessingPayment = false
}

2. 修改startPayment方法,持久化存储回调

原来的startPayment方法里的回调是局部变量,修改为存储到上面新增的实例属性中:

func startPayment(total: Double, custmName: String, order: Orders, completion: @escaping (Bool) -> Void) {
    // 原有初始化PKPaymentRequest、调起支付控制器的逻辑保持不变
    // 将回调存储到实例属性,避免支付控制器关闭后被释放
    self.pendingPaymentCompletion = completion
    self.isProcessingPayment = false
}

3. 修改didAuthorizePayment逻辑,标记处理状态

在收到Apple Pay授权、开始调用Checkout接口时标记支付处理中,接口返回后再触发存储的回调:

func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) {
    isProcessingPayment = true // 标记开始处理支付,关闭控制器时不要立刻返回失败
    checkout.processPayment(body: payment.token.paymentData) { [weak self] success, msg, id in
        guard let self = self else { return }
        DispatchQueue.main.async {
            self.failureMsg = msg
            self.paymentID = id
            self.checkoutFailure = !success
            // 触发存储的回调,返回真实支付结果
            self.pendingPaymentCompletion?(success)
            self.pendingPaymentCompletion = nil
            self.isProcessingPayment = false
        }
        
        if success {
            self.orderObject.sendToDB(custmName: self.custmName, paymentID: self.paymentID)
            completion(PKPaymentAuthorizationResult(status: .success, errors: nil))
        } else {
            completion(PKPaymentAuthorizationResult(status: .failure, errors: []))
        }
    }
}

4. 实现paymentAuthorizationControllerDidFinish代理方法

这个方法是支付控制器关闭时一定会触发的回调,在这里判断如果没有正在处理的支付再返回失败:

func paymentAuthorizationControllerDidFinish(_ controller: PKPaymentAuthorizationController) {
    controller.dismiss(animated: true)
    // 只有没有正在处理的支付时,才判定为用户主动取消,返回失败
    if !isProcessingPayment {
        pendingPaymentCompletion?(false)
        pendingPaymentCompletion = nil
        checkoutFailure = true
    }
}

额外优化建议

  • 给Checkout的支付请求增加超时逻辑(比如15秒超时),超时后主动触发回调返回失败,避免回调长期挂起占用内存
  • 后端增加订单状态查询接口,用户进入订单列表页时主动拉取对应订单的支付状态,避免极端场景下回调丢失导致的状态不一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 17:45:01