StoreKit 2:如何使用 .subscriptionStatusTask 修饰符来了解订阅组中的哪个订阅已购买/活动?

问题描述 投票:0回答:1

我还有一个关于自动续订订阅的问题。我目前正在尝试使用 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 更改订阅时,实际购买是否会立即生效?我认为他们不是,至少在这个特定的场景中。这意味着,如果用户首先购买每月选项,然后也启动每年购买,我还必须让我的代码查看续订信息(我在这里没有这样做),并据此授予他们每年访问功能,希望他们不要取消订阅,如果取消每年续订,请将其降回每月功能。正确吗?

我还遗漏了什么和/或我理解不正确吗?一如既往,任何帮助将不胜感激。

ios swiftui in-app-purchase subscription storekit
1个回答
0
投票

听起来你们的两个订阅级别的周期不同,但排名相同。

由于您的包年订阅比包月订阅提供更多福利,因此您需要确保您给予包年订阅的排名高于包月订阅。例如,您的年度订阅的排名可能为 1,而您的每月订阅的排名可能为 2。

Apple 开发者文档解释了当用户从订阅组中选择不同的订阅时会发生什么:

升级。 有人购买了比当前订阅提供更高级别服务的订阅。他们会立即升级并收到按比例退款的原始订阅金额。如果您希望人们立即访问更多内容或功能,请将订阅排名更高以使其升级。

降级。 有人选择的订阅提供的服务级别低于当前订阅。订阅将持续到下一个续订日期,然后以较低的级别和价格续订。

跨级。有人切换到同等级别的新订阅。如果订阅的持续时间相同,则新订阅立即开始。如果持续时间不同,新订阅将在下一个续订日期生效。

由于您的订阅具有相同的排名,因此商店将此次更改视为跨等级。

如果您的年度订阅排名较高,那么商店将处理升级,新订阅立即生效。

© www.soinside.com 2019 - 2024. All rights reserved.