Browse Source

【轻会员】内购加二次验证代码整理

lizhe 1 year ago
parent
commit
7e8ed111ef

+ 16 - 0
PDF Office/PDF Master.xcodeproj/project.pbxproj

@@ -1519,6 +1519,9 @@
 		ADBC376629CD86A000D93208 /* KMReadModelView.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ADBC376529CD86A000D93208 /* KMReadModelView.xcassets */; };
 		ADBC376729CD86A000D93208 /* KMReadModelView.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ADBC376529CD86A000D93208 /* KMReadModelView.xcassets */; };
 		ADBC376829CD86A000D93208 /* KMReadModelView.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ADBC376529CD86A000D93208 /* KMReadModelView.xcassets */; };
+		ADBE3C442A2892AC00271E30 /* KMInAppPurchaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADBE3C432A2892AC00271E30 /* KMInAppPurchaseManager.swift */; };
+		ADBE3C452A2892AC00271E30 /* KMInAppPurchaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADBE3C432A2892AC00271E30 /* KMInAppPurchaseManager.swift */; };
+		ADBE3C462A2892AC00271E30 /* KMInAppPurchaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADBE3C432A2892AC00271E30 /* KMInAppPurchaseManager.swift */; };
 		ADC075B629866962006C752F /* KMBatchConverPDFWordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADC075B529866962006C752F /* KMBatchConverPDFWordView.swift */; };
 		ADC075B729866962006C752F /* KMBatchConverPDFWordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADC075B529866962006C752F /* KMBatchConverPDFWordView.swift */; };
 		ADC075B829866962006C752F /* KMBatchConverPDFWordView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADC075B529866962006C752F /* KMBatchConverPDFWordView.swift */; };
