Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 3.0.1 #62

Merged
merged 8 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions .github/actions/upload_test_coverage_report/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
path: test_output
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
All notable changes to this project will be documented in this file.

#### 3.x Releases
- `3.0.x` Releases - [`3.0.0`](#300)
- `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
Expand All @@ -11,6 +11,19 @@ All notable changes to this project will be documented in this file.
#### 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
- 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)
- Update mocks
- Updated in Pull Request [#60](https://github.com/space-code/flare/pull/60)

## [3.0.0](https://github.com/space-code/flare/releases/tag/3.0.0)
Released on 2024-06-15.

Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-snapshot-testing",
"state" : {
"revision" : "8ddd519780452729c6634ad6bd0d2595938e9ea3",
"version" : "1.16.1"
"revision" : "6d932a79e7173b275b96c600c86c603cf84f153c",
"version" : "1.17.4"
}
},
{
"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"
Expand Down
15 changes: 13 additions & 2 deletions Sources/Flare/Classes/Flare.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Flare
// Copyright © 2024 Space Code. All rights reserved.
// Copyright © 2023 Space Code. All rights reserved.
//

import struct Log.LogLevel
Expand Down Expand Up @@ -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, any Error>) -> 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<String, IAPError>) -> Void) {
iapProvider.refreshReceipt(updateTransactions: updateTransactions, completion: completion)
}

#if os(iOS) || VISION_OS
@available(iOS 15.0, *)
@available(macOS, unavailable)
Expand Down
69 changes: 60 additions & 9 deletions Sources/Flare/Classes/IFlare.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Flare
// Copyright © 2024 Space Code. All rights reserved.
// Copyright © 2023 Space Code. All rights reserved.
//

import Foundation
Expand Down Expand Up @@ -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<Result<String, IAPError>>)
/// - 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<String, IAPError>` containing the updated receipt information as a `String`.
/// - On failure, it returns a `Result<String, IAPError>` 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<String, IAPError>) -> 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.
Expand Down Expand Up @@ -151,9 +165,30 @@ public protocol IFlare {
@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
func checkEligibility(productIDs: Set<String>) 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<Void, Error>.success(())`.
/// - On failure, it returns `Result<Void, Error>.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, Error>) -> Void)

#if os(iOS) || VISION_OS
/// Present the refund request sheet for the specified transaction in a window scene.
///
Expand Down Expand Up @@ -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<Result<String, IAPError>>) {
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)
}
}
54 changes: 42 additions & 12 deletions Sources/Flare/Classes/Providers/IAPProvider/IAPProvider.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Flare
// Copyright © 2024 Space Code. All rights reserved.
// Copyright © 2023 Space Code. All rights reserved.
//

import StoreKit
Expand Down Expand Up @@ -143,19 +143,46 @@ final class IAPProvider: IIAPProvider {
}
}

func refreshReceipt(completion: @escaping Closure<Result<String, IAPError>>) {
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<String, IAPError>) -> 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<Result<String, IAPError>>) {
refreshReceipt(updateTransactions: false, completion: completion)
}

func refreshReceipt() async throws -> String {
Expand Down Expand Up @@ -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, any Error>) -> Void) {
purchaseProvider.restore(completion)
}

#if os(iOS) || VISION_OS
@available(iOS 15.0, *)
@available(macOS, unavailable)
Expand Down
51 changes: 49 additions & 2 deletions Sources/Flare/Classes/Providers/IAPProvider/IIAPProvider.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Flare
// Copyright © 2024 Space Code. All rights reserved.
// Copyright © 2023 Space Code. All rights reserved.
//

import StoreKit
Expand Down Expand Up @@ -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<String, IAPError>` containing the updated receipt information as a `String`.
/// - On failure, it returns a `Result<String, IAPError>` 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<String, IAPError>) -> 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.
Expand Down Expand Up @@ -150,9 +176,30 @@ public protocol IIAPProvider {
@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
func checkEligibility(productIDs: Set<String>) 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<Void, Error>.success(())`.
/// - On failure, it returns `Result<Void, Error>.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, Error>) -> Void)

#if os(iOS) || VISION_OS
/// Present the refund request sheet for the specified transaction in a window scene.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Void, Error>.success(())`.
/// - On failure, it returns `Result<Void, Error>.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, Error>) -> Void)
}

extension IPurchaseProvider {
Expand Down
Loading
Loading