diff --git a/Sources/FoundationExtensions/UIApplication+RCExtensions.swift b/Sources/FoundationExtensions/UIApplication+RCExtensions.swift index 052d63c121..7ff8a77fad 100644 --- a/Sources/FoundationExtensions/UIApplication+RCExtensions.swift +++ b/Sources/FoundationExtensions/UIApplication+RCExtensions.swift @@ -17,8 +17,7 @@ import UIKit extension UIApplication { - @available(iOS 13.0, *) - @available(macCatalystApplicationExtension 13.1, *) + @available(iOS 13.0, macCatalystApplicationExtension 13.1, *) @available(macOS, unavailable) @available(watchOS, unavailable) @available(watchOSApplicationExtension, unavailable) diff --git a/Sources/Logging/Strings/ManageSubscriptionsStrings.swift b/Sources/Logging/Strings/ManageSubscriptionsStrings.swift index b7ec47d1ef..3eaff2c5b8 100644 --- a/Sources/Logging/Strings/ManageSubscriptionsStrings.swift +++ b/Sources/Logging/Strings/ManageSubscriptionsStrings.swift @@ -21,7 +21,6 @@ extension ManageSubscriptionsHelper { case error_from_appstore_show_manage_subscription(error: Error) case failed_to_get_management_url_error_unknown(error: Error) - case failed_to_get_window_scene case management_url_nil_opening_default case show_manage_subscriptions_called_in_unsupported_platform case susbscription_management_sheet_dismissed @@ -38,8 +37,6 @@ extension ManageSubscriptionsHelper.Strings: LogMessage { return "Error when trying to show manage subscription: \(error.localizedDescription)" case .failed_to_get_management_url_error_unknown(let error): return "Failed to get managementURL from CustomerInfo. Details: \(error.localizedDescription)" - case .failed_to_get_window_scene: - return "Failed to get UIWindowScene" case .management_url_nil_opening_default: return "managementURL is nil, opening Apple's subscription management page" case .susbscription_management_sheet_dismissed: diff --git a/Sources/Misc/SystemInfo.swift b/Sources/Misc/SystemInfo.swift index 8aafe86908..0d81c010f4 100644 --- a/Sources/Misc/SystemInfo.swift +++ b/Sources/Misc/SystemInfo.swift @@ -179,6 +179,25 @@ class SystemInfo { } +#if os(iOS) +extension SystemInfo { + + @available(iOS 13.0, macCatalystApplicationExtension 13.1, *) + @available(macOS, unavailable) + @available(watchOS, unavailable) + @available(watchOSApplicationExtension, unavailable) + @available(tvOS, unavailable) + var currentWindowScene: UIWindowScene { + get throws { + let scene = self.sharedUIApplication?.currentWindowScene + + return try scene.orThrow(ErrorUtils.storeProblemError(withMessage: "Failed to get UIWindowScene")) + } + } + +} +#endif + extension SystemInfo: SandboxEnvironmentDetector {} // @unchecked because: diff --git a/Sources/Purchasing/Purchases/PurchasesOrchestrator.swift b/Sources/Purchasing/Purchases/PurchasesOrchestrator.swift index 93fcaeb2e9..2ddedd6509 100644 --- a/Sources/Purchasing/Purchases/PurchasesOrchestrator.swift +++ b/Sources/Purchasing/Purchases/PurchasesOrchestrator.swift @@ -458,7 +458,7 @@ final class PurchasesOrchestrator { self.cachePresentedOfferingIdentifier(package: package, productIdentifier: sk2Product.id) - result = try await sk2Product.purchase(options: options) + result = try await self.purchase(sk2Product, options) } catch StoreKitError.userCancelled { guard !self.systemInfo.dangerousSettings.customEntitlementComputation else { throw ErrorUtils.purchaseCancelledError() @@ -501,6 +501,25 @@ final class PurchasesOrchestrator { return (transaction, customerInfo, userCancelled) } + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + private func purchase( + _ product: SK2Product, + _ options: Set + ) async throws -> Product.PurchaseResult { + // Note: this can be simplified as `#if swift(>=5.9) && os(xrOS)` + // once we drop support for Xcode 13.x + #if swift(>=5.9) + #if os(xrOS) + return try await product.purchase(confirmIn: try self.systemInfo.currentWindowScene, + options: options) + #else + return try await product.purchase(options: options) + #endif + #else + return try await product.purchase(options: options) + #endif + } + @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) func promotionalOffer( forProductDiscount discount: StoreProductDiscountType, diff --git a/Sources/Support/BeginRefundRequestHelper.swift b/Sources/Support/BeginRefundRequestHelper.swift index a75f19f465..c227c5b720 100644 --- a/Sources/Support/BeginRefundRequestHelper.swift +++ b/Sources/Support/BeginRefundRequestHelper.swift @@ -69,9 +69,7 @@ class BeginRefundRequestHelper { @available(tvOS, unavailable) @MainActor func beginRefundRequest(forProduct productID: String) async throws -> RefundRequestStatus { - guard let windowScene = systemInfo.sharedUIApplication?.currentWindowScene else { - throw ErrorUtils.storeProblemError(withMessage: "Failed to get UIWindowScene") - } + let windowScene = try self.systemInfo.currentWindowScene let transactionID = try await sk2Helper.verifyTransaction(productID: productID) return try await sk2Helper.initiateRefundRequest(transactionID: transactionID, diff --git a/Sources/Support/ManageSubscriptionsHelper.swift b/Sources/Support/ManageSubscriptionsHelper.swift index e974422c96..48936b436e 100644 --- a/Sources/Support/ManageSubscriptionsHelper.swift +++ b/Sources/Support/ManageSubscriptionsHelper.swift @@ -124,10 +124,12 @@ private extension ManageSubscriptionsHelper { @available(iOS 15.0, *) @available(macOS, unavailable) func showSK2ManageSubscriptions() async -> Result { - guard let application = systemInfo.sharedUIApplication, - let windowScene = application.currentWindowScene else { - let message = Strings.failed_to_get_window_scene - return .failure(ErrorUtils.storeProblemError(withMessage: message.description)) + let windowScene: UIWindowScene + + do { + windowScene = try self.systemInfo.currentWindowScene + } catch { + return .failure(ErrorUtils.purchasesError(withUntypedError: error)) } #if os(iOS)