Highlight
Xcode 12 将 StoreKit 内购测试带到本地配置、Transaction Manager 和 StoreKitTest 自动化流程中,让开发者先在本地验证购买、退款、Ask to Buy 和订阅续期,再用 Sandbox 覆盖服务器收据与订阅管理场景。
核心内容
做内购功能时,开发者过去要先进入 App Store Connect,注册 app,定义内购商品,再创建 Sandbox 测试账号。只有这些准备完成后,Xcode 里的 StoreKit 代码才能真正拿到商品、发起购买、验证收据。
这条路径的问题出现在开发早期。商品 ID、价格、订阅分组、退款、Ask to Buy、订阅续期这些状态都需要反复调试,团队却要等待服务器配置和 Sandbox 账号配合。Fruta 示例里,app 已经写好了 SKProductsRequest,但因为 App Store Connect 还没有配置商品,模拟器里不会显示任何食谱。
Xcode 12 给出的改变,是把第一轮 StoreKit 测试放回本地项目。开发者创建 .storekit 配置文件,定义消耗型、非消耗型、自动续期订阅,把 scheme 的 Run Options 指向这个配置文件,StoreKit 就会从本地测试环境返回 SKProduct 元数据。
手动测试也变得可控。Transaction Manager 可以删除交易、模拟退款、批准或拒绝 Ask to Buy。订阅配置可以加速时间,让一个月续期在几秒内发生。等本地流程稳定后,再进入 App Store Connect 和 Sandbox 测试真实服务器、收据签名、服务器通知和 TestFlight 覆盖。
详细内容
本地 StoreKit 配置
(04:13)Fruta 示例先创建 StoreKit configuration file,把要售卖的食谱写进项目。这个文件可以添加 consumable、non-consumable、auto-renewable subscriptions。商品 ID 必须匹配 app 传给 StoreKit API 的值,价格在本地直接填写,用来控制返回给 app 的 SKProduct。
StoreKit configuration file
Product ID copied from Store.swift
Run Options -> StoreKit Configuration
SKProductsRequest -> SKProduct
关键点:
StoreKit configuration file是本地商品目录,演讲中把食谱定义成 non-consumable。Product ID要和 app 代码里的商品标识一致,否则SKProductsRequest拿不到目标商品。- scheme 的
Run Options选择该配置后,StoreKit 使用本地测试环境。 - 修改商品描述后,app 重新执行
SKProductsRequest就能拿到更新后的元数据,不需要重新编译或重启。
交易状态和边界流程
(08:39)Fruta 把拿到的 SKProduct 创建成 SKPayment,再加入 payment queue。模拟器会显示接近真实用户体验的支付表单,但测试时不需要登录,也不会收费。Transaction Manager 显示本地购买记录,并允许开发者删除购买、模拟退款、处理 Ask to Buy、切换 interrupted purchases。
SKProduct -> SKPayment -> payment queue
Transaction Manager -> delete transaction
Transaction Manager -> refund transaction
Ask to Buy -> deferred transaction -> approve or decline
Interrupted purchases -> failed first transaction -> later transaction added to queue
关键点:
- 删除交易可以让 app 回到未购买状态,适合重复调试同一个购买流程。
- 模拟退款后,交易仍在 Transaction Manager 和 receipt 中,但 receipt 会带上 cancellation date。
- Ask to Buy 会让 app 的 payment transaction observer 收到 deferred 状态,再由 Transaction Manager 批准或拒绝。
- Interrupted purchases 先返回失败,用户完成账号动作后,同一商品的新交易会加入队列。
订阅、收据和本地证书
(12:15)session 用 Recipes Plus 和 Recipes Pro 演示自动续期订阅。两个订阅放在同一个 subscription group 中,app 可以提供升级入口。配置文件的 Time Rate 可以把一秒设为一天,用几秒钟观察自动续期。
Auto-renewable subscriptions
Subscription group
Time Rate -> one second equals one day
StoreKit Test Certificate
debug macro for local receipt validation
关键点:
- 同一个 subscription group 支持 app 展示不同订阅档位和升级选项。
- Time Rate 让续期测试不必等待真实月份流逝。
- 本地 StoreKit test receipt 使用不同私钥签名,不能直接按 Sandbox 或 production receipt 的证书链处理。
- transcript 建议在 client-side validation code 中使用 debug macro,在 debug 构建里选择 StoreKit Test Certificate。
StoreKitTest 和 Sandbox 补位
(17:22)手动流程跑通后,StoreKitTest framework 把本地测试环境暴露给 XCTest。测试可以禁用弹窗、清理旧交易、触发购买、立即触发订阅续期,让内购流程进入单元测试和 UI 测试。
StoreKitTest framework
XCTest
StoreKitTest session initialized with configuration file
Disable dialogs
Clear previous transactions
Buy recipe and confirm availability
关键点:
- configuration file 需要加入测试 target,测试才能引用它。
- 禁用 dialogs 后,测试不需要等待人工点击支付表单。
- 清理 previous transactions 可以保证每次测试从干净状态开始。
- Sandbox 仍用于 App Store Connect 商品配置、Sandbox Apple ID、App Store 签名 receipt、server-side receipt validation 和 App Store server notifications。
核心启发
- 本地内购回归套件:做什么:为每个内购商品准备
.storekit配置和测试 target。为什么值得做:session 展示了本地购买、删除交易和退款都可以在 Xcode 中完成。怎么开始:先把商品 ID 从 app 代码复制到配置文件,再用 StoreKitTest 清理旧交易并执行购买断言。 - 退款后权限回收测试:做什么:验证退款发生后,付费内容是否立即锁回去。为什么值得做:transcript 说明退款会保留在 receipt 中并带上 cancellation date,app 会收到更新。怎么开始:用 Transaction Manager 模拟 refund,再检查本地 entitlement 状态。
- Ask to Buy 体验检查:做什么:覆盖儿童账号请求购买、等待批准、批准后解锁的流程。为什么值得做:本地测试可以把交易置为 deferred,再手动 approve 或 decline。怎么开始:在 StoreKit configuration file 的 editor menu 启用 Ask to Buy,观察 payment transaction observer 状态变化。
- 订阅续期加速测试:做什么:把月订阅的续期、升级和权限刷新压缩到几秒内验证。为什么值得做:Time Rate 可以把 one second 设为 one day,适合快速检查 auto-renewable subscriptions。怎么开始:把多个订阅放入同一个 subscription group,购买后调高 Time Rate。
- 本地 receipt 验证分支:做什么:在 debug 构建中使用 StoreKit Test Certificate 验证本地 receipt。为什么值得做:本地 receipt 使用不同私钥签名,证书链也不同。怎么开始:从 StoreKit configuration editor 导出证书,在 client-side validation code 里用 debug macro 选择证书。
关联 Session
- What’s new with in-app purchase — 延续本 session 提到的退款、server notifications、receipt 和 StoreKit 更新。
- Architecting for subscriptions — 深入 subscription entitlement 和订阅生命周期,适合接在 StoreKit Testing 之后做服务端设计。
- What’s new in App Store Connect — 介绍 App Store Connect 中 in-app purchase、subscriptions 和管理工具的更新。
- Expanding automation with the App Store Connect API — 关注 App Store Connect API 自动化,可补充本地测试之后的发布和运营流程。
评论
GitHub Issues · utterances