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

基于StoreKit 2应用交易的商业模式变更生产环境异常求助

App Store生产环境下商业模式变更逻辑异常:所有用户被要求订阅

我按照苹果官方文档指引在应用主视图实现了商业模式变更逻辑,该逻辑在模拟器、物理设备及TestFlight测试环境均运行正常,但发布至App Store生产环境后出现异常——所有新老用户都被要求订阅。测试环境能正常获取交易信息并输出日志,但生产环境无法查看控制台日志,也无法正常获取内容。

沙箱收据信息

AppTransaction.shared obtained: {
  "applicationVersion" : "1",
  "bundleId" : *****
  "deviceVerification" : "6M0Nnw14nSEOBVTPE\\/\\/EfnWSwLm7LFSlrpFEwxgH74SBHp5dSzBEm896Uvo42mwr",
  "deviceVerificationNonce" : "8a8238c0-0aee-41e6-bfb0-1cfc52b70fb6",
  "originalApplicationVersion" : "1.0",
  "originalPurchaseDate" : 1375340400000,
  "receiptCreationDate" : 1737577840917,
  "receiptType" : "Sandbox",
  "requestDate" : 1737577840917
}

测试环境验证日志

New business model change: 1.7
Original version components: ["1", "0"]
Major version: 1, Minor version: 0
This user is premium. Original version: 1.0

核心逻辑代码

.task {
    do {
        let shared = try await AppTransaction.shared
        if case .verified(let appTransaction) = shared {
            let newBusinessModelVersion = (1, 7) // Represented as (major, minor)
            let versionComponents = appTransaction.originalAppVersion.split(separator: ".")
            if let majorVersion = versionComponents.first.flatMap({ Int($0) }),
               let minorVersion = versionComponents.dropFirst().first.flatMap({ Int($0) }) {
                if (majorVersion, minorVersion) < newBusinessModelVersion {
                    self.premiumStatus.isPremium = true
                    isPremium = true    
                } else {
                  
                    let customerInfo = try await Purchases.shared.customerInfo()
                    self.premiumStatus.isPremium = customerInfo.entitlements["premium"]?.isActive == true
                    isPremium = self.premiumStatus.isPremium
                }
            } else {
                print("Error: obtaining version components")
            }
        } else {
            print("Not verified")
        }
    } catch {
        print("Error processing transaction: \(error.localizedDescription)")
    }
}

问题分析

从测试数据来看,沙箱环境中originalAppVersion为1.0,能正确解析版本号并判定老用户为Premium。生产环境异常的可能原因:

  1. 生产环境originalAppVersion格式不符合预期
    代码依赖版本号按.分割为主、次版本,但生产环境中该字段可能是纯数字(如1)或其他格式,导致解析失败进入else分支,进而调用订阅检查逻辑,老用户因无订阅记录被判定为非Premium。

  2. AppTransaction生产环境验证失败
    生产环境中AppTransaction.shared可能返回.unverified,导致代码跳过Premium判定逻辑,默认用户无权限。

  3. 版本比较逻辑的硬编码风险
    新商业模式版本硬编码为(1,7),若生产环境中老用户的originalAppVersion等于或高于该版本,会进入订阅检查分支,而老用户无订阅则被要求订阅。

解决方案

1. 增加版本解析容错处理

修改版本解析逻辑,当无法获取次版本时默认设为0,避免因格式问题导致逻辑走偏:

let versionComponents = appTransaction.originalAppVersion.split(separator: ".")
let majorVersion = versionComponents.first.flatMap(Int.init) ?? 0
let minorVersion = versionComponents.dropFirst().first.flatMap(Int.init) ?? 0

2. 集成生产环境日志上报

由于生产环境无法查看控制台日志,接入第三方日志工具(如Firebase Crashlytics、Sentry),上报关键节点信息:

if case .verified(let appTransaction) = shared {
    // 上报原始版本号
    Crashlytics.crashlytics().log("Original app version: \(appTransaction.originalAppVersion)")
    let versionComponents = appTransaction.originalAppVersion.split(separator: ".")
    let majorVersion = versionComponents.first.flatMap(Int.init) ?? 0
    let minorVersion = versionComponents.dropFirst().first.flatMap(Int.init) ?? 0
    Crashlytics.crashlytics().log("Parsed version: \(majorVersion).\(minorVersion)")
    // ... 后续逻辑
} else {
    Crashlytics.crashlytics().log("AppTransaction verification failed")
}

3. 添加兜底逻辑保护老用户

当版本解析失败或验证失败时,默认赋予老用户Premium权限,避免影响正常使用:

} else {
    // 版本解析失败,默认老用户为Premium
    self.premiumStatus.isPremium = true
    isPremium = true
    Crashlytics.crashlytics().log("Version parsing failed, fallback to premium")
}

4. 确认生产环境originalAppVersion格式

通过日志上报或用户反馈,确认生产环境中originalAppVersion的实际格式,确保版本解析逻辑覆盖所有可能情况。

5. 检查订阅SDK生产环境配置

确认Purchases SDK(如RevenueCat)的生产环境API密钥是否正确,避免因配置错误导致订阅状态获取失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 20:55:55