| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- //
- // LNPurchaseManagerOld.swift
- // Lanu
- //
- // Created by OneeChan on 2025/12/29.
- //
- import Foundation
- import StoreKit
- import Foundation
- /// 充值状态回调
- typealias fetchCompletion = (Result<[SKProduct], LNPurchaseError>) -> Void
- /// 充值管理单例类(StoreKit 1)
- final class RechargeManager: NSObject {
- // MARK: - 单例
- static let shared = RechargeManager()
- private override init() {
- super.init()
-
- LNEventDeliver.addObserver(self)
- }
-
- // MARK: - 私有属性
- /// 商品信息缓存
- private var productCache: [String: SKProduct] = [:]
- private let lock = NSLock()
- /// 支付完成回调
- private var fetchCompletion: fetchCompletion?
- /// 监听交易队列
- private var paymentQueue: SKPaymentQueue { SKPaymentQueue.default() }
-
- // MARK: - 生命周期
- /// 启动监听(建议在 AppDelegate 或 SceneDelegate 中调用)
- private func startObserving() {
- paymentQueue.add(self)
- }
-
- /// 停止监听(建议在 App 退出时调用)
- private func stopObserving() {
- paymentQueue.remove(self)
- }
-
- // MARK: - 公开方法
- /// 加载充值商品信息
- /// - Parameters:
- /// - productIds: 商品ID数组
- /// - completion: 加载完成回调
- func loadRechargeProducts(productIds: [String], completion: fetchCompletion?) {
- // 过滤空ID
- let validIds = productIds.filter { !$0.isEmpty }
- guard !validIds.isEmpty else {
- completion?(.failure(.productNotFound))
- return
- }
-
- // 检查缓存
- lock.lock()
- let cachedProducts = validIds.compactMap { productCache[$0] }
- lock.unlock()
- if cachedProducts.count == validIds.count {
- completion?(.success(cachedProducts))
- return
- }
-
- // 从苹果服务器请求商品
- fetchCompletion = completion
- let request = SKProductsRequest(productIdentifiers: Set(validIds))
- request.delegate = self
- request.start()
- }
-
- /// 发起充值支付
- /// - Parameters:
- /// - productId: 商品ID
- /// - completion: 支付完成回调
- func startRecharge(goods: LNPurchaseGoodsVO) {
- // 检查支付是否可用
- guard SKPaymentQueue.canMakePayments() else {
- notifyPurchaseResult(err: .paymentInvalid)
- return
- }
- // 恢复未完成的交易
- restoreUnfinishedTransactions()
-
- // 加载商品并发起支付
- loadRechargeProducts(productIds: [goods.code]) { [weak self] result in
- guard let self = self else { return }
-
- switch result {
- case .success(let products):
- guard let product = products.first else {
- notifyPurchaseResult(err: .productNotFound)
- return
- }
-
- LNHttpManager.shared.createPurchase(id: goods.id) { [weak self] res, err in
- guard let self else { return }
- guard let res, err == nil else {
- notifyPurchaseResult(err: .createOrderfailed)
- return
- }
- // 创建支付请求
- // 保存当前回调
- let payment = SKMutablePayment(product: product)
- payment.applicationUsername = res.result
- LNUserDefaults[.purchaseOrderId] = res.result
- self.paymentQueue.add(payment)
- }
- case .failure(let error):
- notifyPurchaseResult(err: error)
- }
- }
- }
-
- /// 恢复未完成的交易
- private func restoreUnfinishedTransactions() {
- paymentQueue.restoreCompletedTransactions()
- }
-
- // MARK: - 私有方法
- private func validateReceipt(for transaction: SKPaymentTransaction) {
- // 1. 获取应用收据
- guard let receiptURL = Bundle.main.appStoreReceiptURL,
- FileManager.default.fileExists(atPath: receiptURL.path) else {
- notifyPurchaseResult(err: .receiptParseFailed)
- return
- }
-
- // 2. 读取收据数据
- do {
- let receiptData = try Data(contentsOf: receiptURL)
- let receiptString = receiptData.base64EncodedString(options: [])
-
- let orderId = transaction.payment.applicationUsername ?? LNUserDefaults[.purchaseOrderId, ""]
-
- LNHttpManager.shared.verifyPurchase(orderId: orderId, receipt: receiptString) { [weak self] err in
- guard let self else { return }
- let success = err == nil
- if success {
- notifyPurchaseResult(err: nil)
- Log.w("充值成功 - 商品ID: \(transaction.payment.productIdentifier)")
- LNPurchaseManager.shared.reloadWalletInfo()
-
- let productId = transaction.payment.productIdentifier
- if let (type, goods) = LNPurchaseManager.shared.goodsFro(productId) {
- LNStatisticManager.shared.reportPayment(type: type, amount: goods.coinRechargeAmount, currency: goods.currency, price: goods.amount, orderId: orderId)
- }
- } else {
- notifyPurchaseResult(err: .receiptVerifyFailed)
- Log.w("充值失败 - 收据验证失败")
- }
- // 结束交易
- paymentQueue.finishTransaction(transaction)
- }
- } catch {
- Log.w("收据验证失败: \(error)")
- notifyPurchaseResult(err: .unknownError(error))
- }
- }
- }
- extension RechargeManager: LNAccountManagerNotify {
- func onUserLogin() {
- startObserving()
- }
-
- func onUserLogout() {
- stopObserving()
- }
- }
- // MARK: - SKProductsRequestDelegate
- extension RechargeManager: SKProductsRequestDelegate {
- func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
- // 缓存商品信息
- let products = response.products
- lock.lock()
- products.forEach { productCache[$0.productIdentifier] = $0 }
- lock.unlock()
-
- // 处理无效商品ID
- let invalidIds = response.invalidProductIdentifiers
- if !invalidIds.isEmpty {
- Log.w("无效的商品ID: \(invalidIds)")
- }
-
- // 回调结果
- if !products.isEmpty {
- // 这里是加载商品的回调,需要匹配原始请求的completion
- // 注:实际使用时建议通过闭包捕获或使用更优雅的回调管理
- fetchCompletion?(.success(products))
- } else {
- Log.w("未找到对应商品")
- fetchCompletion?(.failure(.productNotFound))
- }
- fetchCompletion = nil
- }
-
- func request(_ request: SKRequest, didFailWithError error: Error) {
- Log.w("商品请求失败: \(error.localizedDescription)")
- // 匹配错误类型
- fetchCompletion?(.failure(.unknownError(error)))
- fetchCompletion = nil
- }
- }
- // MARK: - SKPaymentTransactionObserver
- extension RechargeManager: SKPaymentTransactionObserver {
- func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
- transactions.forEach { transaction in
- switch transaction.transactionState {
- case .purchased:
- // 交易完成,验证收据
- validateReceipt(for: transaction)
- case .failed:
- // 交易失败
- let error = transaction.error as NSError?
- if error?.code == SKError.paymentCancelled.rawValue {
- notifyPurchaseResult(err: .paymentCancelled)
- paymentQueue.finishTransaction(transaction)
- Log.w("用户取消支付")
- } else {
- notifyPurchaseResult(err: .unknownError(transaction.error ?? NSError(domain: "RechargeError", code: -1, userInfo: nil)))
- Log.w("交易失败: \(transaction.error?.localizedDescription ?? "未知错误")")
- }
- case .restored:
- // 恢复交易
- validateReceipt(for: transaction)
- case .purchasing, .deferred:
- // 交易中/延迟处理(如家长审核)
- Log.w("交易状态: \(transaction.transactionState.rawValue)")
-
- @unknown default:
- notifyPurchaseResult(err: .unknownError(NSError(domain: "RechargeError", code: -2, userInfo: nil)))
- Log.w("未知交易状态")
- }
- }
- }
-
- func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
- Log.w("恢复交易完成 - 共恢复 \(queue.transactions.count) 笔交易")
- }
-
- func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) {
- Log.w("恢复交易失败: \(error.localizedDescription)")
- notifyPurchaseResult(err: .unknownError(error))
- }
- }
- extension RechargeManager {
- private func notifyPurchaseResult(err: LNPurchaseError?) {
- LNEventDeliver.notifyEvent {
- ($0 as? LNPurchaseManagerNotify)?.onUserPurchaseResult(err: err)
- }
- }
- }
|