Redefine in-app receipt strategy (#823)

1. TestFlight: look for release receipt
2. Primary receipt (StoreKit) with build from local
3. Local receipt
This commit is contained in:
Davide 2024-11-07 09:54:51 +01:00 committed by GitHub
parent fccba7d8cb
commit 9abbc6cde2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 33 additions and 27 deletions

View File

@ -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()
}
}