ios 我可以从Superwall和RevenueCat的“PaywallDelegate”扩展中检查用户订阅变量Bool吗?

lx0bsm1f  于 2022-12-15  发布在  iOS
关注(0)|答案(1)|浏览(226)

我正在Swift中集成Superwall和RevenueCat。我决定使用Superwall,因为它易于配置和设置,但实际上我很难有条件地仅向未订阅该平台的用户呈现付费墙。如果用户正确订阅,是否有专业的方式来签入(isUserSubscribed)?

extension PaywallService: PaywallDelegate {
   
    
  // 1
  func purchase(product: SKProduct) {
    Task {
      do {
        let result = try await Purchases.shared.purchase(product: StoreProduct(sk1Product: product))
        // React to the purchase here
          
        print(result)
      } catch {
        // Handle purchase error here
      }
    }
  }

  // 2
  func restorePurchases(completion: @escaping (Bool) -> Void) {
    Task {
      do {
        let purchaserInfo = try await Purchases.shared.restorePurchases()
        
        // check purchaserInfo to see if subscription "MyEntitlement" is now active
        let restored = purchaserInfo.entitlements.all["subPlan"]?.isActive == true
        
        completion(restored)
      } catch {
        completion(false)
      }
    }
  }

    
    
    
  // 3
    func **isUserSubscribed**()  -> Bool {
    // TODO: I need to check here if the user is correctly subscribed, but this first run always gives false and the user is ALWAYS getting the paywall. 
       
        
        var isSub:Bool = false
        Purchases.shared.getCustomerInfo  { purchaserInfo, error in
                    // access latest purchaserInfo
                    
            if (purchaserInfo?.entitlements.all["subPlan"]?.isActive == true) {
                isSub = purchaserInfo?.entitlements.all["subPlan"]?.isActive == true
                

            } else {
                isSub = false
            }
                
                }
          
        return isSub
        
    
    }
}

非常感谢!
我的第一次运行总是给假的,用户总是得到付费墙。

ryhaxcpt

ryhaxcpt1#

问题是Purchases.shared.getCustomerInfo有一个异步的完成块,这意味着isSub的值在完成块有机会更新isSub之前立即返回,这就是为什么它总是false
要同时管理RevenueCat和Superwall,我们建议您创建一个名为PaywallManager.swift的类来处理这一切(请记住替换您的API密钥):

import Paywall
import RevenueCat
import StoreKit

final class PaywallManager: NSObject {
  static let shared = PaywallManager()
  var isSubscribed = false

  #warning("Replace these with your API keys:")
  private static let revenueCatApiKey = "YOUR_REVENUECAT_PUBLIC_API_KEY"
  private static let superwallApiKey = "YOUR_SUPERWALL_PUBLIC_API_KEY"

  private let proEntitlement = "subPlan"

  /// Configures both the RevenueCat and Superwall SDKs.
  ///
  /// Call this on `application(_:didFinishLaunchingWithOptions:)`
  static func configure() {
    Purchases.configure(withAPIKey: revenueCatApiKey)
    Purchases.shared.delegate = shared

    Paywall.configure(
      apiKey: superwallApiKey,
      delegate: shared
    )
  }

  /// Logs the user in to both RevenueCat and Superwall with the specified `userId`.
  ///
  /// Call this when you retrieve a userId.
  static func logIn(userId: String) async {
    do {
      let (customerInfo, _) = try await Purchases.shared.logIn(userId)
      shared.updateSubscriptionStatus(using: customerInfo)

      Paywall.identify(userId: userId)
    } catch {
      print("A RevenueCat error occurred", error)
    }
  }

  /// Logs the user out of RevenueCat and Superwall.
  ///
  /// Call this when your user logs out.
  func logOut() async {
    do {
      let customerInfo = try await Purchases.shared.logOut()
      updateSubscriptionStatus(using: customerInfo)
      Paywall.reset()
    } catch {
      print("A RevenueCat error occurred", error)
    }
  }

  /// Handles a deep link to open a paywall preview.
  ///
  /// [See here](https://docs.superwall.com/docs/in-app-paywall-previews#handling-deep-links)
  /// for information on how to call this function in your app.
  static func handleDeepLink(_ url: URL) {
    Paywall.handleDeepLink(url)
  }
}

// MARK: - Purchases Delegate
extension PaywallManager: PurchasesDelegate {
  /// Handles updated CustomerInfo received from RevenueCat.
  func purchases(_ purchases: Purchases, receivedUpdated customerInfo: CustomerInfo) {
    updateSubscriptionStatus(using: customerInfo)
  }

  /// Updates the subscription status in response to customer info received from RevenueCat.
  private func updateSubscriptionStatus(using customerInfo: CustomerInfo) {
    isSubscribed = customerInfo.entitlements.active[proEntitlement] != nil
  }

  /// Restores purchases and updates subscription status.
  ///
  /// - Returns: A boolean indicating whether the user restored a purchase or not.
  private func restore() async -> Bool {
    do {
      let customerInfo = try await Purchases.shared.restorePurchases()
      updateSubscriptionStatus(using: customerInfo)
      return customerInfo.entitlements.active[proEntitlement] != nil
    } catch {
      return false
    }
  }

  /// Purchases a product with RevenueCat.
  ///
  /// - Returns: A boolean indicating whether the user cancelled or not.
  private func purchase(_ product: SKProduct) async {
    let storeProduct = StoreProduct(sk1Product: product)
    do {
      let (_, customerInfo, _) = try await Purchases.shared.purchase(product: storeProduct)
      updateSubscriptionStatus(using: customerInfo)
    } catch {
      print("An error occurred purchasing", error)
    }
  }
}

// MARK: - Paywall Delegate
extension PaywallManager: PaywallDelegate {
  /// Purchase a product from a paywall.
  func purchase(product: SKProduct) {
    Task {
      await purchase(product)
    }
  }

  func restorePurchases(completion: @escaping (Bool) -> Void) {
    Task {
      let isRestored = await restore()
      completion(isRestored)
    }
  }

  /// Lets Superwall know whether the user is subscribed or not.
  func isUserSubscribed() -> Bool {
    return isSubscribed
  }
}

在AppDelegate中调用此函数:

func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
  PaywallManager.configure()
}

它的作用是在配置Paywall之前先配置和设置Purchases的委托。当它这样做时,委托函数purchases(_:,receivedUpdated:)接收到一个包含最新CustomerInfo的回调。从那里,它在调用isUserSubscribed()之前确定和存储用户的订阅状态。
请注意,对于全新安装的应用程序,如果您有session_start触发器,则在RevenueCat有机会更新订阅状态之前仍将调用isUserSubscribed(),因为RevenueCat正在从在线检索客户信息。对于后续打开的应用程序,用户订阅状态将是正确的。我们将在应用程序的下一次重大更新中修复此问题,但是,除非有订阅的用户正在重新下载应用程序,否则你应该没问题。

相关问题