Skip to content

Commit

Permalink
Disabled retry by default
Browse files Browse the repository at this point in the history
  • Loading branch information
NachoSoto committed Oct 7, 2022
1 parent 1587d9f commit 0936f4e
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 51 deletions.
19 changes: 18 additions & 1 deletion Sources/Misc/DangerousSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ import Foundation
*/
@objc(RCDangerousSettings) public final class DangerousSettings: NSObject {

/// Dangerous settings not exposed outside of the SDK.
internal struct InternalSettings {

/// Whether `ReceiptFetcher` can retry fetching receipts.
let enableReceiptFetchRetry: Bool

static let `default`: Self = .init(enableReceiptFetchRetry: false)
}

/**
* Disable or enable subscribing to the StoreKit queue. If this is disabled, RevenueCat won't observe
* the StoreKit queue, and it will not sync any purchase automatically.
Expand All @@ -23,6 +32,8 @@ import Foundation
*/
@objc public let autoSyncPurchases: Bool

internal let internalSettings: InternalSettings

@objc public override convenience init() {
self.init(autoSyncPurchases: true)
}
Expand All @@ -34,8 +45,14 @@ import Foundation
* If this is disabled, RevenueCat won't observe the StoreKit queue, and it will not sync any purchase
* automatically.
*/
@objc public init(autoSyncPurchases: Bool) {
@objc public convenience init(autoSyncPurchases: Bool) {
self.init(autoSyncPurchases: autoSyncPurchases, internalSettings: .default)
}

/// Designated initializer
internal init(autoSyncPurchases: Bool, internalSettings: InternalSettings) {
self.autoSyncPurchases = autoSyncPurchases
self.internalSettings = internalSettings
}

}
Expand Down
2 changes: 1 addition & 1 deletion Sources/Purchasing/Purchases/PurchasesOrchestrator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ private extension PurchasesOrchestrator {
}

private func refreshRequestPolicy(forProductIdentifier productIdentifier: String) -> ReceiptRefreshPolicy {
if self.systemInfo.isSandbox {
if self.systemInfo.dangerousSettings.internalSettings.enableReceiptFetchRetry {
return .retryUntilProductIsFound(productIdentifier: productIdentifier,
maximumRetries: Self.receiptRetryCount,
sleepDuration: Self.receiptRetrySleepDuration)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,16 @@ private extension BaseBackendIntegrationTests {
storeKit2Setting: Self.storeKit2Setting,
storeKitTimeout: Configuration.storeKitRequestTimeoutDefault,
networkTimeout: Configuration.networkTimeoutDefault,
dangerousSettings: nil)
dangerousSettings: self.dangerousSettings)
Purchases.logLevel = .debug
Purchases.shared.delegate = self.purchasesDelegate
}

private var dangerousSettings: DangerousSettings {
return .init(autoSyncPurchases: true,
internalSettings: .init(enableReceiptFetchRetry: true))
}

}

private final class MockSandboxEnvironmentDetector: SandboxEnvironmentDetector {
Expand Down
68 changes: 21 additions & 47 deletions Tests/StoreKitUnitTests/PurchasesOrchestratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ class PurchasesOrchestratorTests: StoreKitConfigTestCase {
mockBeginRefundRequestHelper = MockBeginRefundRequestHelper(systemInfo: systemInfo,
customerInfoManager: customerInfoManager,
currentUserProvider: currentUserProvider)
setupStoreKit1Wrapper()
setUpOrchestrator()
setUpStoreKit2Listener()
self.setupStoreKit1Wrapper()
self.setUpOrchestrator()
self.setUpStoreKit2Listener()
}

fileprivate func setUpStoreKit2Listener() {
Expand Down Expand Up @@ -188,42 +188,6 @@ class PurchasesOrchestratorTests: StoreKitConfigTestCase {
}
}

expect(self.receiptFetcher.receiptDataCalled) == true
expect(self.receiptFetcher.receiptDataReceivedRefreshPolicy) == .retryUntilProductIsFound(
productIdentifier: product.productIdentifier,
maximumRetries: PurchasesOrchestrator.receiptRetryCount,
sleepDuration: PurchasesOrchestrator.receiptRetrySleepDuration
)

expect(self.backend.invokedPostReceiptDataCount) == 1
expect(self.backend.invokedPostReceiptDataParameters?.productData).toNot(beNil())
}

func testPurchaseDoesNotRetryReceiptFetchIfNotInSandbox() async throws {
self.customerInfoManager.stubbedCachedCustomerInfoResult = self.mockCustomerInfo
self.backend.stubbedPostReceiptResult = .success(self.mockCustomerInfo)
self.systemInfo.stubbedIsSandbox = false

let product = try await self.fetchSk1Product()
let storeProduct = try await self.fetchSk1StoreProduct()
let package = Package(identifier: "package",
packageType: .monthly,
storeProduct: storeProduct,
offeringIdentifier: "offering")

let payment = self.storeKit1Wrapper.payment(with: product)

_ = await withCheckedContinuation { continuation in
self.orchestrator.purchase(
sk1Product: product,
payment: payment,
package: package,
wrapper: self.storeKit1Wrapper
) { transaction, customerInfo, error, userCancelled in
continuation.resume(returning: (transaction, customerInfo, error, userCancelled))
}
}

expect(self.receiptFetcher.receiptDataCalled) == true
expect(self.receiptFetcher.receiptDataReceivedRefreshPolicy) == .always

Expand Down Expand Up @@ -394,27 +358,33 @@ class PurchasesOrchestratorTests: StoreKitConfigTestCase {
_ = try await orchestrator.purchase(sk2Product: product, promotionalOffer: nil)

expect(self.receiptFetcher.receiptDataCalled) == true
expect(self.receiptFetcher.receiptDataReceivedRefreshPolicy) == .retryUntilProductIsFound(
productIdentifier: product.id,
maximumRetries: PurchasesOrchestrator.receiptRetryCount,
sleepDuration: PurchasesOrchestrator.receiptRetrySleepDuration
)
expect(self.receiptFetcher.receiptDataReceivedRefreshPolicy) == .always

expect(self.backend.invokedPostReceiptDataCount) == 1
expect(self.backend.invokedPostReceiptDataParameters?.productData).toNot(beNil())
}

@available(iOS 15.0, tvOS 15.0, watchOS 8.0, macOS 12.0, *)
func testPurchaseSK2PackageDoesNotRetryReceiptFetchIfNotInSandbox() async throws {
func testPurchaseSK2PackageRetriesReceiptFetchIfEnabled() async throws {
try AvailabilityChecks.iOS15APIAvailableOrSkipTest()

self.systemInfo = try .init(
platformInfo: nil,
finishTransactions: false,
storeKit2Setting: .enabledForCompatibleDevices,
dangerousSettings: .init(autoSyncPurchases: true,
internalSettings: .init(enableReceiptFetchRetry: true))
)

self.setUpOrchestrator()
self.setUpStoreKit2Listener()

let mockListener = try XCTUnwrap(
self.orchestrator.storeKit2TransactionListener as? MockStoreKit2TransactionListener
)

self.customerInfoManager.stubbedCachedCustomerInfoResult = self.mockCustomerInfo
self.backend.stubbedPostReceiptResult = .success(self.mockCustomerInfo)
self.systemInfo.stubbedIsSandbox = false

mockListener.mockTransaction.value = try await self.createTransactionWithPurchase()

Expand All @@ -423,7 +393,11 @@ class PurchasesOrchestratorTests: StoreKitConfigTestCase {
_ = try await orchestrator.purchase(sk2Product: product, promotionalOffer: nil)

expect(self.receiptFetcher.receiptDataCalled) == true
expect(self.receiptFetcher.receiptDataReceivedRefreshPolicy) == .always
expect(self.receiptFetcher.receiptDataReceivedRefreshPolicy) == .retryUntilProductIsFound(
productIdentifier: product.id,
maximumRetries: PurchasesOrchestrator.receiptRetryCount,
sleepDuration: PurchasesOrchestrator.receiptRetrySleepDuration
)

expect(self.backend.invokedPostReceiptDataCount) == 1
expect(self.backend.invokedPostReceiptDataParameters?.productData).toNot(beNil())
Expand Down
7 changes: 7 additions & 0 deletions Tests/UnitTests/Misc/SystemInfoTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@ class SystemInfoTests: TestCase {
)) == false
}

func testReceiptFetchRetryIsDisabledByDefault() throws {
let systemInfo = try SystemInfo(platformInfo: nil, finishTransactions: false)
let settings = systemInfo.dangerousSettings.internalSettings

expect(settings.enableReceiptFetchRetry) == false
}

}

private extension SystemInfo {
Expand Down
3 changes: 2 additions & 1 deletion Tests/UnitTests/Mocks/MockSystemInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class MockSystemInfo: SystemInfo {
var stubbedIsApplicationBackgrounded: Bool?
var stubbedIsSandbox: Bool?

convenience init(finishTransactions: Bool, storeKit2Setting: StoreKit2Setting = .default) {
convenience init(finishTransactions: Bool,
storeKit2Setting: StoreKit2Setting = .default) {
// swiftlint:disable:next force_try
try! self.init(platformInfo: nil,
finishTransactions: finishTransactions,
Expand Down

0 comments on commit 0936f4e

Please sign in to comment.