跳转到正文
YGJoon 技术博客

iOS 支付回跳对账:待处理记录持久化与服务端确认

发布于:
·736 字 · 约 2 分钟·作者:YGJoon
介绍第三方支付发起、待处理引用持久化与前台恢复对账,说明客户端回调不能单独证明交易完成。
iOS 支付回跳对账:待处理记录持久化与服务端确认文章封面
目录

示例代码均为匿名化改写,用于说明模式;交易状态必须以服务端核对结果为准。

发起支付不等于交易成功

用户切换到第三方支付应用后,原应用可能挂起;用户也可能取消、切换账号,或在服务端更新订单前先回到客户端。把 SDK 的“请求已接受”当作付款完成,会造成订单状态误报。

客户端收到回跳时,适合将它视为查询提示。真正的付款状态应通过服务端查询确认,只有服务端状态满足条件后才清理本地待处理记录或离开付款流程。

enum PaymentState: Sendable {
    case pending, paid, cancelled, failed
}

struct PendingPayment: Sendable {
    let reference: String
    let accountID: UUID
}

protocol PaymentReconciliation: Sendable {
    func state(for reference: String, accountID: UUID) async throws -> PaymentState
    func removePending(reference: String, accountID: UUID) async
}

func reconcile(
    _ payment: PendingPayment,
    using service: some PaymentReconciliation
) async throws -> PaymentState {
    let state = try await service.state(
        for: payment.reference,
        accountID: payment.accountID
    )
    switch state {
    case .pending:
        break // Keep the local reference for a later retry.
    case .paid, .cancelled, .failed:
        await service.removePending(
            reference: payment.reference,
            accountID: payment.accountID
        )
    }
    return state
}

第三方回跳只表示可以开始核对,不足以证明付款成功;成功页面必须等待服务端确认。

为何先写待处理记录

发起第三方流程前,把恢复所需的支付引用和账号归属写入本地应用数据,再打开第三方 SDK。若支付页面无法启动,则撤销本次新建记录。这样即使 App 被系统回收,也可以在下次恢复时继续核对。

本地记录应只包含必要的引用标识,不保存可复用登录凭据。记录要绑定账号,避免当前用户误处理另一个账号之前留下的支付状态。

待处理引用应在切换到支付应用前持久化,并绑定发起它的账号。这样应用被系统回收后仍能恢复查询,同时不必把可复用凭据写入本地记录。

对账时机与失败处理

登录恢复、重新回到前台和进入相关订单页面,都可以触发一次对账。网络暂时失败时有限重试;仍失败就保留引用,等待下一次前台机会。若应用不安排后台任务,就不应承诺用户离开应用时持续更新支付状态。

凭据传递要格外谨慎

若第三方页面路由中需要登录凭据,应核对该凭据的权限、有效期、接收范围以及日志策略。URL 编码不会隐藏凭据;可行时使用服务端签发的短时、单次交换码。


分享这篇文章:


相关文章

上一篇
iOS 退款流程设计:金额校验、申请理由与进度状态
下一篇
iOS Keychain 会话隔离:请求快照与迟到响应处理