StoreKit 2: How to use .subscriptionStatusTask modifier to know which subscription in a subscription group is purchased/active?

I have another question about auto-renewable subscriptions. I am currently trying to implement In-App purchase subscription choices (one monthly and one yearly; both are in the same subscription group) to my app using SubscriptionStoreView and the modifiers .onInAppPurchaseCompletion, .subscriptionStatusTask, and .manageSubscriptionSheet. I do NOT offer any other type of In-App purchases and will not be in the future.

This question specifically deals with using .subscriptionStatusTask. Is there a way in this closure to know exactly which subscription has been purchased? I thought I figured this out by looking at the value returned, mapping it, and then looking at transaction payloadValue but I don’t think that this is necessarily correct. For example, if I buy the monthly subscription and then immediately upgrade and buy the yearly, the transaction.payloadValue.productID still shows monthly (presumably because the monthly subscription must finish first?). My app needs to know if the user actually purchased yearly because even more options are available to them if they did. How/where can I see this just using .subscriptionStatusTask?

Below is some sample code that I hastily threw together. It has basic logic and comments/questions for stuff I’m trying to figure out.

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()
}

}

Note: When I purchase a monthly subscription and then immediately purchase the yearly (via .manageSubscriptionSheet), the var prodId that I get back is still showing a monthly subscription. When I look at Debug -> StoreKit -> Manage Transactions, it shows that the subscription is “monthly”, that it will expire 9-7-24, and that a yearly subscription will renew. However, if I click on my manage subscription button again, it shows a yearly subscription. So, how can I see in .subscriptionStatusTask where I actually purchased a yearly subscription?

Also, if I then cancel the yearly subscription from the .manageSubscriptionSheet, it shows a message that says, “if you confirm and end your subscription now, you can still access it until Sept 7, 2024. Why 2024? Shouldn’t this be 2025? Did I already actually “pay” for a year or is this payment delayed until the monthly runs out? If I actually confirm the cancel, Debug -> StoreKit -> Manage Transactions shows they still have a monthly subscription but that now the subscription (monthly or yearly) will NOT renew.

Question: So, when a user changes subscriptions via .manageSubscriptionSheet, are the actual purchases immediate? I’m kind of thinking they are not, at least in this particular scenario. Which means that if a user buys the monthly option first and then initiates a yearly purchase also, that I have to have my code look at renewal info also (which I’m not doing here), grant them yearly access features based on that, hope that they don’t cancel that subscription, and drop them back down to monthly features if they do cancel the yearly renewal. Correct?

What else am I missing and/or am I not understanding correctly? As always, any help would be greatly appreciated.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật