-->
从iOS17、macOS14开始,苹果使用了新版的StoreKit 2来处理应用内购买和订阅。相比之前的StoreKit,StoreKit 2提供了更简洁和强大的API,简化了开发者的工作流程。
StoreKit 2引入了SubscriptionStoreView
,这是一个预构建的视图组件,可以轻松地集成到应用中,展示订阅选项和处理购买流程。现在想要展示一个订阅界面,只需要几行代码就能实现。我用 【便便时刻!】 的订阅项做一个演示:
struct PurchaseViewDemo: View {
let lifetimeProduct = "lifetimeProduct"
let subscriptionProduct = "subscriptionProduct"
var body: some View {
SubscriptionStoreView(productIDs: [lifetimeProduct, subscriptionProduct])
}
}
可以看到,
SubscriptionStoreView
只需要传入一个产品ID数组,就能自动处理展示和购买逻辑,非常方便。但是有一个问题,他只能处理订阅和一次性购买的产品,不能处理消耗型和非消耗性产品。比如永久会员这类的,可以看到上图中的 【便便时刻!】 的终身会员是无法通过SubscriptionStoreView
来处理的。下期我会用StoreView
来处理这类产品。
所有的app内购项目,都必须有一个恢复购买的按钮,还有隐私协议和服务条款的链接。SubscriptionStoreView
提供了修饰符来直接显示这几个常见元素:
struct PurchaseViewDemo: View {
let lifetimeProduct = "lifetimeProduct"
let subscriptionProduct = "subscriptionProduct"
var body: some View {
SubscriptionStoreView(productIDs: [lifetimeProduct, subscriptionProduct])
.storeButton(.visible, for: .restorePurchases, .policies)
}
}
使用官方的
.storeButton
修饰符,简简单单就能添加恢复购买和隐私政策按钮。这个修饰符接受一个StoreButtonKind
类型的参数,表示按钮的类型。鼠标选中.restorePurchases
按下command + click
可以查看官方文档,一共有五种样式。
如果有多个订阅项,那么他默认的样式会发生改变。由于【便便时刻!】只有一个年度会员,所以我用本地的Storekit做演示。这里使用订阅组来展示,可以不用单独一个个写产品ID,他会自动处理订阅组中的所有产品。
struct PurchaseViewDemo: View {
let lifetimeProduct = "lifetimeProduct"
let subscriptionProduct = "subscriptionProduct"
let subscriptionProduct2 = "subscriptionProduct Month"
let subscriptionGroup = "subscriptionGroup"
var body: some View {
// SubscriptionStoreView(productIDs: [subscriptionProduct, subscriptionProduct2]) 同样的效果
SubscriptionStoreView(groupID: subscriptionGroup)
.storeButton(.visible, for: .restorePurchases, .policies)
// 控制订阅按钮的样式
.subscriptionStoreButtonLabel(.multiline)
}
}
可以看到,多个订阅项出现时,
SubscriptionStoreView
会自动处理订阅组的展示。你只需要传入订阅组ID或者多个产品ID,它就会帮你处理好。并且和单独一个订阅时的模式样式不同,会显示简介和价格等信息。使用.subscriptionStoreButtonLabel(.multiline)
修饰符,可以将订阅按钮的标签设置为多行显示,还有.singleLine
等样式可选。
现在想要使用SubscriptionStoreView
来处理购买流程,也很简单,同样提供了修饰符来处理。
struct PurchaseViewDemo: View {
let lifetimeProduct = "lifetimeProduct"
let subscriptionProduct = "subscriptionProduct"
let subscriptionProduct2 = "subscriptionProduct Month"
let subscriptionGroup = "subscriptionGroup"
var body: some View {
// SubscriptionStoreView(productIDs: [subscriptionProduct, subscriptionProduct2]) 同样的效果
SubscriptionStoreView(groupID: subscriptionGroup)
.storeButton(.visible, for: .restorePurchases, .policies)
// 控制订阅按钮的样式
.subscriptionStoreButtonLabel(.multiline)
.onInAppPurchaseStart { product in
print("onInAppPurchaseStart 执行 \(product.displayName)")
}
.onInAppPurchaseCompletion { product, result in
print("onInAppPurchaseCompletion 执行 \(product.displayName)")
switch result {
case .success(.pending):
print("购买被挂起")
case .success(.userCancelled):
print("用户取消购买")
case .success(.success(let res)):
print(res)
print("购买成功 ")
case .success:
print("success")
case .failure:
print("failure")
}
}
}
}
当选中一个订阅项并按下时,触发 .onInAppPurchaseStart
按下可以看到控制打印 onInAppPurchaseStart 执行 月会员
。当购买完成后,触发 .onInAppPurchaseCompletion
并执行代码,可以根据结果来判断购买是否成功。
onInAppPurchaseStart 执行 月会员
onInAppPurchaseCompletion 执行 月会员
用户取消购买
onInAppPurchaseStart 执行 月会员
onInAppPurchaseCompletion 执行 月会员
{
"header" : {...},
"payload" : {...},
"signature" : "64 bytes (verified)"
}
购买成功
case .success(.success(let res)):
这个结果是购买成功后的详细信息,可以根据需要进行处理。比如再次验证是否有效、获取购买项详细信息、更新UI等。这里只是展示一下,使用新版的StoreKit 2来处理购买流程是多么简单。