@@ -3977,6 +3980,7 @@
 		ADBC375C29CC61E100D93208 /* KMReadModelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMReadModelView.swift; sourceTree = "<group>"; };
 		ADBC376029CC637900D93208 /* KMReadModelView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KMReadModelView.xib; sourceTree = "<group>"; };
 		ADBC376529CD86A000D93208 /* KMReadModelView.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = KMReadModelView.xcassets; sourceTree = "<group>"; };
+		ADBE3C432A2892AC00271E30 /* KMInAppPurchaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMInAppPurchaseManager.swift; sourceTree = "<group>"; };
 		ADC075B529866962006C752F /* KMBatchConverPDFWordView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMBatchConverPDFWordView.swift; sourceTree = "<group>"; };
 		ADC075B929866984006C752F /* KMBatchConverPDFWordView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KMBatchConverPDFWordView.xib; sourceTree = "<group>"; };
 		ADC075BF29866AE6006C752F /* KMBatchTextRecognitionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMBatchTextRecognitionView.swift; sourceTree = "<group>"; };
@@ -6528,6 +6532,14 @@
 			path = Source;
 			sourceTree = "<group>";
 		};
+		ADBE3C422A28924700271E30 /* InAppPurchase */ = {
+			isa = PBXGroup;
+			children = (
+				ADBE3C432A2892AC00271E30 /* KMInAppPurchaseManager.swift */,
+			);
+			path = InAppPurchase;
+			sourceTree = "<group>";
+		};
 		ADC075B42986693E006C752F /* Views */ = {
 			isa = PBXGroup;
 			children = (
@@ -6950,6 +6962,7 @@
 		ADE3C1CB29A5A79E00793B13 /* KMLightMember */ = {
 			isa = PBXGroup;
 			children = (
+				ADBE3C422A28924700271E30 /* InAppPurchase */,
 				AD53B70129ACC63D00D61E81 /* Tools */,
 				AD015FB529AB483200A57062 /* Config */,
 				ADF1569A29A63CAB001D1018 /* Source */,
@@ -10506,6 +10519,7 @@
 				9FAAA339290F72CC0046FFCE /* KMHistoryFileCollectionView.swift in Sources */,
 				BB2F18462A0C7E250003F65E /* KMConvertBaseView.swift in Sources */,
 				BB99ACCA292DEE6E0048AFD9 /* KMMergeTitleBar.swift in Sources */,
+				ADBE3C442A2892AC00271E30 /* KMInAppPurchaseManager.swift in Sources */,
 				BB4DD043299B291A00E80DF6 /* KMCloudNoNetworkView.swift in Sources */,
 				BB49ECF6293F44DC00C82CA2 /* KMConvertExcelWindowController.swift in Sources */,
 				BBC348432956A638008D2CD1 /* KMEditBackgroundController.swift in Sources */,
@@ -11125,6 +11139,7 @@
 				89E4E751296427C8002DBA6F /* NSURL_SKExtensions.m in Sources */,
 				9F221ED829A9EC0900978A59 /* KMFillSignTextPanel.swift in Sources */,
 				BBF38A5F294F42FF0086D025 /* KMWatermarkAdjectiveStepper.swift in Sources */,
+				ADBE3C452A2892AC00271E30 /* KMInAppPurchaseManager.swift in Sources */,
 				BB003027298CF7EC002DD1A0 /* KMPreferenceDisplayController.swift in Sources */,
 				F36AD77829642FE80015AD53 /* CPDFListView+UndoManager.m in Sources */,
 				BB89726A294DB41D0045787C /* KMWatermarkAdjectivePositionView.swift in Sources */,
@@ -11784,6 +11799,7 @@
 				F3B7DF9C2948565000333201 /* CPDFListHoverAnnotationViewController.m in Sources */,
 				9FDD0FB429534FEA000C4DAD /* KMGlobal.swift in Sources */,
 				BB2EDF78296ECE17003BCF58 /* KMPageEditInsertPageSizeItemView.swift in Sources */,
+				ADBE3C462A2892AC00271E30 /* KMInAppPurchaseManager.swift in Sources */,
 				BB6DD823293497B6001F0544 /* KMSecureEncryptModel.swift in Sources */,
 				89D2D2E0294C451400BFF5FE /* KMThumbnailViewController.swift in Sources */,
 				9FAAA334290BD0A20046FFCE /* KMHistoryFileCollectionViewItem.swift in Sources */,

+ 113 - 0
PDF Office/PDF Master/Class/KMLightMember/InAppPurchase/KMInAppPurchaseManager.swift

@@ -0,0 +1,113 @@
+//
+//  KMInAppPurchaseManager.swift
+//  PDF Master
+//
+//  Created by lizhe on 2023/6/1.
+//
+
+import Cocoa
+import StoreKit
+import AuthenticationServices
+
+class KMInAppPurchaseManager: NSObject {
+    public static let manager = KMInAppPurchaseManager()
+    
+    var availableProducts: [SKProduct] = []
+    
+    override init() {
+        super.init()
+        // 注册购买交易观察者
+        SKPaymentQueue.default().add(self)
+    }
+    
+    func fetchProducts() {
+        let productIdentifiers: Set<String> = ["com.yourapp.product1", "com.yourapp.product2"]
+        let request = SKProductsRequest(productIdentifiers: productIdentifiers)
+        request.delegate = self
+        request.start()
+    }
+    
+    func purchaseProduct(productIdentifier: String) {
+        guard let product = availableProducts.first(where: { $0.productIdentifier == productIdentifier }) else {
+            // 未找到匹配的产品
+            return
+        }
+        
+        let payment = SKPayment(product: product)
+        SKPaymentQueue.default().add(payment)
+    }
+}
+
+extension KMInAppPurchaseManager: SKProductsRequestDelegate {
+    func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
+        availableProducts = response.products
+        // 处理产品信息
+    }
+    
+    func request(_ request: SKRequest, didFailWithError error: Error) {
+        // 处理请求错误
+    }
+}
+
+extension KMInAppPurchaseManager: SKPaymentTransactionObserver {
+    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
+        for transaction in transactions {
+            switch transaction.transactionState {
+            case .purchased:
+                // 购买成功,进行本地二次验证
+                validatePurchase(transaction: transaction)
+            case .failed:
+                // 购买失败,处理错误
+                handleError(transaction: transaction)
+            case .restored:
+                // 恢复购买,进行本地二次验证
+                validatePurchase(transaction: transaction)
+            default:
+                break
+            }
+        }
+    }
+        
+    func validatePurchase(transaction: SKPaymentTransaction) {
+        // 获取购买凭证
+        if let receiptURL = Bundle.main.appStoreReceiptURL,
+           let receiptData = try? Data(contentsOf: receiptURL) {
+            // 进行本地二次验证
+            if let parsedReceipt = parseReceipt(receiptData: receiptData),
+               let purchase = parsedReceipt["in_app"] as? [[String: Any]],
+               let matchingPurchase = purchase.first(where: { $0["transaction_id"] as? String == transaction.transactionIdentifier }) {
+                // 验证购买凭证,进行相应的处理
+                if verifyPurchase(purchase: matchingPurchase) {
+                    // 购买凭证验证成功,进行购买成功的逻辑
+                    SKPaymentQueue.default().finishTransaction(transaction)
+                    // ...
+                } else {
+                    // 购买凭证验证失败,进行购买失败的逻辑
+                    SKPaymentQueue.default().finishTransaction(transaction)
+                    // ...
+                }
+            }
+        }
+    }
+    
+    func handleError(transaction: SKPaymentTransaction) {
+        // 处理购买失败的逻辑
+        SKPaymentQueue.default().finishTransaction(transaction)
+        // ...
+    }
+    
+    func verifyPurchase(purchase: [String: Any]) -> Bool {
+        // 执行购买凭证验证的逻辑,例如验证产品标识符、购买日期等
+        // 如果验证成功返回 true,否则返回 false
+        // ...
+        return true
+    }
+    
+    func parseReceipt(receiptData: Data) -> [String: Any]? {
+        guard let receipt = try? JSONSerialization.jsonObject(with: receiptData, options: []) as? [String: Any] else {
+            return nil
+        }
+        
+        return receipt
+    }
+}