Skip to content

Commit

Permalink
Merge pull request #245 from superwall/feature/purchasing-api
Browse files Browse the repository at this point in the history
Feature/purchasing-api
  • Loading branch information
yusuftor authored Oct 1, 2024
2 parents 7ea8255 + 641c07f commit 6030acf
Show file tree
Hide file tree
Showing 20 changed files with 741 additions and 235 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

The changelog for `SuperwallKit`. Also see the [releases](https://github.com/superwall/Superwall-iOS/releases) on GitHub.

## 3.9.2
## 3.10.0

### Enhancements

- Adds `purchase(_:)` to initiate a purchase of an `SKProduct` via Superwall regardless of whether you are using paywalls or not.
- Adds `restorePurchases()` to restore purchases via Superwall.

### Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/RevenueCat/purchases-ios.git",
"state": {
"branch": null,
"revision": "0d2f1fa050acad0de99b9b0ce45d53c741c20629",
"version": "5.2.1"
"revision": "c7058bfd80d7f42ca6aa392bf1fab769d1158bf1",
"version": "5.5.0"
}
}
]
Expand Down
11 changes: 9 additions & 2 deletions Sources/SuperwallKit/Dependencies/DependencyContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ final class DependencyContainer {
receiptManager: receiptManager,
sessionEventsManager: sessionEventsManager,
identityManager: identityManager,
storage: storage,
factory: self
)
}
Expand Down Expand Up @@ -468,8 +469,14 @@ extension DependencyContainer: PurchasedTransactionsFactory {
return productPurchaser.coordinator
}

func purchase(product: SKProduct) async -> PurchaseResult {
return await productPurchaser.purchase(product: product)
func purchase(
product: SKProduct,
isExternal: Bool
) async -> PurchaseResult {
return await productPurchaser.purchase(
product: product,
isExternal: isExternal
)
}

func restorePurchases() async -> RestorationResult {
Expand Down
5 changes: 4 additions & 1 deletion Sources/SuperwallKit/Dependencies/FactoryProtocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,10 @@ protocol TriggerFactory: AnyObject {

protocol PurchasedTransactionsFactory {
func makePurchasingCoordinator() -> PurchasingCoordinator
func purchase(product: SKProduct) async -> PurchaseResult
func purchase(
product: SKProduct,
isExternal: Bool
) async -> PurchaseResult
func restorePurchases() async -> RestorationResult
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ The ``Superwall`` class is used to access all the features of the SDK. Before us
- ``PaywallSkippedReason``
- ``PaywallSkippedReasonObjc``

### Handling Purchases

- ``purchase(_:)``
- ``purchase(_:completion:)-6oyxm``
- ``purchase(_:completion:)-4rj6r``
- ``restorePurchases()``
- ``restorePurchases(completion:)-4fx45``
- ``restorePurchases(completion:)-4cxt5``

### In-App Previews

- ``handleDeepLink(_:)``
Expand Down
2 changes: 2 additions & 0 deletions Sources/SuperwallKit/Logger/LogScope.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public enum LogScope: Int, Encodable, Sendable, CustomStringConvertible {
case receipts
case superwallCore
case paywallPresentation

// TODO: In v4 rename to transactions
case paywallTransactions
case paywallViewController
case cache
Expand Down
2 changes: 1 addition & 1 deletion Sources/SuperwallKit/Misc/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ let sdkVersion = """
*/

let sdkVersion = """
3.9.1
3.10.0
"""
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public enum PaywallCloseReason: Int, Codable, Equatable, Sendable, CustomStringC
case .webViewFailedToLoad:
return "webViewFailedToLoad"
case .manualClose:
return "manualClsoe"
return "manualClose"
case .none:
return "none"
}
Expand Down
62 changes: 55 additions & 7 deletions Sources/SuperwallKit/Paywall/Presentation/PaywallInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//
// Created by Yusuf Tör on 28/02/2022.
//
// swiftlint:disable file_length

import Foundation
import StoreKit
Expand Down Expand Up @@ -332,12 +333,12 @@ public final class PaywallInfo: NSObject {
extension PaywallInfo: Stubbable {
static func stub() -> PaywallInfo {
return PaywallInfo(
databaseId: "abc",
identifier: "1",
name: "Test",
cacheKey: "cacheKey",
buildId: "buildId",
url: URL(string: "https://www.google.com")!,
databaseId: "test",
identifier: "test",
name: "test",
cacheKey: "test",
buildId: "test",
url: URL(string: "https://superwall.com")!,
products: [],
productItems: [],
productIds: [],
Expand All @@ -361,7 +362,54 @@ extension PaywallInfo: Stubbable {
computedPropertyRequests: [],
surveys: [],
presentation: .init(
style: .fullscreen,
style: .none,
condition: .checkUserSubscription,
delay: 0
)
)
}

/// Used when purchasing internally.
static func empty() -> PaywallInfo {
return PaywallInfo(
databaseId: "",
identifier: "",
name: "",
cacheKey: "",
buildId: "",
url: URL(string: "https://superwall.com")!,
products: [],
productItems: [],
productIds: [],
fromEventData: nil,
responseLoadStartTime: nil,
responseLoadCompleteTime: nil,
responseLoadFailTime: nil,
webViewLoadStartTime: nil,
webViewLoadCompleteTime: nil,
webViewLoadFailTime: nil,
productsLoadStartTime: nil,
productsLoadFailTime: nil,
productsLoadCompleteTime: nil,
experiment: .init(
id: "0",
groupId: "0",
variant: .init(
id: "0",
type: .holdout,
paywallId: "0"
)
),
paywalljsVersion: nil,
isFreeTrialAvailable: false,
presentationSourceType: "",
featureGatingBehavior: .nonGated,
closeReason: .none,
localNotifications: [],
computedPropertyRequests: [],
surveys: [],
presentation: .init(
style: .none,
condition: .checkUserSubscription,
delay: 0
)
Expand Down
8 changes: 8 additions & 0 deletions Sources/SuperwallKit/Storage/Cache/CacheKeys.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,11 @@ enum AdServicesTokenStorage: Storable {
static var directory: SearchPathDirectory = .userSpecificDocuments
typealias Value = String
}

enum SavedTransactions: Storable {
static var key: String {
"store.savedTransactions"
}
static var directory: SearchPathDirectory = .appSpecificDocuments
typealias Value = Set<SavedTransaction>
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ final class AutomaticPurchaseController {
extension AutomaticPurchaseController: PurchaseController {
@MainActor
func purchase(product: SKProduct) async -> PurchaseResult {
return await factory.purchase(product: product)
return await factory.purchase(
product: product,
isExternal: false
)
}

@MainActor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ public enum PurchaseResult: Sendable, Equatable {
return false
}
}

func toObjc() -> PurchaseResultObjc {
switch self {
case .cancelled: return .cancelled
case .purchased: return .purchased
case .restored: return .restored
case .pending: return .pending
case .failed: return .failed
}
}
}

// MARK: - Objective-C Only
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import StoreKit
/// When implementing the ``PurchaseController/restorePurchases()`` delegate
/// method, all cases should be considered.
public enum RestorationResult: Sendable, Equatable {
/// The restore was successful – this does not mean the user is subscribed, it just means your restore
/// logic did not fail due to some error. User will see an alert if `Superwall.shared.subscriptionStatus` is
/// not `.active` after returning this value.
/// The restore was successful
///
/// - Warning: This does not mean the user is subscribed, it just means your restore
/// logic did not fail due to some error. User will see an alert if ``Superwall/subscriptionStatus`` is
/// not ``SubscriptionStatus/active`` after returning this value.
case restored

/// The restore failed for some reason (i.e. you were not able to determine if the user has an active subscription.
Expand All @@ -31,6 +33,15 @@ public enum RestorationResult: Sendable, Equatable {
return false
}
}

func toObjc() -> RestorationResultObjc {
switch self {
case .restored:
return .restored
case .failed:
return .failed
}
}
}

/// An enum that defines the possible outcomes of attempting to restore a product.
Expand Down
Loading

0 comments on commit 6030acf

Please sign in to comment.