LESSON 49 / 577 分钟

StoreKit 2:一次购买如何完成

把购买看成可取消、可能待批准、需要验证和交付的状态机,而不是一次成功/失败的网络调用。

用你的前端经验理解

类似创建订单 → 支付状态变化 → 校验 → 履约。StoreKit 的成功结果还包着交易验证结果,pending 也不是已付款成功。

为什么需要它

一次购买是状态机,不是一个只会成功或抛错的函数。用户可以取消,家长批准可能让交易进入 pending,系统也可能在稍后通过更新序列送来交易。把“购买中”“等待处理”“已验证且已交付”分别建模,可以避免按钮卡住或提前解锁。

它是怎样工作的

StoreKit 2 以验证结果包装交易。处理可信交易后交付相应内容,并在已完成所需处理后 finish;如果还未可靠发放消耗型额度就提前结束,可能难以恢复交付。应用需要长期监听相关交易更新,处理启动时尚未完成的工作,并对同一交易 ID 保持幂等。

把关键概念连起来

1

加载与发起

用 Product.products(for:) 获取商品并处理缺失/失败;调用 purchase() 展示系统购买界面。防止重复点击,不伪造价格或可购买状态。

2

处理结果

success 中检查 VerificationResult,只有 verified 才进入可靠交付路径;pending 等待后续交易更新,userCancelled 安静返回;抛出的错误单独反馈。

3

交付与完成

以 transaction ID 做幂等,可靠记录并交付权益后调用 finish()。启动早期监听 Transaction.updates,覆盖延后批准、外部购买等变化,并管理监听任务生命周期。

Swift · 示例片段
import StoreKit// async throws 函数内的处理结构;deliverOnce 需自行实现switch try await product.purchase() {case .success(let result):    switch result {    case .verified(let transaction):        try await deliverOnce(transaction) // 可靠、幂等地履约        await transaction.finish()    case .unverified:        showVerificationFailure() // 不授予权益    }case .pending:    showPending() // 等待 Transaction.updatescase .userCancelled:    break@unknown default:    showUnsupportedResult()}
  • 购买返回的枚举与交易验证结果属于两层判断:成功分支内部也不能忽略验证。
  • pending 与取消都不是已交付。finish 应在所需交易处理可靠完成后调用,重复交易处理必须保持幂等。

用于理解当前概念的代码片段;部分示例需要放入对应工程与作用域,并补齐上下文。

家长批准后的迟到成功

孩子点击购买后显示待批准,先保持未解锁。家长之后批准,应用通过交易更新接收并验证交易,再幂等授予权益并 finish;这可能发生在原购买页面已经关闭之后。

购买十次 AI 生成额度

  1. 客户端发起商品购买,取消时不改变余额,pending 时显示等待且不重复引导付费。
  2. 可信交易到达后交给服务端账本验证并发放一次额度,网络失败时保留可重试状态,不直接伪造成功余额。
  3. 交付确认后完成交易处理;再次收到同一交易时读取原有结果,不再发放十次。

这里需要你亲自判断

不要在拿到 success 外层枚举后就跳过验证发会员;也不要在消耗型权益尚未可靠入账时先 finish。未验证交易不能悄悄当成功。

做一个小练习

在购买实验中依次模拟取消、待批准、校验失败和已验证成功,观察每种结果是否能开启权益。

  1. 推演购买后立刻断网、交付成功后客户端崩溃、同一交易重复到达三种情况。
  2. 分别指出何时可以显示权益、何时可以 finish。
展开参考思路与验收标准

支付结果与内容交付可能跨进程完成,所以必须可恢复。完成顺序围绕可靠交付设计,不能把 finish 放在无论成功失败都会执行的清理块里。

打开对应交互实验

purchase() 返回 pending 时,应该立即解锁会员吗?

继续查阅官方资料
Apple Developer 官方资料

本课聚焦核心认知。具体 API、系统要求与发布政策,以当前官方文档和工程验证为准。

答对理解题后即可标记完成