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

如何在RevenueCat SwiftUI中阻止跨账号的权益转移与恢复?

解决RevenueCat订阅权益跨账号转移问题(Keep with original app user id方案实现)

核心逻辑

这个方案的本质是让订阅权益和你的应用用户ID绑定,而非设备ID。必须确保用户完成注册/登录后,再将RevenueCat的用户体系和你的应用用户体系关联,彻底切断订阅与设备的绑定关系。

具体实现步骤

1. 初始化RevenueCat(启动时)

启动App时仅初始化RevenueCat,暂不绑定用户ID,使用默认的匿名ID:

// App启动时调用(比如在AppDelegate或SceneDelegate)
Purchases.configure(withAPIKey: "你的RevenueCat API密钥")

2. 用户登录/注册后绑定用户ID

用户完成账号验证后,立即调用RevenueCat的logIn方法,将你的应用用户ID和RevenueCat用户ID绑定:

func onUserLoginSuccess(userId: String) {
    Purchases.shared.logIn(userId) { customerInfo, isNewUser, error in
        if let error = error {
            print("RevenueCat账号绑定失败: \(error.localizedDescription)")
            return
        }
        
        // 根据绑定后的订阅状态更新本地UI
        let hasActiveSubscription = customerInfo?.entitlements.all["All Access"]?.isActive == true
        authViewModel.isActive = hasActiveSubscription
        authViewModel.updateSubscriptionStatus(status: hasActiveSubscription)
    }
}

3. 调整购买逻辑(强制登录后购买)

修改你的购买代码,确保只有已登录的用户才能发起购买,这样订阅会直接绑定到当前登录的用户ID:

// 确保调用此方法前,用户已经完成登录
Purchases.shared.purchase(package: pkg) { transaction, customerInfo, error, userCancelled in
    if userCancelled {
        print("用户取消了交易")
        return
    }
    
    if let error = error {
        print("交易出错: \(error.localizedDescription)")
        self.isSpinningViewShown = false
        return
    }
    
    guard let customerInfo = customerInfo else {
        print("未获取到用户订阅信息")
        self.isSpinningViewShown = false
        return
    }
    
    if customerInfo.entitlements.all["All Access"]?.isActive == true {
        print("账号已激活")
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
            self.authViewModel.isActive = true
            self.authViewModel.updateSubscriptionStatus(status: true)
        }
    } else {
        print("用户无有效订阅")
        self.isSpinningViewShown = false
    }
}

4. 用户登出时重置RevenueCat状态

用户登出时,调用logOut方法让RevenueCat回到匿名状态,避免下一个登录的用户关联到之前的订阅:

func onUserLogout() {
    Purchases.shared.logOut { customerInfo, error in
        if let error = error {
            print("RevenueCat登出失败: \(error.localizedDescription)")
            return
        }
        // 重置本地订阅状态
        authViewModel.isActive = false
        authViewModel.updateSubscriptionStatus(status: false)
    }
}

关键注意事项

  • 强制先登录再购买:在前端拦截未登录用户的购买入口,确保订阅从一开始就绑定到正确的用户ID。
  • 避免匿名购买:如果用户在未登录时误操作购买,后续只能通过RevenueCat后台手动转移订阅,无法自动关联到用户账号。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 09:27:49