Highlight
Apple 为年度订阅新增了 12 个月承诺期的按月付费方案,用户按月扣款降低决策门槛,开发者获得锁定的长期订阅收入;StoreKit 新增
PricingTerms和billingPlanTypeAPI 用于展示和购买,服务端 JWSTransaction 新增commitmentInfo字段追踪履约进度,App Store Connect 审核提交流程也统一支持将 IAP 与其他审核项打包提交。
核心内容
年度订阅的定价困境
做订阅业务的开发者都遇到过这个难题:推年度订阅,用户看到一次性扣款金额直接放弃;推月度订阅,用户随时取消,LTV(生命周期价值)难以保障。两种方案各有利弊,但没有中间地带。
Apple 在 iOS 26.5 给出了官方解法:12 个月承诺期的按月订阅(Monthly subscriptions with a 12-month commitment)。用户每个月支付较小金额,但合约锁定 12 个月。开发者获得确定的长期收入预期,用户获得更低的决策门槛。
这个方案在 App Store Connect 中直接配置。选择一个一年期的自动续订订阅,在 “monthly with a 12-month commitment availability” 下设置可用性,按步骤完成配置。每个计费方案可以独立配置订阅优惠,比如只为承诺期用户提供免费试用。
(01:53)
用 StoreKit 展示新的计费方案
配置完成后,StoreKit 通过新的 PricingTerms 属性暴露计费方案信息。SubscriptionInfo.pricingTerms 返回一个数组,包含该产品的所有可用计费方案。默认的年度预付方案类型是 .upFront,如果配置了按月承诺,数组中会多出一个 .monthly 类型的对象。
在 SwiftUI 中使用 SubscriptionStoreView 时,可以通过 .preferredSubscriptionPricingTerms 修饰符筛选并优先展示按月承诺方案。
(03:29)
服务端追踪承诺期进度
用户订阅后,服务端需要知道当前处于承诺期的第几个月、还剩多少期。JWSTransaction 和 JWSRenewalInfo 新增了 commitmentInfo 字段,包含 billingPeriodNumber(当前期数)、totalBillingPeriods(总期数)、commitmentExpiresDate(承诺到期时间)等信息。
关键点:如果 billingPeriodNumber 小于 totalBillingPeriods,用户仍在承诺期内。此时即使用户在系统设置中取消自动续订,Apple 仍会按月扣款直到承诺期结束。服务端不能提前剥夺用户权益。
(07:45)
Offer Code Redemption API 升级
优惠码兑换接口现在返回 VerificationResult,兑换成功时直接拿到 transaction 对象,失败时拿到具体错误信息。不再需要依赖 Transaction.updates 去盲猜兑换结果。
SwiftUI 中使用 .offerCodeRedemption 修饰符,UIKit 中使用 presentOfferCodeRedeemSheet。Xcode 27 的 StoreKit Testing 支持测试新的兑换 API。
(09:58)
App Store Connect 审核提交流验统一
IAP 审核提交现在可以和其他审核项(In-App Events、自定义产品页面、产品页面优化)打包成一个 Submission 统一提交。提交后在集中视图中查看所有审核项的状态。
App Store Connect API 的 reviewSubmissions 接口扩展支持 IAP、订阅和订阅组资源。旧的 IAP 专属提交 API 将被废弃,建议迁移到新的 reviewSubmission 和 reviewSubmissionItems 资源。
(10:42)
详细内容
在 StoreKit 视图中展示按月承诺方案
(03:29)
import StoreKit
import SwiftUI
struct SubscriptionStore: View {
var body: some View {
SubscriptionStoreView(groupID: "3F19ED53") {
// Custom marketing content
}
.preferredSubscriptionPricingTerms { _, subscriptionInfo in
subscriptionInfo.pricingTerms.first {
$0.billingPlanType == .monthly
}
}
}
}
关键点:
SubscriptionStoreView自动从 App Store 加载产品元数据并适配各平台布局.preferredSubscriptionPricingTerms是 iOS 26.5 新增的修饰符,用于筛选优先展示的计费方案subscriptionInfo.pricingTerms返回所有可用计费方案,.upFront始终存在,.monthly仅在配置了承诺期时出现- 如果不加筛选,系统默认展示
.upFront,按月承诺的低价优势无法体现
自定义商店 UI 中获取定价信息并购买
(04:02)
import StoreKit
var product: Product?
// Fetch and assign product
let pricingTerms = product?.subscription?.pricingTerms
.first(where: { $0.billingPlanType == .monthly })
if let pricingTerms {
let monthlyPrice = pricingTerms.billingDisplayPrice
let totalCommitmentPrice = pricingTerms.commitmentInfo.price
// Display both monthly and total commitment price to the customer
}
let result = try? await product?.purchase(options: [.billingPlanType(.monthly)])
switch result {
// Verify the transaction, give the customer access to
// the purchased content, and then finish the transaction
}
关键点:
billingDisplayPrice是展示给用户的月供金额commitmentInfo.price是 12 个月的总价,应在 UI 中同时展示月供和总价- 购买时传入
.billingPlanType(.monthly)选项,指定使用按月承诺方案 - 计费方案元数据只在用户所在市场的商店可用时才会返回
管理订阅 Sheet
(05:05)
import SwiftUI
import StoreKit
struct ManageSubscriptionsButton: View {
let subscriptionGroupID: String
@State var presentingManageSubscriptionsSheet: Bool = false
var body: some View {
Button("Manage Subscriptions") {
presentingManageSubscriptionsSheet = true
}
.manageSubscriptionsSheet(
isPresented: $presentingManageSubscriptionsSheet,
subscriptionGroupID: subscriptionGroupID
)
}
}
关键点:
.manageSubscriptionsSheet是 SwiftUI 中展示订阅管理界面的方式- UIKit 中对应
showManageSubscriptionsAPI - 用户可以在管理界面查看剩余付款期数和承诺期续订时间
- App Store 自动为承诺期订阅提供新的管理 UI
服务端 JWSTransaction 中的承诺期信息
(07:45)
{
"expiresDate": 1783503660000,
"price": 10990,
"productId": "plus.pro.annual",
"purchaseDate": 1780911660000,
"type": "Auto-Renewable Subscription",
"billingPlanType": "MONTHLY",
"commitmentInfo": {
"billingPeriodNumber": 1,
"totalBillingPeriods": 12,
"commitmentExpiresDate": 1812447660000,
"commitmentPrice": 131880
}
}
关键点:
billingPlanType为"MONTHLY"表示这是按月承诺订阅commitmentInfo.billingPeriodNumber表示当前是第几个计费周期commitmentInfo.totalBillingPeriods固定为 12commitmentInfo.commitmentExpiresDate是整个承诺期的结束时间- 对于
.upFront类型的交易,commitmentInfo为nil
服务端 JWSRenewalInfo 中的承诺期续订信息
(07:59)
{
"renewalBillingPlanType": "MONTHLY",
"commitmentInfo": {
"commitmentAutoRenewProductId": "plus.standard.annual",
"commitmentAutoRenewStatus": 0,
"commitmentRenewalDate": 1812447660000,
"commitmentRenewalPrice": 10990,
"commitmentRenewalBillingPlanType": "BILLED_UPFRONT"
}
}
关键点:
commitmentAutoRenewStatus为 0 表示用户设置了承诺期结束后不续订commitmentRenewalBillingPlanType表示承诺期结束后的续订方案类型- 这个例子中用户选择在承诺期结束后转为一次性预付的年度订阅
commitmentInfo只在当前订阅处于承诺期时才会出现在 renewal info 中
优惠码兑换 Sheet
(09:58)
struct OfferCodeRedemption: View {
@State var presentingOfferCodeSheet: Bool = false
var body: some View {
Button("Redeem Offer Code") {
presentingOfferCodeSheet = true
}
.offerCodeRedemption(options: [], isPresented: $presentingOfferCodeSheet) { result in
switch result {
case .success(let verificationResult):
switch verificationResult {
// Verify the transaction, give the customer access to
// the purchased content, and then finish the transaction
}
case .failure(let error):
// Handle error
}
}
}
}
关键点:
.offerCodeRedemption现在返回VerificationResult,兑换结果明确可追踪options参数接受RedeemOption值数组,用于配置兑换行为- 兑换成功时
verificationResult中包含 transaction 对象 - UIKit 中使用
presentOfferCodeRedeemSheet实现相同功能
核心启发
为订阅产品添加按月承诺方案
做什么:为现有的年度订阅产品配置 12 个月承诺期的按月付费选项,并在 App 中优先展示。
为什么值得做:降低用户的首次付费门槛,同时锁定 12 个月的订阅收入。对于价格敏感型用户,月供金额比年度总价更容易接受。
怎么开始:在 App Store Connect 中找到现有的一年期自动续订订阅,设置 “monthly with a 12-month commitment” 可用性。在代码中用 .preferredSubscriptionPricingTerms 筛选 .monthly 方案并优先展示。
构建承诺期进度追踪 UI
做什么:在 App 的账户或订阅管理页面中,展示用户当前处于承诺期的第几个月、还剩多少期。
为什么值得做:透明度提升用户信任,减少”我不知道签了 12 个月”的客诉。同时可以帮助用户在承诺期结束前做出续订决策。
怎么开始:从 Transaction.currentEntitlements 获取最新交易,读取 commitmentInfo 字段,用 billingPeriodNumber 和 totalBillingPeriods 计算进度并展示。
升级优惠码兑换逻辑
做什么:将现有的优惠码兑换调用点迁移到新的 API,获得明确的兑换结果回调。
为什么值得做:旧 API 兑换完成后没有直接结果,需要依赖 Transaction.updates 异步监听,实现复杂且容易出错。新 API 直接返回成功或失败。
怎么开始:搜索代码中的 presentOfferCodeRedeemSheet 调用,替换为带 VerificationResult 回调的新版本。在 Xcode 27 的 StoreKit Testing 中测试兑换流程。
统一审核提交流程
做什么:将 IAP 审核提交纳入统一的 reviewSubmissions 工作流,和 App 二进制文件、In-App Events 一起打包提交。
为什么值得做:避免”App 已上架但 IAP 还在审核中”的尴尬情况。统一提交意味着所有审核项一起过审或一起被拒,状态完全同步。
怎么开始:检查现有的 CI/CD 脚本,将旧的 IAP 专属提交 API 调用迁移到 reviewSubmissions 和 reviewSubmissionItems 资源。
准备订阅 Bundles 和 Suites
做什么:如果你有多个 App 或多种订阅产品,提前规划订阅 Bundle 或 Suite 的产品结构。
为什么值得做:Bundle 将多个可单独购买的订阅打包以优惠价格销售,Suite 将仅作为整体存在的订阅组提供给一套相关 App。两者都能提升订阅收入。
怎么开始:在 Xcode 27 中测试 Bundles 和 Suites 的 API,关注 Apple 下半年公布的商业化细节。
关联 Session
- What’s new in StoreKit 2 and StoreKit Testing in Xcode — StoreKit 2 的新功能和 Xcode 中的测试最佳实践
- Explore Retention Messaging in App Store Connect — 服务器到服务器的留存消息 API,支持 12 个月承诺期订阅的精准挽留
- What’s New in App Store Connect — 审核提交工作流的深入解析
- Implement App Store Offers — 优惠码和订阅优惠的配置与实现
评论
GitHub Issues · utterances