This commit is contained in:
2025-12-16 14:14:49 +08:00
parent 1651258eec
commit f10ddd9a31
3 changed files with 43 additions and 42 deletions

View File

@@ -51,30 +51,12 @@ final class KBStoreKitBridge: NSObject, StoreKitDelegate {
do {
try await self.manager.purchase(productId: productId)
let state = self.manager.currentState
switch state {
case .purchaseSuccess(let id) where id == productId:
let receipt = try await Self.fetchReceiptData()
self.verifyReceipt(receipt, completion: completion)
case .purchasePending(let id) where id == productId:
if let payload = await Self.latestJWSPayload(for: productId) {
self.verifySignedPayload(payload, completion: completion)
} else {
await MainActor.run {
completion(false, "Purchase pending approval.")
}
case .purchaseCancelled(let id) where id == productId:
await MainActor.run {
completion(false, "Purchase cancelled.")
}
case .purchaseFailed(let id, let error) where id == productId:
await MainActor.run {
completion(false, error.localizedDescription)
}
case .error(let error):
await MainActor.run {
completion(false, error.localizedDescription)
}
default:
await MainActor.run {
completion(false, "Purchase failed.")
completion(false, "Unable to obtain transaction payload.")
}
}
} catch {
@@ -119,12 +101,12 @@ final class KBStoreKitBridge: NSObject, StoreKitDelegate {
return true
}
private func verifyReceipt(_ receipt: String, completion: @escaping (Bool, String?) -> Void) {
receiptVerifier.verifyReceipt(receipt) { success, message, _ in
private func verifySignedPayload(_ payload: String, completion: @escaping (Bool, String?) -> Void) {
receiptVerifier.verifySignedPayload(payload) { success, message, _ in
DispatchQueue.main.async {
if success {
NotificationCenter.default.post(
name: NSNotification.Name(rawValue: NSNotification.Name.KBIAPDidCompletePurchase.rawValue),
name: NSNotification.Name.KBIAPDidCompletePurchase,
object: nil
)
}
@@ -133,22 +115,11 @@ final class KBStoreKitBridge: NSObject, StoreKitDelegate {
}
}
private static func fetchReceiptData() async throws -> String {
if let receipt = try loadReceiptFromBundle() {
return receipt
private static func latestJWSPayload(for productId: String) async -> String? {
guard let result = await Transaction.latest(for: productId) else { return nil }
if case .verified = result {
return result.jwsRepresentation
}
try await AppStore.sync()
if let receipt = try loadReceiptFromBundle() {
return receipt
}
throw StoreKitError.verificationFailed
}
private static func loadReceiptFromBundle() throws -> String? {
guard let url = Bundle.main.appStoreReceiptURL else { return nil }
guard FileManager.default.fileExists(atPath: url.path) else { return nil }
let data = try Data(contentsOf: url, options: .alwaysMapped)
guard !data.isEmpty else { return nil }
return data.base64EncodedString()
return nil
}
}