Untitled
unknown
swift
2 years ago
3.9 kB
7
Indexable
final class PaywallManager: NSObject { static let shared = PaywallManager() var isSubscribed: Bool { switch Superwall.shared.subscriptionStatus { case .active: return true default: return false } } /// Configures both the RevenueCat and Superwall SDKs. /// /// Call this on `application(_:didFinishLaunchingWithOptions:)` static func configure() { Superwall.configure( apiKey: Constants.superwallApiKey, purchaseController: shared ) Purchases.configure(withAPIKey: Constants.revenueCatApiKey) Superwall.shared.logLevel = .error Purchases.logLevel = .error syncSubscriptionStatus() } /// Handles a deep link to open a paywall preview. /// /// [See here](https://docs.superwall.com/v3.0/docs/in-app-paywall-previews#handling-deep-links) /// for information on how to call this function in your app. static func handleDeepLink(_ url: URL) { Superwall.shared.handleDeepLink(url) } /// Updates the subscription status in response to customer info received from RevenueCat. private func updateSubscriptionStatus(using customerInfo: CustomerInfo) { if customerInfo.entitlements.active.isEmpty { #if DEBUG Superwall.shared.subscriptionStatus = .active #else Superwall.shared.subscriptionStatus = .inactive #endif } else { Superwall.shared.subscriptionStatus = .active } } // MARK: Sync Subscription Status /// Makes sure that Superwall knows the customers subscription status by /// changing `Superwall.shared.subscriptionStatus` static func syncSubscriptionStatus() { assert(Purchases.isConfigured, "You must configure RevenueCat before calling this method.") Task { for await customerInfo in Purchases.shared.customerInfoStream { // Gets called whenever new CustomerInfo is available let hasActiveSubscription = !customerInfo.entitlements.active.isEmpty // Why? -> https://www.revenuecat.com/docs/entitlements#entitlements if hasActiveSubscription { Superwall.shared.subscriptionStatus = .active } else { #if DEBUG Superwall.shared.subscriptionStatus = .active #else Superwall.shared.subscriptionStatus = .inactive #endif } } } } } // MARK: - PurchaseController extension PaywallManager: PurchaseController { // MARK: Handle Restores /// Makes a restore with RevenueCat and returns `.restored`, unless an error is thrown. /// This gets called when someone tries to restore purchases on one of your paywalls. func restorePurchases() async -> RestorationResult { do { _ = try await Purchases.shared.restorePurchases() return .restored } catch { return .failed(error) } } // MARK: Handle Purchases /// Makes a purchase with RevenueCat and returns its result. This gets called when /// someone tries to purchase a product on one of your paywalls. func purchase(product: SKProduct) async -> PurchaseResult { do { let storeProduct = RevenueCat.StoreProduct(sk1Product: product) let revenueCatResult = try await Purchases.shared.purchase(product: storeProduct) if revenueCatResult.userCancelled { return .cancelled } else { return .purchased } } catch let error as ErrorCode { if error == .paymentPendingError { return .pending } else { return .failed(error) } } catch { return .failed(error) } } func purchases(_ purchases: Purchases, readyForPromotedProduct product: RevenueCat.StoreProduct, purchase startPurchase: @escaping StartPurchaseBlock) { startPurchase { _, info, error, cancelled in if let info = info, error == nil, !cancelled { self.updateSubscriptionStatus(using: info) } } } }
Editor is loading...