feat: 优化 PIIAPRegulate
This commit is contained in:
@@ -15,12 +15,9 @@ typealias RenewalState = StoreKit.Product.SubscriptionInfo.RenewalState
|
|||||||
|
|
||||||
|
|
||||||
enum PIStoreError: Error {
|
enum PIStoreError: Error {
|
||||||
|
|
||||||
|
|
||||||
// 错误回调枚举
|
// 错误回调枚举
|
||||||
case failedVerification
|
case failedVerification
|
||||||
case noProduct
|
case noProduct
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public enum StoreConditionResult: Int64 { // 支付状态
|
@objc public enum StoreConditionResult: Int64 { // 支付状态
|
||||||
@@ -43,32 +40,26 @@ public class PIIAPRegulate: NSObject {
|
|||||||
|
|
||||||
var updateListenerTask: Task<Void, Error>? = nil // 支付事件监听
|
var updateListenerTask: Task<Void, Error>? = nil // 支付事件监听
|
||||||
|
|
||||||
var transactionMap :[String:Transaction] // 用于完成Id的缓存map
|
var transactionMap :[String:Transaction] = [:]// 用于完成Id的缓存map
|
||||||
|
|
||||||
var name: String = "iosStore" // 单例的写法
|
@objc public static let shared = PIIAPRegulate()
|
||||||
|
|
||||||
@objc public static let shared = {
|
|
||||||
let instance = PIIAPRegulate()
|
|
||||||
return instance
|
|
||||||
}()
|
|
||||||
|
|
||||||
private override init() { // 单例需要保证private的私有性质
|
private override init() { // 单例需要保证private的私有性质
|
||||||
|
|
||||||
transactionMap = [:] // 初始化
|
|
||||||
super.init()
|
super.init()
|
||||||
Task {
|
self.updateListenerTask = listenForTransactions()
|
||||||
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 {
|
do {
|
||||||
if let scene = await view.window?.windowScene{
|
if let scene = await view.window?.windowScene{
|
||||||
try await Transaction.beginRefundRequest(for:transactionId , in: scene)
|
_ = try await Transaction.beginRefundRequest(for:transactionId , in: scene)
|
||||||
}
|
}
|
||||||
}catch{
|
}catch{
|
||||||
print("iap error")
|
print("iap error")
|
||||||
@@ -77,70 +68,43 @@ public class PIIAPRegulate: NSObject {
|
|||||||
|
|
||||||
// 购买某个产品
|
// 购买某个产品
|
||||||
@objc public func demandCommodityThing(productId:String, uuid: String) async throws {
|
@objc public func demandCommodityThing(productId:String, uuid: String) async throws {
|
||||||
if(ConditionBlock != nil ){
|
triggerConditionBlock(.start)
|
||||||
ConditionBlock(StoreConditionResult.start,nil)
|
|
||||||
}
|
|
||||||
do {
|
do {
|
||||||
let list:[String] = [productId]
|
let list = [productId]
|
||||||
let storeProducts = try await Product.products(for: Set.init(list))
|
let storeProducts = try await Product.products(for: Set(list))
|
||||||
|
guard let product = storeProducts.first else {
|
||||||
|
// triggerConditionBlock(.noProduct)
|
||||||
|
throw PIStoreError.noProduct
|
||||||
|
|
||||||
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 // 没有该产品
|
|
||||||
}
|
}
|
||||||
|
_ = try await purchase(product, uuid)
|
||||||
} catch {
|
} catch {
|
||||||
print("Failed product request from the App Store server: \(error)")
|
triggerConditionBlock(.noProduct)
|
||||||
if(ConditionBlock != nil ){
|
throw PIStoreError.noProduct
|
||||||
ConditionBlock(StoreConditionResult.noProduct,nil)
|
|
||||||
}
|
|
||||||
throw PIStoreError.noProduct // 没有该产品
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 购买
|
// 购买
|
||||||
private func purchase(_ product: Product, _ uuid: String) async throws -> Transaction? {
|
private func purchase(_ product: Product, _ uuid: String) async throws -> Transaction? {
|
||||||
if(ConditionBlock != nil ){
|
triggerConditionBlock(.pay)
|
||||||
ConditionBlock(StoreConditionResult.pay,nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let curUUID = UUID.init(uuidString: uuid) else{
|
guard let curUUID = UUID.init(uuidString: uuid) else{
|
||||||
|
triggerConditionBlock(.failedVerification)
|
||||||
if(ConditionBlock != nil ){
|
|
||||||
ConditionBlock(StoreConditionResult.failedVerification,nil)
|
|
||||||
}
|
|
||||||
return nil
|
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 {
|
switch result {
|
||||||
case .success(let verification): // 用户购买完成
|
case .success(let verification): // 用户购买完成
|
||||||
let transaction = try await verifiedAndAccomplish(verification)
|
return try await verifiedAndAccomplish(verification)
|
||||||
return transaction
|
|
||||||
case .userCancelled: // 用户取消
|
case .userCancelled: // 用户取消
|
||||||
if(ConditionBlock != nil ){
|
triggerConditionBlock(.userCancelled)
|
||||||
ConditionBlock(StoreConditionResult.userCancelled,nil)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case .pending: // 此次购买被挂起
|
case .pending: // 此次购买被挂起
|
||||||
if(ConditionBlock != nil ){
|
triggerConditionBlock(.pending)
|
||||||
ConditionBlock(StoreConditionResult.pending,nil)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
default:
|
default:
|
||||||
if(ConditionBlock != nil ){
|
triggerConditionBlock(.unowned)
|
||||||
ConditionBlock(StoreConditionResult.unowned,nil)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验
|
// 校验
|
||||||
@@ -149,9 +113,7 @@ public class PIIAPRegulate: NSObject {
|
|||||||
switch result {
|
switch result {
|
||||||
case .unverified:
|
case .unverified:
|
||||||
//StoreKit parses the JWS, but it fails verification.
|
//StoreKit parses the JWS, but it fails verification.
|
||||||
if(ConditionBlock != nil ){
|
triggerConditionBlock(.failedVerification)
|
||||||
ConditionBlock(StoreConditionResult.failedVerification,nil)
|
|
||||||
}
|
|
||||||
throw PIStoreError.failedVerification
|
throw PIStoreError.failedVerification
|
||||||
case .verified(let safe):
|
case .verified(let safe):
|
||||||
//The result is verified. Return the unwrapped value.
|
//The result is verified. Return the unwrapped value.
|
||||||
@@ -195,53 +157,60 @@ public class PIIAPRegulate: NSObject {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
} catch let error {
|
} catch let error {
|
||||||
|
|
||||||
print("error:----\(error)")
|
print("error:----\(error)")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Transaction.latest(for: "pid")
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// 事件完成处理
|
// 事件完成处理
|
||||||
|
|
||||||
@objc public func verifyBusinessAccomplish(transaction:String) async{
|
// @objc public func verifyBusinessAccomplish(transaction:String) async {
|
||||||
if(transactionMap[transaction] != nil){
|
// if(transactionMap[transaction] != nil){
|
||||||
await transactionMap[transaction]!.finish()
|
// await transactionMap[transaction]!.finish()
|
||||||
transactionMap.removeValue(forKey: transaction)
|
// transactionMap.removeValue(forKey: transaction)
|
||||||
print("verifyBusinessFinish end")
|
// print("verifyBusinessFinish end")
|
||||||
}else {
|
// }else {
|
||||||
await getAllBusiness(transactionId: transaction)
|
// 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
|
@MainActor
|
||||||
func uploadServer(for transactionId:UInt64) async {
|
func uploadServer(for transactionId:UInt64) async {
|
||||||
let dic :Dictionary<String,Any> = ["transactionId":transactionId]
|
let dic :Dictionary<String,Any> = ["transactionId":transactionId]
|
||||||
if(ConditionBlock != nil ){
|
triggerConditionBlock(.verifiedServer, dic)
|
||||||
ConditionBlock(StoreConditionResult.verifiedServer,dic)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 支付监听事件
|
// 支付监听事件
|
||||||
func listenForTransactions() -> Task<Void, Error> {
|
func listenForTransactions() -> Task<Void, Error> {
|
||||||
return Task.detached {
|
return Task.detached {
|
||||||
//Iterate through any transactions that don't come from a direct call to `purchase()`.
|
for await result in Transaction.updates {
|
||||||
// 修改update 为 unfinished?
|
|
||||||
for await result in Transaction.updates { //会导致二次校验?
|
|
||||||
do {
|
do {
|
||||||
print("iap: updates")
|
let resultId = try result.payloadValue.id
|
||||||
print("result:\(result)")
|
if !self.transactionMap.keys.contains(String(resultId)) {
|
||||||
try await self.verifiedAndAccomplish(result)
|
_ = try await self.verifiedAndAccomplish(result)
|
||||||
|
}
|
||||||
} catch {
|
} 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]?{
|
func Promotion() async -> [SKProduct]?{
|
||||||
let promotion = SKProductStorePromotionController()
|
let promotion = SKProductStorePromotionController()
|
||||||
|
Reference in New Issue
Block a user