我还有一个关于自动续订订阅的问题。我目前正在尝试使用 SubscriptionStoreView 和修饰符 .onInAppPurchaseCompletion、.subscriptionStatusTask 和 .manageSubscriptionSheet 在我的应用程序中实现应用内购买订阅选项(每月一次和每年一次;两者都在同一订阅组中)。我不提供任何其他类型的应用内购买,将来也不会提供。
这个问题专门涉及使用 .subscriptionStatusTask。 在这个闭包中是否有方法可以准确地知道已购买哪个订阅?我认为我是通过查看返回的值、映射它,然后查看事务有效负载值来解决这个问题的,但我认为这不一定是正确的。例如,如果我购买按月订阅,然后立即升级并购买按年订阅,则 transaction.payloadValue.productID 仍然显示每月(大概是因为每月订阅必须先完成?)。我的应用程序需要知道用户是否确实每年购买,因为如果他们这样做,他们可以使用更多选项。我如何/在哪里可以仅使用 .subscriptionStatusTask 看到这个?
下面是我匆忙拼凑的一些示例代码。它有我想要弄清楚的基本逻辑和评论/问题。
struct ContentViewSO2: View {
@State private var paywallShown = false
@State private var isPro = false
@State private var presentingSubscriptionSheet = false
@State private var showManageSubscriptionButton = false
@State private var subType = ""
var body: some View {
VStack(spacing: 75){
Text("Testing Store Paywall and Subscription Status Sheet")
.multilineTextAlignment(.center)
.foregroundColor(.black)
.font(.system(size: 18, weight: .heavy, design: .rounded))
.padding(.vertical, 75)
.subscriptionStatusTask(for: "C5FF4E1D") { taskState in
if let value = taskState.value {
//.. check to see if there was EVER a subscription in order to know whether or not to present the .manageSubscriptionSheet. It seems that if there was never a subscription, the .manageSubscriptionSheet will not appear... it just clocks
if value.count > 0 {
showManageSubscriptionButton = true
} else {
showManageSubscriptionButton = false
}
let _: [()] = value.map { status in
//.. transaction = what's currently purchased???????
let statusTransaction = status.transaction
let payloadValue = try? status.transaction.payloadValue
let prodId = payloadValue?.productID
print("product id = \(prodId)")
if prodId == "com.HR.test.yearly" {
subType = "yearly"
} else if prodId == "com.HR.test.monthly" {
subType = "monthly"
} else {
subType = "none"
}
//.. if there is a value that's not .revoked and not .expired
isPro = !value
.filter { $0.state != .revoked && $0.state != .expired }
.isEmpty
//.. for more debugging
let renewalState = status.state
switch renewalState {
case .revoked:
print("renewalState = revoked")
case .expired:
print("renewalState = expired")
case .subscribed:
print("renewalState = subscribed")
case .inBillingRetryPeriod:
print("renewalState = inBillingRetryPeriod")
case .inGracePeriod:
print("renewalState = inGracePeriod")
default:
print("renewalState = ???")
}
}
}
}
isPro ?
Text("IS PRO FROM .subscriptionStatusTask")
.foregroundColor(.white)
.background(Color.green)
:
Text("IS NOT PRO FROM .subscriptionStatusTask")
.foregroundColor(.white)
.background(Color.red)
switch subType {
case "monthly":
Text("Monthly Subscription")
.padding(.horizontal, 25)
.foregroundColor(.white)
.background(Color.blue)
case "yearly":
Text("Yearly Subscription")
.padding(.horizontal, 25)
.foregroundColor(.white)
.background(Color.teal)
default:
Text("No Subscription")
.padding(.horizontal, 25)
.foregroundColor(.white)
.background(Color.red)
}
//.. check to see if there was EVER a subscription in order to know whether to present the .manageSubscriptionSheet. It seems that if there was never a subscription, the .manageSubscriptionSheet will not appear... it just clocks. If there has not been any subscription EVER, show paywall instead of manage subscription sheet
if !showManageSubscriptionButton {
Button(action: {
paywallShown = true
}, label: {
Text("Press to test paywall")
})
.buttonStyle(.borderedProminent)
.sheet(isPresented: $paywallShown) {
HRShop()
}
} else {
Button(action: {
self.presentingSubscriptionSheet = true
}, label: {
Text("Show .manageSubScriptionSheet")
})
.manageSubscriptionsSheet(
isPresented: $presentingSubscriptionSheet,
subscriptionGroupID: "C5FF4E1D"
)
}
}
Spacer()
}
}
注意:当我购买按月订阅,然后立即购买按年订阅(通过 .manageSubscriptionSheet)时,我得到的 var prodId 仍然显示按月订阅。当我查看“调试”->“StoreKit”->“管理事务”时,它显示订阅是“每月”,将于 24 年 9 月 7 日到期,并且每年订阅将续订。但是,如果我再次单击“管理订阅”按钮,它会显示按年订阅。那么,如何在 .subscriptionStatusTask 中查看我实际购买了年度订阅的位置?
此外,如果我随后从 .manageSubscriptionSheet 取消年度订阅,它会显示一条消息:“如果您现在确认并结束订阅,您仍然可以在 2024 年 9 月 7 日之前访问它。为什么是 2024 年?这不应该吗?”是 2025 年吗?我是否已经实际“支付”了一年的费用,或者这笔付款是否延迟到每月用完为止?如果我确实确认取消,“调试”->“StoreKit”->“管理交易”显示他们仍然有每月订阅,但现在订阅(按月或按年)将不会续订。
问题:那么,当用户通过 .manageSubscriptionSheet 更改订阅时,实际购买是否会立即生效?我认为他们不是,至少在这个特定的场景中。这意味着,如果用户首先购买每月选项,然后也启动每年购买,我还必须让我的代码查看续订信息(我在这里没有这样做),并据此授予他们每年访问功能,希望他们不要取消订阅,如果取消每年续订,请将其降回每月功能。正确吗?
我还遗漏了什么和/或我理解不正确吗?一如既往,任何帮助将不胜感激。
听起来你们的两个订阅级别的周期不同,但排名相同。
由于您的包年订阅比包月订阅提供更多福利,因此您需要确保您给予包年订阅的排名高于包月订阅。例如,您的年度订阅的排名可能为 1,而您的每月订阅的排名可能为 2。
Apple 开发者文档解释了当用户从订阅组中选择不同的订阅时会发生什么:
升级。 有人购买了比当前订阅提供更高级别服务的订阅。他们会立即升级并收到按比例退款的原始订阅金额。如果您希望人们立即访问更多内容或功能,请将订阅排名更高以使其升级。
降级。 有人选择的订阅提供的服务级别低于当前订阅。订阅将持续到下一个续订日期,然后以较低的级别和价格续订。
跨级。有人切换到同等级别的新订阅。如果订阅的持续时间相同,则新订阅立即开始。如果持续时间不同,新订阅将在下一个续订日期生效。
由于您的订阅具有相同的排名,因此商店将此次更改视为跨等级。
如果您的年度订阅排名较高,那么商店将处理升级,新订阅立即生效。