From aadd69572d27312ba12bbf1375d188de60d4d922 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 08:21:06 +0400 Subject: [PATCH 1/8] Bump github.com/pointfreeco/swift-snapshot-testing from 1.16.1 to 1.16.2 (#49) Bumps [github.com/pointfreeco/swift-snapshot-testing](https://github.com/pointfreeco/swift-snapshot-testing) from 1.16.1 to 1.16.2. - [Release notes](https://github.com/pointfreeco/swift-snapshot-testing/releases) - [Commits](https://github.com/pointfreeco/swift-snapshot-testing/compare/1.16.1...1.16.2) --- updated-dependencies: - dependency-name: github.com/pointfreeco/swift-snapshot-testing dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index 18547265b..bfec2897b 100644 --- a/Package.resolved +++ b/Package.resolved @@ -50,8 +50,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing", "state" : { - "revision" : "8ddd519780452729c6634ad6bd0d2595938e9ea3", - "version" : "1.16.1" + "revision" : "d2341adf332dc7341b4acad8761dff65e905d63c", + "version" : "1.16.2" } }, { From 7ab00f0c6798d48aa2e5abf8a6501fb4a977ee91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 09:36:00 +0400 Subject: [PATCH 2/8] Bump github.com/pointfreeco/swift-snapshot-testing from 1.16.2 to 1.17.2 (#52) Bumps [github.com/pointfreeco/swift-snapshot-testing](https://github.com/pointfreeco/swift-snapshot-testing) from 1.16.2 to 1.17.2. - [Release notes](https://github.com/pointfreeco/swift-snapshot-testing/releases) - [Commits](https://github.com/pointfreeco/swift-snapshot-testing/compare/1.16.2...1.17.2) --- updated-dependencies: - dependency-name: github.com/pointfreeco/swift-snapshot-testing dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Package.resolved | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Package.resolved b/Package.resolved index bfec2897b..a0e0f6efb 100644 --- a/Package.resolved +++ b/Package.resolved @@ -50,14 +50,14 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing", "state" : { - "revision" : "d2341adf332dc7341b4acad8761dff65e905d63c", - "version" : "1.16.2" + "revision" : "c097f955b4e724690f0fc8ffb7a6d4b881c9c4e3", + "version" : "1.17.2" } }, { "identity" : "swift-syntax", "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-syntax.git", + "location" : "https://github.com/swiftlang/swift-syntax", "state" : { "revision" : "64889f0c732f210a935a0ad7cda38f77f876262d", "version" : "509.1.1" From 23c2e1b170941c1e2a5a28f4e12253e5c90b62ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 09:42:41 +0400 Subject: [PATCH 3/8] Bump github.com/pointfreeco/swift-snapshot-testing from 1.17.2 to 1.17.4 (#58) Bumps [github.com/pointfreeco/swift-snapshot-testing](https://github.com/pointfreeco/swift-snapshot-testing) from 1.17.2 to 1.17.4. - [Release notes](https://github.com/pointfreeco/swift-snapshot-testing/releases) - [Commits](https://github.com/pointfreeco/swift-snapshot-testing/compare/1.17.2...1.17.4) --- updated-dependencies: - dependency-name: github.com/pointfreeco/swift-snapshot-testing dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Package.resolved | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.resolved b/Package.resolved index a0e0f6efb..9478aa8ff 100644 --- a/Package.resolved +++ b/Package.resolved @@ -50,8 +50,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-snapshot-testing", "state" : { - "revision" : "c097f955b4e724690f0fc8ffb7a6d4b881c9c4e3", - "version" : "1.17.2" + "revision" : "6d932a79e7173b275b96c600c86c603cf84f153c", + "version" : "1.17.4" } }, { From 4b353f4beb91ee3ea6d66ac22c5985d5b77ba6f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 09:42:57 +0400 Subject: [PATCH 4/8] Bump rexml from 3.2.8 to 3.3.3 (#53) Bumps [rexml](https://github.com/ruby/rexml) from 3.2.8 to 3.3.3. - [Release notes](https://github.com/ruby/rexml/releases) - [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md) - [Commits](https://github.com/ruby/rexml/compare/v3.2.8...v3.3.3) --- updated-dependencies: - dependency-name: rexml dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 02e9385ea..e25445e09 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -47,8 +47,8 @@ GEM open4 (1.3.4) public_suffix (5.0.3) rchardet (1.8.0) - rexml (3.2.8) - strscan (>= 3.0.9) + rexml (3.3.3) + strscan ruby2_keywords (0.0.5) sawyer (0.9.2) addressable (>= 2.3.5) From 7792783594aef8ca3c8bd7dd47ca60b334ad5d08 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Thu, 8 Aug 2024 10:33:38 +0400 Subject: [PATCH 5/8] Bump `codecov` from 3.1.0 to 4.5.0 (#59) * Bump `codecov` from 3.1.0 to 4.5.0 * Update `CHANGELOG.md` --- .github/actions/upload_test_coverage_report/action.yml | 10 ++-------- CHANGELOG.md | 6 ++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/actions/upload_test_coverage_report/action.yml b/.github/actions/upload_test_coverage_report/action.yml index 3599ff664..4cdd4df4a 100644 --- a/.github/actions/upload_test_coverage_report/action.yml +++ b/.github/actions/upload_test_coverage_report/action.yml @@ -15,20 +15,14 @@ runs: using: "composite" steps: - - name: Dir - shell: bash - run: pwd && ls -al - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3.1.0 + uses: codecov/codecov-action@v4.5.0 with: token: ${{ inputs.token }} xcode: true flags: ${{ inputs.scheme_name }} xcode_archive_path: test_output/${{ inputs.filename }}.xcresult - - name: Dir - shell: bash - run: pwd && ls -al - uses: actions/upload-artifact@v4 with: name: ${{ inputs.filename }} - path: test_output \ No newline at end of file + path: test_output diff --git a/CHANGELOG.md b/CHANGELOG.md index 098f603e0..c7c1935d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +## [Unreleased] + +## Updated +- Update `codecov` version + - Updated in Pull Request [#59](https://github.com/space-code/flare/pull/59) + #### 3.x Releases - `3.0.x` Releases - [`3.0.0`](#300) - `3.0.0` Release Candidates - [`3.0.0-rc.1`](#300-rc1) | [`3.0.0-rc.2`](#300-rc2) From d2b764aae392b008b2eabe3036264139fdffd16a Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Thu, 8 Aug 2024 14:14:55 +0400 Subject: [PATCH 6/8] Implement Restoring Transactions (#57) * Implement the `restore` method for StoreKit * Update the logic to refresh the receipt The method includes a new parameter, `updateTransactions`, which forces the update of transactions first. By default, this parameter is set to `false`. * Update `CHANGELOG.md` * Update `restore-purchase.md` --- CHANGELOG.md | 4 ++ Sources/Flare/Classes/Flare.swift | 15 +++- Sources/Flare/Classes/IFlare.swift | 69 ++++++++++++++++--- .../Providers/IAPProvider/IAPProvider.swift | 54 +++++++++++---- .../Providers/IAPProvider/IIAPProvider.swift | 51 +++++++++++++- .../PurchaseProvider/IPurchaseProvider.swift | 23 ++++++- .../PurchaseProvider/PurchaseProvider.swift | 21 +++++- .../Flare.docc/Articles/restore-purchase.md | 2 + Sources/FlareUIMock/Mocks/FlareMock.swift | 3 +- .../TestHelpers/Mocks/IAPProviderMock.swift | 16 ++++- .../Mocks/PurchaseProviderMock.swift | 3 +- 11 files changed, 229 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7c1935d3..9dc9ec272 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## Added +- Implement restoring transactions for StoreKit 1 + - Added in Pull Request [#57](https://github.com/space-code/flare/pull/57). + ## Updated - Update `codecov` version - Updated in Pull Request [#59](https://github.com/space-code/flare/pull/59) diff --git a/Sources/Flare/Classes/Flare.swift b/Sources/Flare/Classes/Flare.swift index d2e5f2842..4d508e60b 100644 --- a/Sources/Flare/Classes/Flare.swift +++ b/Sources/Flare/Classes/Flare.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2024 Space Code. All rights reserved. +// Copyright © 2023 Space Code. All rights reserved. // import struct Log.LogLevel @@ -153,11 +153,22 @@ extension Flare: IFlare { try await iapProvider.checkEligibility(productIDs: productIDs) } - @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) public func restore() async throws { try await iapProvider.restore() } + public func restore(_ completion: @escaping (Result) -> Void) { + iapProvider.restore(completion) + } + + public func receipt(updateTransactions: Bool) async throws -> String { + try await iapProvider.refreshReceipt(updateTransactions: updateTransactions) + } + + public func receipt(updateTransactions: Bool, completion: @escaping (Result) -> Void) { + iapProvider.refreshReceipt(updateTransactions: updateTransactions, completion: completion) + } + #if os(iOS) || VISION_OS @available(iOS 15.0, *) @available(macOS, unavailable) diff --git a/Sources/Flare/Classes/IFlare.swift b/Sources/Flare/Classes/IFlare.swift index c108dd85c..0cc638c80 100644 --- a/Sources/Flare/Classes/IFlare.swift +++ b/Sources/Flare/Classes/IFlare.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2024 Space Code. All rights reserved. +// Copyright © 2023 Space Code. All rights reserved. // import Foundation @@ -105,17 +105,31 @@ public protocol IFlare { promotionalOffer: PromotionalOffer? ) async throws -> StoreTransaction - /// Refreshes the receipt, representing the user's transactions with your app. + /// Refreshes the receipt and optionally updates transactions. /// - /// - Parameter completion: The closure to be executed when the refresh operation ends. - func receipt(completion: @escaping Closure>) + /// - Parameters: + /// - updateTransactions: A boolean indicating whether to update transactions. + /// - If `true`, the method will refresh completed transactions. + /// - If `false`, only the receipt will be refreshed. + /// - completion: A closure that gets called with the result of the refresh operation. + /// - On success, it returns a `Result` containing the updated receipt information as a `String`. + /// - On failure, it returns a `Result` with an `IAPError` describing the issue. + /// + /// - Note: Use this method to handle asynchronous receipt refreshing and transaction updates with completion handler feedback. + func receipt(updateTransactions: Bool, completion: @escaping (Result) -> Void) - /// Refreshes the receipt, representing the user's transactions with your app. + /// Refreshes the receipt and optionally updates transactions. /// - /// `IAPError(error:)` if the request did fail with error. + /// - Parameter updateTransactions: A boolean indicating whether to update transactions. + /// - If `true`, the method will refresh completed transactions. + /// - If `false`, only the receipt will be refreshed. /// - /// - Returns: A receipt. - func receipt() async throws -> String + /// - Returns: A `String` containing the updated receipt information. + /// + /// - Throws: An `IAPError` if the refresh process encounters an issue. + /// + /// - Note: Use this method for an asynchronous refresh operation with error handling and receipt data retrieval. + func receipt(updateTransactions: Bool) async throws -> String /// Removes a finished (i.e. failed or completed) transaction from the queue. /// Attempting to finish a purchasing transaction will throw an exception. @@ -151,9 +165,30 @@ public protocol IFlare { @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) func checkEligibility(productIDs: Set) async throws -> [String: SubscriptionEligibility] - @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + /// Restores completed transactions. + /// + /// This method initiates the process of restoring any previously completed transactions. + /// It is an asynchronous function that might throw an error if the restoration fails. + /// + /// - Throws: An error if the restoration process encounters an issue. + /// + /// - Note: This method should be called when you need to restore purchases made by the user on a different device or after + /// reinstallation. func restore() async throws + /// Restores completed transactions. + /// + /// This method initiates the process of restoring any previously completed transactions. + /// It uses a completion handler to provide the result of the restoration process. + /// + /// - Parameter completion: A closure that gets called with a `Result` indicating success or failure of the restoration. + /// - On success, it returns `Result.success(())`. + /// - On failure, it returns `Result.failure(Error)` with an error describing the issue. + /// + /// - Note: Use this method when you need to handle the restoration process asynchronously and provide feedback through the completion + /// handler. + func restore(_ completion: @escaping (Result) -> Void) + #if os(iOS) || VISION_OS /// Present the refund request sheet for the specified transaction in a window scene. /// @@ -259,4 +294,20 @@ public extension IFlare { ) async throws -> StoreTransaction { try await purchase(product: product, options: options, promotionalOffer: nil) } + + /// Refreshes the receipt, representing the user's transactions with your app. + /// + /// - Parameter completion: The closure to be executed when the refresh operation ends. + func receipt(completion: @escaping Closure>) { + receipt(updateTransactions: false, completion: completion) + } + + /// Refreshes the receipt, representing the user's transactions with your app. + /// + /// `IAPError(error:)` if the request did fail with error. + /// + /// - Returns: A receipt. + func receipt() async throws -> String { + try await receipt(updateTransactions: false) + } } diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift index fd787f988..15a76942b 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2024 Space Code. All rights reserved. +// Copyright © 2023 Space Code. All rights reserved. // import StoreKit @@ -143,19 +143,46 @@ final class IAPProvider: IIAPProvider { } } - func refreshReceipt(completion: @escaping Closure>) { - receiptRefreshProvider.refresh(requestID: UUID().uuidString) { [weak self] result in - switch result { - case .success: - if let receipt = self?.receiptRefreshProvider.receipt { - completion(.success(receipt)) - } else { - completion(.failure(.receiptNotFound)) + func refreshReceipt(updateTransactions: Bool) async throws -> String { + try await withCheckedThrowingContinuation { continuation in + refreshReceipt(updateTransactions: updateTransactions) { result in + continuation.resume(with: result) + } + } + } + + func refreshReceipt(updateTransactions: Bool, completion: @escaping (Result) -> Void) { + let refresh = { [weak self] in + self?.receiptRefreshProvider.refresh(requestID: UUID().uuidString) { [weak self] result in + switch result { + case .success: + if let receipt = self?.receiptRefreshProvider.receipt { + completion(.success(receipt)) + } else { + completion(.failure(.receiptNotFound)) + } + case let .failure(error): + completion(.failure(error)) } - case let .failure(error): - completion(.failure(error)) } } + + if updateTransactions { + restore { result in + switch result { + case .success: + refresh() + case let .failure(error): + completion(.failure(IAPError.with(error: error))) + } + } + } else { + refresh() + } + } + + func refreshReceipt(completion: @escaping Closure>) { + refreshReceipt(updateTransactions: false, completion: completion) } func refreshReceipt() async throws -> String { @@ -192,11 +219,14 @@ final class IAPProvider: IIAPProvider { return try await eligibilityProvider.checkEligibility(products: products) } - @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) func restore() async throws { try await purchaseProvider.restore() } + func restore(_ completion: @escaping (Result) -> Void) { + purchaseProvider.restore(completion) + } + #if os(iOS) || VISION_OS @available(iOS 15.0, *) @available(macOS, unavailable) diff --git a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift index 318a1435f..c2b18e33f 100644 --- a/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift +++ b/Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2024 Space Code. All rights reserved. +// Copyright © 2023 Space Code. All rights reserved. // import StoreKit @@ -103,6 +103,32 @@ public protocol IIAPProvider { promotionalOffer: PromotionalOffer? ) async throws -> StoreTransaction + /// Refreshes the receipt and optionally updates transactions. + /// + /// - Parameters: + /// - updateTransactions: A boolean indicating whether to update transactions. + /// - If `true`, the method will refresh completed transactions. + /// - If `false`, only the receipt will be refreshed. + /// - completion: A closure that gets called with the result of the refresh operation. + /// - On success, it returns a `Result` containing the updated receipt information as a `String`. + /// - On failure, it returns a `Result` with an `IAPError` describing the issue. + /// + /// - Note: Use this method to handle asynchronous receipt refreshing and transaction updates with completion handler feedback. + func refreshReceipt(updateTransactions: Bool, completion: @escaping (Result) -> Void) + + /// Refreshes the receipt and optionally updates transactions. + /// + /// - Parameter updateTransactions: A boolean indicating whether to update transactions. + /// - If `true`, the method will refresh completed transactions. + /// - If `false`, only the receipt will be refreshed. + /// + /// - Returns: A `String` containing the updated receipt information. + /// + /// - Throws: An `IAPError` if the refresh process encounters an issue. + /// + /// - Note: Use this method for an asynchronous refresh operation with error handling and receipt data retrieval. + func refreshReceipt(updateTransactions: Bool) async throws -> String + /// Refreshes the receipt, representing the user's transactions with your app. /// /// - Parameter completion: The closure to be executed when the refresh operation ends. @@ -150,9 +176,30 @@ public protocol IIAPProvider { @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) func checkEligibility(productIDs: Set) async throws -> [String: SubscriptionEligibility] - @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + /// Restores completed transactions. + /// + /// This method initiates the process of restoring any previously completed transactions. + /// It is an asynchronous function that might throw an error if the restoration fails. + /// + /// - Throws: An error if the restoration process encounters an issue. + /// + /// - Note: This method should be called when you need to restore purchases made by the user on a different device or after + /// reinstallation. func restore() async throws + /// Restores completed transactions. + /// + /// This method initiates the process of restoring any previously completed transactions. + /// It uses a completion handler to provide the result of the restoration process. + /// + /// - Parameter completion: A closure that gets called with a `Result` indicating success or failure of the restoration. + /// - On success, it returns `Result.success(())`. + /// - On failure, it returns `Result.failure(Error)` with an error describing the issue. + /// + /// - Note: Use this method when you need to handle the restoration process asynchronously and provide feedback through the completion + /// handler. + func restore(_ completion: @escaping (Result) -> Void) + #if os(iOS) || VISION_OS /// Present the refund request sheet for the specified transaction in a window scene. /// diff --git a/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift b/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift index cd290ad09..f5951a3a6 100644 --- a/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift +++ b/Sources/Flare/Classes/Providers/PurchaseProvider/IPurchaseProvider.swift @@ -58,8 +58,29 @@ protocol IPurchaseProvider { completion: @escaping PurchaseCompletionHandler ) - @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) + /// Restores completed transactions. + /// + /// This method initiates the process of restoring any previously completed transactions. + /// It is an asynchronous function that might throw an error if the restoration fails. + /// + /// - Throws: An error if the restoration process encounters an issue. + /// + /// - Note: This method should be called when you need to restore purchases made by the user on a different device or after + /// reinstallation. func restore() async throws + + /// Restores completed transactions. + /// + /// This method initiates the process of restoring any previously completed transactions. + /// It uses a completion handler to provide the result of the restoration process. + /// + /// - Parameter completion: A closure that gets called with a `Result` indicating success or failure of the restoration. + /// - On success, it returns `Result.success(())`. + /// - On failure, it returns `Result.failure(Error)` with an error describing the issue. + /// + /// - Note: Use this method when you need to handle the restoration process asynchronously and provide feedback through the completion + /// handler. + func restore(_ completion: @escaping (Result) -> Void) } extension IPurchaseProvider { diff --git a/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift b/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift index 479ffcd84..2290c6871 100644 --- a/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift +++ b/Sources/Flare/Classes/Providers/PurchaseProvider/PurchaseProvider.swift @@ -230,9 +230,26 @@ extension PurchaseProvider: IPurchaseProvider { paymentProvider.removeTransactionObserver() } - @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) func restore() async throws { - try await AppStore.sync() + if #available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) { + try await AppStore.sync() + } else { + try await withCheckedThrowingContinuation { continuation in + restore { result in + continuation.resume(with: result) + } + } + } + } + + func restore(_ completion: @escaping (Result) -> Void) { + paymentProvider.restoreCompletedTransactions { _, error in + if let error = error { + completion(.failure(error)) + } else { + completion(.success(())) + } + } } } diff --git a/Sources/Flare/Flare.docc/Articles/restore-purchase.md b/Sources/Flare/Flare.docc/Articles/restore-purchase.md index 1164954b4..b4644da4d 100644 --- a/Sources/Flare/Flare.docc/Articles/restore-purchase.md +++ b/Sources/Flare/Flare.docc/Articles/restore-purchase.md @@ -34,3 +34,5 @@ There is an ``IFlare/receipt()`` method for obtaining a receipt using async/awai ```swift let receipt = try await Flare.shared.receipt() ``` + +The ``IFlare/receipt(updateTransactions:completion:)`` method has a parameter, `updateTransactions`, which controls whether transactions are updated first. diff --git a/Sources/FlareUIMock/Mocks/FlareMock.swift b/Sources/FlareUIMock/Mocks/FlareMock.swift index 364f3cfa6..fa3d1c50e 100644 --- a/Sources/FlareUIMock/Mocks/FlareMock.swift +++ b/Sources/FlareUIMock/Mocks/FlareMock.swift @@ -250,12 +250,13 @@ public final class FlareMock: IFlare { public var invokedRestore = false public var invokedRestoreCount = 0 - @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) public func restore() async throws { invokedRestore = true invokedRestoreCount += 1 } + public func restore(_: @escaping (Result) -> Void) {} + #if os(iOS) || VISION_OS public var invokedBeginRefundRequest = false public var invokedBeginRefundRequestCount = 0 diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift index 296b91b41..610bd92a8 100644 --- a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/IAPProviderMock.swift @@ -1,6 +1,6 @@ // // Flare -// Copyright © 2024 Space Code. All rights reserved. +// Copyright © 2023 Space Code. All rights reserved. // @testable import Flare @@ -297,6 +297,18 @@ final class IAPProviderMock: IIAPProvider { invokedPresentOfferCodeRedeemSheetCount += 1 } - @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) func restore() async throws {} + + func restore(_: @escaping (Result) -> Void) {} + + var invokedRefreshReceiptUpdateTransaction = false + var invokedRefreshReceiptUpdateTransactionCount = 0 + var stubbedInvokedRefreshReceiptUpdateTransaction: String = "" + func refreshReceipt(updateTransactions _: Bool) async throws -> String { + invokedRefreshReceiptUpdateTransaction = true + invokedRefreshReceiptUpdateTransactionCount += 1 + return stubbedInvokedRefreshReceiptUpdateTransaction + } + + func refreshReceipt(updateTransactions _: Bool, completion _: @escaping (Result) -> Void) {} } diff --git a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift index f58fd3121..ec176852a 100644 --- a/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift +++ b/Tests/FlareTests/UnitTests/TestHelpers/Mocks/PurchaseProviderMock.swift @@ -81,6 +81,7 @@ final class PurchaseProviderMock: IPurchaseProvider { } } - @available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *) func restore() async throws {} + + func restore(_: @escaping (Result) -> Void) {} } From 6628d4dfcb393d4f77a85b2c049be54a15c7a603 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 9 Aug 2024 08:46:31 +0400 Subject: [PATCH 7/8] Update Mocks (#60) * Update `FlareMock` * Update `CHANGELOG.md` --- CHANGELOG.md | 2 ++ Sources/FlareUIMock/Mocks/FlareMock.swift | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dc9ec272..c10bebf7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ All notable changes to this project will be documented in this file. ## Updated - Update `codecov` version - Updated in Pull Request [#59](https://github.com/space-code/flare/pull/59) +- Update mocks + - Updated in Pull Request [#60](https://github.com/space-code/flare/pull/60) #### 3.x Releases - `3.0.x` Releases - [`3.0.0`](#300) diff --git a/Sources/FlareUIMock/Mocks/FlareMock.swift b/Sources/FlareUIMock/Mocks/FlareMock.swift index fa3d1c50e..6e21c3003 100644 --- a/Sources/FlareUIMock/Mocks/FlareMock.swift +++ b/Sources/FlareUIMock/Mocks/FlareMock.swift @@ -257,6 +257,17 @@ public final class FlareMock: IFlare { public func restore(_: @escaping (Result) -> Void) {} + public var invokedReceiptUpdateTransactions = false + public var invokedReceiptUpdateTransactionsCount = 0 + public var stubbedReceiptUpdateTransactions = "" + public func receipt(updateTransactions _: Bool) async throws -> String { + invokedReceiptUpdateTransactions = true + invokedReceiptUpdateTransactionsCount += 1 + return stubbedReceiptUpdateTransactions + } + + public func receipt(updateTransactions _: Bool, completion _: @escaping (Result) -> Void) {} + #if os(iOS) || VISION_OS public var invokedBeginRefundRequest = false public var invokedBeginRefundRequestCount = 0 From f09c73735c027f1ff256544e9748d21b05fd1bd4 Mon Sep 17 00:00:00 2001 From: Nikita Vasilev Date: Fri, 9 Aug 2024 09:57:36 +0400 Subject: [PATCH 8/8] Update `CHANGELOG` (#61) --- CHANGELOG.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c10bebf7c..d72fbc1dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,18 @@ # Change Log All notable changes to this project will be documented in this file. -## [Unreleased] +#### 3.x Releases +- `3.0.x` Releases - [`3.0.0`](#300) | [`3.0.1`](#301) +- `3.0.0` Release Candidates - [`3.0.0-rc.1`](#300-rc1) | [`3.0.0-rc.2`](#300-rc2) + +#### 2.x Releases +- `2.0.x` Releases - [2.0.0](#200) + +#### 1.x Releases +- `1.0.x` Releases - [1.0.0](#100) + +## [3.0.1](https://github.com/space-code/flare/releases/tag/3.0.1) +Released on 2024-08-09. ## Added - Implement restoring transactions for StoreKit 1 @@ -13,16 +24,6 @@ All notable changes to this project will be documented in this file. - Update mocks - Updated in Pull Request [#60](https://github.com/space-code/flare/pull/60) -#### 3.x Releases -- `3.0.x` Releases - [`3.0.0`](#300) -- `3.0.0` Release Candidates - [`3.0.0-rc.1`](#300-rc1) | [`3.0.0-rc.2`](#300-rc2) - -#### 2.x Releases -- `2.0.x` Releases - [2.0.0](#200) - -#### 1.x Releases -- `1.0.x` Releases - [1.0.0](#100) - ## [3.0.0](https://github.com/space-code/flare/releases/tag/3.0.0) Released on 2024-06-15.