diff --git a/YuMi/Tools/PIIAPTool/PIIAPRegulate.swift b/YuMi/Tools/PIIAPTool/PIIAPRegulate.swift index 212ba3c5..13b70376 100644 --- a/YuMi/Tools/PIIAPTool/PIIAPRegulate.swift +++ b/YuMi/Tools/PIIAPTool/PIIAPRegulate.swift @@ -15,12 +15,9 @@ typealias RenewalState = StoreKit.Product.SubscriptionInfo.RenewalState enum PIStoreError: Error { - - // 错误回调枚举 case failedVerification case noProduct - } @objc public enum StoreConditionResult: Int64 { // 支付状态 @@ -43,32 +40,26 @@ public class PIIAPRegulate: NSObject { var updateListenerTask: Task? = nil // 支付事件监听 - var transactionMap :[String:Transaction] // 用于完成Id的缓存map - - var name: String = "iosStore" // 单例的写法 - - @objc public static let shared = { - let instance = PIIAPRegulate() - return instance - }() + var transactionMap :[String:Transaction] = [:]// 用于完成Id的缓存map + + @objc public static let shared = PIIAPRegulate() private override init() { // 单例需要保证private的私有性质 - - transactionMap = [:] // 初始化 super.init() - Task { - updateListenerTask = listenForTransactions() - } - - + self.updateListenerTask = listenForTransactions() } - - + + func triggerConditionBlock(_ state: StoreConditionResult, _ param: [String: Any]? = nil) { + if let ConditionBlock = ConditionBlock { + ConditionBlock(state, param) + } + } + // 退订 - @objc public func refunRequest(view: UIView,transactionId:UInt64) async{ + @objc public func refunRequest(view: UIView,transactionId:UInt64) async { do { if let scene = await view.window?.windowScene{ - try await Transaction.beginRefundRequest(for:transactionId , in: scene) + _ = try await Transaction.beginRefundRequest(for:transactionId , in: scene) } }catch{ print("iap error") @@ -77,70 +68,43 @@ public class PIIAPRegulate: NSObject { // 购买某个产品 @objc public func demandCommodityThing(productId:String, uuid: String) async throws { - if(ConditionBlock != nil ){ - ConditionBlock(StoreConditionResult.start,nil) - } + triggerConditionBlock(.start) do { - let list:[String] = [productId] - let storeProducts = try await Product.products(for: Set.init(list)) - - - - - if storeProducts.count > 0 { - try await purchase(storeProducts[0],uuid) - }else { - print("iap: no found product") - if(ConditionBlock != nil ){ - ConditionBlock(StoreConditionResult.noProduct,nil) - } - throw PIStoreError.noProduct // 没有该产品 + let list = [productId] + let storeProducts = try await Product.products(for: Set(list)) + guard let product = storeProducts.first else { +// triggerConditionBlock(.noProduct) + throw PIStoreError.noProduct } + _ = try await purchase(product, uuid) } catch { - print("Failed product request from the App Store server: \(error)") - if(ConditionBlock != nil ){ - ConditionBlock(StoreConditionResult.noProduct,nil) - } - throw PIStoreError.noProduct // 没有该产品 + triggerConditionBlock(.noProduct) + throw PIStoreError.noProduct } } // 购买 private func purchase(_ product: Product, _ uuid: String) async throws -> Transaction? { - if(ConditionBlock != nil ){ - ConditionBlock(StoreConditionResult.pay,nil) - } - + triggerConditionBlock(.pay) + guard let curUUID = UUID.init(uuidString: uuid) else{ - - if(ConditionBlock != nil ){ - ConditionBlock(StoreConditionResult.failedVerification,nil) - } + triggerConditionBlock(.failedVerification) return nil } - let getUUID = Product.PurchaseOption.appAccountToken(curUUID) - let result = try await product.purchase(options: [getUUID]) - + + let result = try await product.purchase(options: [.appAccountToken(curUUID)]) + switch result { case .success(let verification): // 用户购买完成 - let transaction = try await verifiedAndAccomplish(verification) - return transaction + return try await verifiedAndAccomplish(verification) case .userCancelled: // 用户取消 - if(ConditionBlock != nil ){ - ConditionBlock(StoreConditionResult.userCancelled,nil) - } - return nil + triggerConditionBlock(.userCancelled) case .pending: // 此次购买被挂起 - if(ConditionBlock != nil ){ - ConditionBlock(StoreConditionResult.pending,nil) - } - return nil + triggerConditionBlock(.pending) default: - if(ConditionBlock != nil ){ - ConditionBlock(StoreConditionResult.unowned,nil) - } - return nil + triggerConditionBlock(.unowned) } + return nil } // 校验 @@ -149,9 +113,7 @@ public class PIIAPRegulate: NSObject { switch result { case .unverified: //StoreKit parses the JWS, but it fails verification. - if(ConditionBlock != nil ){ - ConditionBlock(StoreConditionResult.failedVerification,nil) - } + triggerConditionBlock(.failedVerification) throw PIStoreError.failedVerification case .verified(let safe): //The result is verified. Return the unwrapped value. @@ -195,53 +157,60 @@ public class PIIAPRegulate: NSObject { break } } catch let error { - print("error:----\(error)") } - } - - - //Transaction.latest(for: "pid") - } // 事件完成处理 - @objc public func verifyBusinessAccomplish(transaction:String) async{ - if(transactionMap[transaction] != nil){ - await transactionMap[transaction]!.finish() - transactionMap.removeValue(forKey: transaction) - print("verifyBusinessFinish end") - }else { - await getAllBusiness(transactionId: transaction) +// @objc public func verifyBusinessAccomplish(transaction:String) async { +// if(transactionMap[transaction] != nil){ +// await transactionMap[transaction]!.finish() +// transactionMap.removeValue(forKey: transaction) +// print("verifyBusinessFinish end") +// }else { +// await getAllBusiness(transactionId: transaction) +// } +// } + + @objc public func verifyBusinessAccomplish(transactionID: String, completionHandler: @escaping (Bool, Error?) -> Void) { + if let transaction = transactionMap[transactionID] { + Task { + await transaction.finish() + transactionMap.removeValue(forKey: transactionID) + completionHandler(true, nil) // 成功完成交易 + } + } else { + Task { + await getAllBusiness(transactionId: transactionID) + completionHandler(false, nil) // 没有找到交易,但已尝试处理未完成交易 + } } } - + @MainActor func uploadServer(for transactionId:UInt64) async { let dic :Dictionary = ["transactionId":transactionId] - if(ConditionBlock != nil ){ - ConditionBlock(StoreConditionResult.verifiedServer,dic) - } + triggerConditionBlock(.verifiedServer, dic) } // 支付监听事件 func listenForTransactions() -> Task { return Task.detached { - //Iterate through any transactions that don't come from a direct call to `purchase()`. - // 修改update 为 unfinished? - for await result in Transaction.updates { //会导致二次校验? + for await result in Transaction.updates { do { - print("iap: updates") - print("result:\(result)") - try await self.verifiedAndAccomplish(result) + let resultId = try result.payloadValue.id + if !self.transactionMap.keys.contains(String(resultId)) { + _ = try await self.verifiedAndAccomplish(result) + } } catch { - //StoreKit has a transaction that fails verification. Don't deliver content to the user. - print("Transaction failed verification") + // 在这里处理错误 + print("Error: \(error)") } } } } + //获取推广内购商品 func Promotion() async -> [SKProduct]?{ let promotion = SKProductStorePromotionController()