|
@@ -5,229 +5,229 @@
|
|
|
// Created by 100Years on 2025/8/10.
|
|
|
//
|
|
|
|
|
|
-import Foundation
|
|
|
-import StoreKit
|
|
|
-
|
|
|
-
|
|
|
-typealias PurchaseTimesStateChangeHandler = (_ manager: TSPurchaseTimesManager, _ state: PremiumRequestState, _ object: Any?) -> Void
|
|
|
-
|
|
|
-public class TSPurchaseTimesManager: NSObject {
|
|
|
- @objc public static let `default` = TSPurchaseTimesManager()
|
|
|
-
|
|
|
- //购买次数的商品
|
|
|
- static var purchaseNumProducts: [String] = {
|
|
|
- return ["201","202","203"]
|
|
|
- }()
|
|
|
-
|
|
|
- lazy var products: [SKProduct] = []
|
|
|
- var paymentProductIdentifier:String?
|
|
|
- var onPurchaseStateChanged: PurchaseTimesStateChangeHandler?
|
|
|
-
|
|
|
- // 原始订单交易id dict
|
|
|
- var originalTransactionIdentifierDict: [String: String] = [:]
|
|
|
-
|
|
|
- override init() {
|
|
|
- super.init()
|
|
|
- SKPaymentQueue.default().add(self)
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-// MARK: 商品 & 订阅请求
|
|
|
-extension TSPurchaseTimesManager {
|
|
|
- /// 购买支付
|
|
|
- public func pay(for period: PremiumPeriod) {
|
|
|
- guard SKPaymentQueue.canMakePayments() else {
|
|
|
- purchase(self, didChaged: .payFail, object: "Payment failed, please check your payment account",transaction: nil)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
-// guard SKPaymentQueue.default().transactions.count <= 0 else {
|
|
|
-// purchase(self, didChaged: .payFail, object: "You have outstanding orders that must be paid for before a new subscription can be placed.",transaction: nil)
|
|
|
-// debugPrint("TSPurchaseTimesManager pay period restorePremium = \(period)")
|
|
|
+//import Foundation
|
|
|
+//import StoreKit
|
|
|
+//
|
|
|
+//
|
|
|
+//typealias PurchaseTimesStateChangeHandler = (_ manager: TSPurchaseTimesManager, _ state: PremiumRequestState, _ object: Any?) -> Void
|
|
|
+//
|
|
|
+//public class TSPurchaseTimesManager: NSObject {
|
|
|
+// @objc public static let `default` = TSPurchaseTimesManager()
|
|
|
+//
|
|
|
+// //购买次数的商品
|
|
|
+// static var purchaseNumProducts: [String] = {
|
|
|
+// return ["201","202","203"]
|
|
|
+// }()
|
|
|
+//
|
|
|
+// lazy var products: [SKProduct] = []
|
|
|
+// var paymentProductIdentifier:String?
|
|
|
+// var onPurchaseStateChanged: PurchaseTimesStateChangeHandler?
|
|
|
+//
|
|
|
+// // 原始订单交易id dict
|
|
|
+// var originalTransactionIdentifierDict: [String: String] = [:]
|
|
|
+//
|
|
|
+// override init() {
|
|
|
+// super.init()
|
|
|
+// SKPaymentQueue.default().add(self)
|
|
|
+// }
|
|
|
+//
|
|
|
+//}
|
|
|
+//
|
|
|
+//
|
|
|
+//
|
|
|
+//// MARK: 商品 & 订阅请求
|
|
|
+//extension TSPurchaseTimesManager {
|
|
|
+// /// 购买支付
|
|
|
+// public func pay(for period: PremiumPeriod) {
|
|
|
+// guard SKPaymentQueue.canMakePayments() else {
|
|
|
+// purchase(self, didChaged: .payFail, object: "Payment failed, please check your payment account",transaction: nil)
|
|
|
// return
|
|
|
// }
|
|
|
-
|
|
|
- if let product = kPurchaseDefault.product(for: period) {
|
|
|
- purchase(self, didChaged: .paying, object: nil,transaction: nil)
|
|
|
- let payment = SKPayment(product: product)
|
|
|
- debugPrint("TSPurchaseTimesManager pay product = \(product.localizedDescription)")
|
|
|
- SKPaymentQueue.default().add(payment)
|
|
|
- paymentProductIdentifier = payment.productIdentifier
|
|
|
- debugPrint("TSPurchaseTimesManager pay period = \(period)")
|
|
|
-
|
|
|
- kPurchaseDefault.subscriptionApple(type: .created, jsonString: "Payment period = \(product)")
|
|
|
- } else {
|
|
|
- purchase(self, didChaged: .payFail, object: "Payment failed, no this item",transaction: nil)
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// MARK: 订阅回调
|
|
|
-
|
|
|
-extension TSPurchaseTimesManager: SKPaymentTransactionObserver {
|
|
|
- public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
|
|
- debugPrint("TSPurchaseTimesManager paymentQueue transactions.count = \(transactions.count)")
|
|
|
- originalTransactionIdentifierDict.removeAll()
|
|
|
- // 因为只有订阅类的购买项
|
|
|
- for transaction in transactions {
|
|
|
- if Self.purchaseNumProducts.contains(transaction.payment.productIdentifier) == false {
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- switch transaction.transactionState {
|
|
|
- case .purchasing:
|
|
|
- // Transaction is being added to the server queue.
|
|
|
- purchase(self, didChaged: .paying, object: nil,transaction:transaction)
|
|
|
-
|
|
|
- case .purchased:
|
|
|
- SKPaymentQueue.default().finishTransaction(transaction)
|
|
|
- // 同样的原始订单,只处理一次.
|
|
|
- guard judgeWhether(transaction: transaction) else {
|
|
|
- break
|
|
|
- }
|
|
|
-
|
|
|
- // Transaction is in queue, user has been charged. Client should complete the transaction.
|
|
|
- #if DEBUG
|
|
|
- verifyPayResult(transaction: transaction, useSandBox: true)
|
|
|
- #else
|
|
|
- verifyPayResult(transaction: transaction, useSandBox: false)
|
|
|
- #endif
|
|
|
-
|
|
|
- case .failed:
|
|
|
-
|
|
|
- SKPaymentQueue.default().finishTransaction(transaction)
|
|
|
- var message = "Payment Failed"
|
|
|
- if let error = transaction.error as? SKError{
|
|
|
- if error.code == SKError.paymentCancelled {
|
|
|
- message = "The subscription was canceled"
|
|
|
- }else{
|
|
|
- message = error.localizedDescription
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- purchase(self, didChaged: .payFail, object: message,transaction:transaction)
|
|
|
- kPurchaseDefault.subscriptionApple(type: .result, jsonString: message)
|
|
|
- case .restored:
|
|
|
- SKPaymentQueue.default().finishTransaction(transaction)
|
|
|
- // 同样的原始订单,只处理一次.
|
|
|
- guard judgeWhether(transaction: transaction) else {
|
|
|
- break
|
|
|
- }
|
|
|
-
|
|
|
- // Transaction was restored from user's purchase history. Client should complete the transaction.
|
|
|
- if let original = transaction.original,
|
|
|
- original.transactionState == .purchased {
|
|
|
- #if DEBUG
|
|
|
- verifyPayResult(transaction: transaction, useSandBox: true)
|
|
|
- #else
|
|
|
- verifyPayResult(transaction: transaction, useSandBox: false)
|
|
|
- #endif
|
|
|
- } else {
|
|
|
- purchase(self, didChaged: .restoreFail, object: "Failed to restore subscribe, please try again",transaction:transaction)
|
|
|
- kPurchaseDefault.subscriptionApple(type: .result, jsonString: "Failed to restore subscribe, please try again")
|
|
|
- }
|
|
|
-
|
|
|
- case .deferred: // The transaction is in the queue, but its final status is pending external action.
|
|
|
- break
|
|
|
- @unknown default:
|
|
|
- SKPaymentQueue.default().finishTransaction(transaction)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
|
|
|
- purchase(self, didChaged: .restoreFail, object: nil,transaction:nil)
|
|
|
- }
|
|
|
-
|
|
|
- public func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
|
|
|
- if let trans = queue.transactions.first(where: { $0.transactionState == .purchased }) {
|
|
|
- verifyPayResult(transaction: trans, useSandBox: false)
|
|
|
- } else if queue.transactions.isEmpty {
|
|
|
- purchase(self, didChaged: .restoreFail, object: "You don't have an active subscription",transaction:nil)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func judgeWhether(transaction: SKPaymentTransaction) -> Bool {
|
|
|
- let id = transaction.original?.transactionIdentifier
|
|
|
- if let id = id {
|
|
|
- if let value = originalTransactionIdentifierDict[id] {
|
|
|
- return false
|
|
|
- }
|
|
|
- originalTransactionIdentifierDict[id] = "1"
|
|
|
- }
|
|
|
- return true
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension TSPurchaseTimesManager {
|
|
|
- func verifyPayResult(transaction: SKPaymentTransaction, useSandBox: Bool) {
|
|
|
- purchase(self, didChaged: .verifying, object: nil,transaction:transaction)
|
|
|
-
|
|
|
- guard let url = Bundle.main.appStoreReceiptURL,
|
|
|
- let receiptData = try? Data(contentsOf: url) else {
|
|
|
- purchase(self, didChaged: .verifyFail, object: "凭证文件为空",transaction:transaction)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- let requestContents = [
|
|
|
- "receipt-data": receiptData.base64EncodedString(),
|
|
|
- "password": kPurchaseDefault.AppleSharedKey,
|
|
|
- ]
|
|
|
- guard let requestData = try? JSONSerialization.data(withJSONObject: requestContents) else {
|
|
|
- purchase(self, didChaged: .verifyFail, object: "凭证文件为空",transaction:transaction)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- let verifyUrlString = useSandBox ? PurchaseManager.Config.sandBoxUrl : PurchaseManager.Config.verifyUrl
|
|
|
-
|
|
|
- kPurchaseDefault.postRequest(urlString: verifyUrlString, httpBody: requestData) { [weak self] data, _ in
|
|
|
- guard let self = self else { return }
|
|
|
- if let data = data,
|
|
|
- let jsonResponse = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
|
|
|
- debugPrint("TSPurchaseTimesManager verifyPayResult = \(jsonResponse)")
|
|
|
- let status = jsonResponse["status"]
|
|
|
- if let status = status as? String, status == "21007" {
|
|
|
- self.verifyPayResult(transaction: transaction, useSandBox: true)
|
|
|
- } else if let status = status as? Int, status == 21007 {
|
|
|
- self.verifyPayResult(transaction: transaction, useSandBox: true)
|
|
|
- } else if let status = status as? String, status == "0" {
|
|
|
- self.handlerPayResult(transaction: transaction, resp: jsonResponse)
|
|
|
- } else if let status = status as? Int, status == 0 {
|
|
|
- self.handlerPayResult(transaction: transaction, resp: jsonResponse)
|
|
|
- } else {
|
|
|
- self.purchase(self, didChaged: .verifyFail, object: "验证结果状态码错误:\(status.debugDescription)",transaction:transaction)
|
|
|
- }
|
|
|
- } else {
|
|
|
- self.purchase(self, didChaged: .verifyFail, object: "验证结果为空",transaction:transaction)
|
|
|
- debugPrint("TSPurchaseTimesManager 验证结果为空")
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- func handlerPayResult(transaction: SKPaymentTransaction, resp: [String: Any]) {
|
|
|
-
|
|
|
- //购买视频次数相关
|
|
|
- //分析处理购买消耗品的逻辑处理
|
|
|
- kPurchaseDefault.analyzeDataReceiptForPurchase(resp: resp)
|
|
|
-
|
|
|
- DispatchQueue.main.async {
|
|
|
- self.purchase(self, didChaged: .paySuccess, object: nil,transaction:transaction)
|
|
|
- }
|
|
|
-
|
|
|
- kPurchaseDefault.subscriptionApple(type: .result, jsonString: kPurchaseDefault.simplifyVerifyPayResult(resp: resp))
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-public extension TSPurchaseTimesManager {
|
|
|
- func purchase(_ manager: TSPurchaseTimesManager, didChaged state: PremiumRequestState, object: Any?,transaction:SKPaymentTransaction?) {
|
|
|
- if transaction == nil{
|
|
|
- onPurchaseStateChanged?(manager, state, object)
|
|
|
- }else if let productIdentifier = transaction?.payment.productIdentifier,productIdentifier == paymentProductIdentifier {
|
|
|
- onPurchaseStateChanged?(manager, state, object)
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
+//
|
|
|
+//// guard SKPaymentQueue.default().transactions.count <= 0 else {
|
|
|
+//// purchase(self, didChaged: .payFail, object: "You have outstanding orders that must be paid for before a new subscription can be placed.",transaction: nil)
|
|
|
+//// debugPrint("TSPurchaseTimesManager pay period restorePremium = \(period)")
|
|
|
+//// return
|
|
|
+//// }
|
|
|
+//
|
|
|
+// if let product = kPurchaseDefault.product(for: period) {
|
|
|
+// purchase(self, didChaged: .paying, object: nil,transaction: nil)
|
|
|
+// let payment = SKPayment(product: product)
|
|
|
+// debugPrint("TSPurchaseTimesManager pay product = \(product.localizedDescription)")
|
|
|
+// SKPaymentQueue.default().add(payment)
|
|
|
+// paymentProductIdentifier = payment.productIdentifier
|
|
|
+// debugPrint("TSPurchaseTimesManager pay period = \(period)")
|
|
|
+//
|
|
|
+// kPurchaseDefault.subscriptionApple(type: .created, jsonString: "Payment period = \(product)")
|
|
|
+// } else {
|
|
|
+// purchase(self, didChaged: .payFail, object: "Payment failed, no this item",transaction: nil)
|
|
|
+// }
|
|
|
+// }
|
|
|
+//}
|
|
|
+//
|
|
|
+//// MARK: 订阅回调
|
|
|
+//
|
|
|
+//extension TSPurchaseTimesManager: SKPaymentTransactionObserver {
|
|
|
+// public func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
|
|
+// debugPrint("TSPurchaseTimesManager paymentQueue transactions.count = \(transactions.count)")
|
|
|
+// originalTransactionIdentifierDict.removeAll()
|
|
|
+// // 因为只有订阅类的购买项
|
|
|
+// for transaction in transactions {
|
|
|
+// if Self.purchaseNumProducts.contains(transaction.payment.productIdentifier) == false {
|
|
|
+// return
|
|
|
+// }
|
|
|
+//
|
|
|
+// switch transaction.transactionState {
|
|
|
+// case .purchasing:
|
|
|
+// // Transaction is being added to the server queue.
|
|
|
+// purchase(self, didChaged: .paying, object: nil,transaction:transaction)
|
|
|
+//
|
|
|
+// case .purchased:
|
|
|
+// SKPaymentQueue.default().finishTransaction(transaction)
|
|
|
+// // 同样的原始订单,只处理一次.
|
|
|
+// guard judgeWhether(transaction: transaction) else {
|
|
|
+// break
|
|
|
+// }
|
|
|
+//
|
|
|
+// // Transaction is in queue, user has been charged. Client should complete the transaction.
|
|
|
+// #if DEBUG
|
|
|
+// verifyPayResult(transaction: transaction, useSandBox: true)
|
|
|
+// #else
|
|
|
+// verifyPayResult(transaction: transaction, useSandBox: false)
|
|
|
+// #endif
|
|
|
+//
|
|
|
+// case .failed:
|
|
|
+//
|
|
|
+// SKPaymentQueue.default().finishTransaction(transaction)
|
|
|
+// var message = "Payment Failed"
|
|
|
+// if let error = transaction.error as? SKError{
|
|
|
+// if error.code == SKError.paymentCancelled {
|
|
|
+// message = "The subscription was canceled"
|
|
|
+// }else{
|
|
|
+// message = error.localizedDescription
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// purchase(self, didChaged: .payFail, object: message,transaction:transaction)
|
|
|
+// kPurchaseDefault.subscriptionApple(type: .result, jsonString: message)
|
|
|
+// case .restored:
|
|
|
+// SKPaymentQueue.default().finishTransaction(transaction)
|
|
|
+// // 同样的原始订单,只处理一次.
|
|
|
+// guard judgeWhether(transaction: transaction) else {
|
|
|
+// break
|
|
|
+// }
|
|
|
+//
|
|
|
+// // Transaction was restored from user's purchase history. Client should complete the transaction.
|
|
|
+// if let original = transaction.original,
|
|
|
+// original.transactionState == .purchased {
|
|
|
+// #if DEBUG
|
|
|
+// verifyPayResult(transaction: transaction, useSandBox: true)
|
|
|
+// #else
|
|
|
+// verifyPayResult(transaction: transaction, useSandBox: false)
|
|
|
+// #endif
|
|
|
+// } else {
|
|
|
+// purchase(self, didChaged: .restoreFail, object: "Failed to restore subscribe, please try again",transaction:transaction)
|
|
|
+// kPurchaseDefault.subscriptionApple(type: .result, jsonString: "Failed to restore subscribe, please try again")
|
|
|
+// }
|
|
|
+//
|
|
|
+// case .deferred: // The transaction is in the queue, but its final status is pending external action.
|
|
|
+// break
|
|
|
+// @unknown default:
|
|
|
+// SKPaymentQueue.default().finishTransaction(transaction)
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// public func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
|
|
|
+// purchase(self, didChaged: .restoreFail, object: nil,transaction:nil)
|
|
|
+// }
|
|
|
+//
|
|
|
+// public func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
|
|
|
+// if let trans = queue.transactions.first(where: { $0.transactionState == .purchased }) {
|
|
|
+// verifyPayResult(transaction: trans, useSandBox: false)
|
|
|
+// } else if queue.transactions.isEmpty {
|
|
|
+// purchase(self, didChaged: .restoreFail, object: "You don't have an active subscription",transaction:nil)
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// func judgeWhether(transaction: SKPaymentTransaction) -> Bool {
|
|
|
+// let id = transaction.original?.transactionIdentifier
|
|
|
+// if let id = id {
|
|
|
+// if let value = originalTransactionIdentifierDict[id] {
|
|
|
+// return false
|
|
|
+// }
|
|
|
+// originalTransactionIdentifierDict[id] = "1"
|
|
|
+// }
|
|
|
+// return true
|
|
|
+// }
|
|
|
+//}
|
|
|
+//
|
|
|
+//extension TSPurchaseTimesManager {
|
|
|
+// func verifyPayResult(transaction: SKPaymentTransaction, useSandBox: Bool) {
|
|
|
+// purchase(self, didChaged: .verifying, object: nil,transaction:transaction)
|
|
|
+//
|
|
|
+// guard let url = Bundle.main.appStoreReceiptURL,
|
|
|
+// let receiptData = try? Data(contentsOf: url) else {
|
|
|
+// purchase(self, didChaged: .verifyFail, object: "凭证文件为空",transaction:transaction)
|
|
|
+// return
|
|
|
+// }
|
|
|
+//
|
|
|
+// let requestContents = [
|
|
|
+// "receipt-data": receiptData.base64EncodedString(),
|
|
|
+// "password": kPurchaseDefault.AppleSharedKey,
|
|
|
+// ]
|
|
|
+// guard let requestData = try? JSONSerialization.data(withJSONObject: requestContents) else {
|
|
|
+// purchase(self, didChaged: .verifyFail, object: "凭证文件为空",transaction:transaction)
|
|
|
+// return
|
|
|
+// }
|
|
|
+//
|
|
|
+// let verifyUrlString = useSandBox ? PurchaseManager.Config.sandBoxUrl : PurchaseManager.Config.verifyUrl
|
|
|
+//
|
|
|
+// kPurchaseDefault.postRequest(urlString: verifyUrlString, httpBody: requestData) { [weak self] data, _ in
|
|
|
+// guard let self = self else { return }
|
|
|
+// if let data = data,
|
|
|
+// let jsonResponse = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
|
|
|
+// debugPrint("TSPurchaseTimesManager verifyPayResult = \(jsonResponse)")
|
|
|
+// let status = jsonResponse["status"]
|
|
|
+// if let status = status as? String, status == "21007" {
|
|
|
+// self.verifyPayResult(transaction: transaction, useSandBox: true)
|
|
|
+// } else if let status = status as? Int, status == 21007 {
|
|
|
+// self.verifyPayResult(transaction: transaction, useSandBox: true)
|
|
|
+// } else if let status = status as? String, status == "0" {
|
|
|
+// self.handlerPayResult(transaction: transaction, resp: jsonResponse)
|
|
|
+// } else if let status = status as? Int, status == 0 {
|
|
|
+// self.handlerPayResult(transaction: transaction, resp: jsonResponse)
|
|
|
+// } else {
|
|
|
+// self.purchase(self, didChaged: .verifyFail, object: "验证结果状态码错误:\(status.debugDescription)",transaction:transaction)
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// self.purchase(self, didChaged: .verifyFail, object: "验证结果为空",transaction:transaction)
|
|
|
+// debugPrint("TSPurchaseTimesManager 验证结果为空")
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// func handlerPayResult(transaction: SKPaymentTransaction, resp: [String: Any]) {
|
|
|
+//
|
|
|
+// //购买视频次数相关
|
|
|
+// //分析处理购买消耗品的逻辑处理
|
|
|
+// kPurchaseDefault.analyzeDataReceiptForPurchase(resp: resp)
|
|
|
+//
|
|
|
+// DispatchQueue.main.async {
|
|
|
+// self.purchase(self, didChaged: .paySuccess, object: nil,transaction:transaction)
|
|
|
+// }
|
|
|
+//
|
|
|
+// kPurchaseDefault.subscriptionApple(type: .result, jsonString: kPurchaseDefault.simplifyVerifyPayResult(resp: resp))
|
|
|
+// }
|
|
|
+//
|
|
|
+//}
|
|
|
+//
|
|
|
+//public extension TSPurchaseTimesManager {
|
|
|
+// func purchase(_ manager: TSPurchaseTimesManager, didChaged state: PremiumRequestState, object: Any?,transaction:SKPaymentTransaction?) {
|
|
|
+// if transaction == nil{
|
|
|
+// onPurchaseStateChanged?(manager, state, object)
|
|
|
+// }else if let productIdentifier = transaction?.payment.productIdentifier,productIdentifier == paymentProductIdentifier {
|
|
|
+// onPurchaseStateChanged?(manager, state, object)
|
|
|
+// }
|
|
|
+// }
|
|
|
+//}
|