From 9abbc6cde25d85713ff80d1aa559ef093e526106 Mon Sep 17 00:00:00 2001 From: Davide Date: Thu, 7 Nov 2024 09:54:51 +0100 Subject: [PATCH] Redefine in-app receipt strategy (#823) 1. TestFlight: look for release receipt 2. Primary receipt (StoreKit) with build from local 3. Local receipt --- .../IAP/FallbackReceiptReader.swift | 60 ++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/Passepartout/Library/Sources/CommonLibrary/IAP/FallbackReceiptReader.swift b/Passepartout/Library/Sources/CommonLibrary/IAP/FallbackReceiptReader.swift index c1b46254..4d90876f 100644 --- a/Passepartout/Library/Sources/CommonLibrary/IAP/FallbackReceiptReader.swift +++ b/Passepartout/Library/Sources/CommonLibrary/IAP/FallbackReceiptReader.swift @@ -44,47 +44,53 @@ public actor FallbackReceiptReader: AppReceiptReader { public func receipt(at userLevel: AppUserLevel) async -> InAppReceipt? { let localURL = Bundle.main.appStoreReceiptURL - if let receipt = await reader?.receipt() { + pp_log(.app, .debug, "Parse receipt for user level \(userLevel)") - // fetch build number from local receipt - if let localURL, - let local = localReader(localURL), - let localReceipt = await local.receipt(), - let build = localReceipt.originalBuildNumber { - - return receipt.withBuildNumber(build) + // 1. TestFlight, look for release receipt + let releaseReceipt: InAppReceipt? = await { + guard userLevel == .beta, let localURL else { + return nil } - return receipt - } - - // fall back to release/sandbox receipt - guard let localURL else { - return nil - } - - // attempt fallback from primary to local receipt - pp_log(.app, .error, "Primary receipt not found, falling back to local receipt") - if let local = localReader(localURL), let localReceipt = await local.receipt() { - return localReceipt - } - - // in TestFlight, attempt fallback from sandbox to release receipt - if userLevel == .beta { + pp_log(.app, .debug, "\tTestFlight, look for release receipt") let releaseURL = localURL .deletingLastPathComponent() .appendingPathComponent("receipt") guard releaseURL != localURL else { #if !os(macOS) && !targetEnvironment(simulator) - assertionFailure("How can release URL be equal to sandbox URL in TestFlight?") + assertionFailure("How can release URL be equal to Sandbox URL in TestFlight?") #endif return nil } - pp_log(.app, .error, "Sandbox receipt not found, falling back to Release receipt") let release = localReader(releaseURL) return await release?.receipt() + }() + + if let releaseReceipt { + pp_log(.app, .debug, "\tTestFlight, return release receipt") + return releaseReceipt } - return nil + let localReceiptBlock: () async -> InAppReceipt? = { [weak self] in + guard let localURL, let local = self?.localReader(localURL) else { + return nil + } + return await local.receipt() + } + + // 2. primary receipt + build from local receipt + pp_log(.app, .debug, "\tNo release receipt, read primary receipt") + if let receipt = await reader?.receipt() { + if let build = await localReceiptBlock()?.originalBuildNumber { + pp_log(.app, .debug, "\tReturn primary receipt with local build: \(build)") + return receipt.withBuildNumber(build) + } + pp_log(.app, .debug, "\tReturn primary receipt without local build") + return receipt + } + + // 3. fall back to local receipt + pp_log(.app, .debug, "\tReturn local receipt") + return await localReceiptBlock() } }