You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift StoreKit2:如何判断用户订阅了哪项订阅产品?

优化StoreKit2获取当前订阅产品的实现方式

你的当前实现已经能获取到订阅产品ID,但可以从有效性校验、结果准确性和可维护性三个方向优化:


1. 过滤活跃的有效订阅

Transaction.currentEntitlements会返回所有当前用户有权限的交易,但其中可能包含已过期、已取消的订阅(测试环境中这类情况更常见)。需要先校验交易的活跃状态,确保拿到的是当前有效的订阅:

func currentActiveSubscriptionProductID() async -> String? {
    var activeTransactions: [Transaction] = []
    
    for await result in Transaction.currentEntitlements {
        guard case .verified(let transaction) = result else {
            continue
        }
        // 校验订阅是否处于活跃状态:未被撤销、未过期
        guard transaction.revocationDate == nil, 
              let expirationDate = transaction.expirationDate, 
              expirationDate > Date() else {
            continue
        }
        activeTransactions.append(transaction)
    }
    
    // 同一订阅组内仅存在一个有效订阅,取最新的交易记录
    return activeTransactions.sorted { $0.purchaseDate > $1.purchaseDate }.first?.productID
}

2. 避免硬编码产品ID的维护问题

硬编码产品ID会增加后期迭代的维护成本,建议统一管理:

  • 将产品ID存入单独的配置文件(比如SubscriptionConstants.swift):
    enum SubscriptionProductID {
        static let basic = "com.yourapp.sub.basic"
        static let premium = "com.yourapp.sub.premium"
        static let family = "com.yourapp.sub.family"
    }
    
  • 如果需要展示订阅名称、价格等信息,可以提前通过Product.products(for:)获取产品详情,关联产品ID与展示数据:
    func fetchSubscriptionProducts() async -> [Product]? {
        do {
            return try await Product.products(for: [
                SubscriptionProductID.basic,
                SubscriptionProductID.premium,
                SubscriptionProductID.family
            ])
        } catch {
            print("获取产品列表失败: \(error)")
            return nil
        }
    }
    

3. 结合RevenueCat简化实现

既然你已经参考RevenueCat的教程实现了PurchaseManager,完全可以利用其封装好的API直接获取当前订阅状态,无需手动处理StoreKit底层逻辑:

import RevenueCat

func fetchCurrentSubscription() async -> String? {
    let customerInfo = try? await Purchases.shared.customerInfo()
    // 获取当前活跃的订阅权限(对应你在RevenueCat后台配置的Entitlement)
    guard let entitlement = customerInfo?.entitlements.active.values.first else {
        return nil
    }
    // 返回订阅对应的产品ID
    return entitlement.productIdentifier
}

这种方式会自动处理订阅升级/降级、过期、退款等复杂场景,比手动处理StoreKit交易更可靠。


内容的提问来源于stack exchange,提问作者Kyra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 00:12:51