feat: 优化 PIIAPRegulate

This commit is contained in:
eggmanQQQ
2024-09-24 18:02:05 +08:00
parent 6ba054c694
commit 4d46e1505c

View File

@@ -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<Void, Error>? = nil //
var transactionMap :[String:Transaction] // Idmap
var name: String = "iosStore" //
@objc public static let shared = {
let instance = PIIAPRegulate()
return instance
}()
var transactionMap :[String:Transaction] = [:]// Idmap
@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<String,Any> = ["transactionId":transactionId]
if(ConditionBlock != nil ){
ConditionBlock(StoreConditionResult.verifiedServer,dic)
}
triggerConditionBlock(.verifiedServer, dic)
}
//
func listenForTransactions() -> Task<Void, Error> {
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()