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:
parent
fccba7d8cb
commit
9abbc6cde2
|
@ -44,47 +44,53 @@ public actor FallbackReceiptReader: AppReceiptReader {
|
||||||
public func receipt(at userLevel: AppUserLevel) async -> InAppReceipt? {
|
public func receipt(at userLevel: AppUserLevel) async -> InAppReceipt? {
|
||||||
let localURL = Bundle.main.appStoreReceiptURL
|
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
|
// 1. TestFlight, look for release receipt
|
||||||
if let localURL,
|
let releaseReceipt: InAppReceipt? = await {
|
||||||
let local = localReader(localURL),
|
guard userLevel == .beta, let localURL else {
|
||||||
let localReceipt = await local.receipt(),
|
|
||||||
let build = localReceipt.originalBuildNumber {
|
|
||||||
|
|
||||||
return receipt.withBuildNumber(build)
|
|
||||||
}
|
|
||||||
return receipt
|
|
||||||
}
|
|
||||||
|
|
||||||
// fall back to release/sandbox receipt
|
|
||||||
guard let localURL else {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
pp_log(.app, .debug, "\tTestFlight, look for release receipt")
|
||||||
// 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 {
|
|
||||||
let releaseURL = localURL
|
let releaseURL = localURL
|
||||||
.deletingLastPathComponent()
|
.deletingLastPathComponent()
|
||||||
.appendingPathComponent("receipt")
|
.appendingPathComponent("receipt")
|
||||||
|
|
||||||
guard releaseURL != localURL else {
|
guard releaseURL != localURL else {
|
||||||
#if !os(macOS) && !targetEnvironment(simulator)
|
#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
|
#endif
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
pp_log(.app, .error, "Sandbox receipt not found, falling back to Release receipt")
|
|
||||||
let release = localReader(releaseURL)
|
let release = localReader(releaseURL)
|
||||||
return await release?.receipt()
|
return await release?.receipt()
|
||||||
|
}()
|
||||||
|
|
||||||
|
if let releaseReceipt {
|
||||||
|
pp_log(.app, .debug, "\tTestFlight, return release receipt")
|
||||||
|
return releaseReceipt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let localReceiptBlock: () async -> InAppReceipt? = { [weak self] in
|
||||||
|
guard let localURL, let local = self?.localReader(localURL) else {
|
||||||
return nil
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue