// // KMProductModel.swift // PDF Reader Pro // // Created by wanjun on 2024/11/6. // import Foundation import Combine #if !VERSION_DMG import StoreKit #endif @objc enum KMCompareTableType : Int { case trial = 0 // 试用比较表 case dmg_Base // DMG 购买比较表 case dmg_Upgrades1 // DMG 升级比较表 39.99 case dmg_Upgrades2 // DMG 升级比较表 49.99 case lite_Base // Lite 基础版 case lite_MacWindows // Lite Mac&Windows双平台高级版永久 case pro_Base // Pro 基础版 case pro_Advanced // Pro Mac单平台高级版永久 } @objc enum KMCompareProductType : Int { case free = 0 // 免费 case freeTrial // 试用 case allPlatformStandard // 全平台标准版年订阅 case dualPlatformAdvanced // Mac&Windows双平台高级版永久 case allPlatformAdvanced_6 // 全平台高级版6个月订阅 case allPlatformAdvanced_12 // 全平台高级版12个月订阅 case macPlatformAdvanced // MAC单平台高级版永久 } @objc enum KMPurchasedProductType : Int { case fourDevicesAllAccessPackNew6months_lite = 0 // 4_devices_all_access_pack_new_6months(订阅) case fourDevicesAllAccessPackNew12months_lite // 4_devices_all_access_pack_12months(订阅) // case allAccessPackNew6months_lite // all_access_pack_new_6months(订阅) // case allAccessPack12months_lite // all_access_pack_12months(订阅) // case allAccessPack6months_lite // all_access_pack_6months(订阅) case aiAllAccessPack1month_lite // ai_all_access_pack_1month(订阅) case aiAllAccessPack12month_lite // ai_all_access_pack_12month(订阅) case allAccessPackPermanent_lite // all_access_pack_permanent(永久) case advancedAddDevicesAllAccessPack12months_lite // advanced_add_devices_all_access_pack_12months(订阅) case advancedAdd2DevicesAllAccessPack12months_lite // advanced_add_2_devices_all_access_pack_12months(订阅) case aiAllAccessPack1month_pro // ai_all_access_pack_1month(订阅) case aiAllAccessPack12month_pro // ai_all_access_pack_1month(订阅) case pdfToOfficePackPermanent_pro // pdf_to_office_pack_permanent(永久) case fourDevicesAllAccessPack12months_pro // 4_devices_all_access_pack_12months(全平台高级年订阅) case standardAddDevicesAllAccessPack12months_pro // standard_add_devices_all_access_pack_12months(订阅) case advancedAddDevicesAllAccessPack12months_pro // advanced_add_devices_all_access_pack_12months(订阅) case advancedAdd2DevicesAllAccessPack12months_pro // advanced_add_2_devices_all_access_pack_12months(订阅) case pdfReaderProStandard_dmg // 全平台标准版年订阅 case pdfReaderProAdvanced_dmg // 全平台高级版年订阅 case pdfReaderProPermanent_dmg // Mac&Windows双平台高级版永久 case pdfReaderProAIAnnual_dmg // AI 年订阅 case pdfReaderProAIMonthly_dmg // AI 月订阅 case pdfToOffice_dmg // 转档包 永久 case add2Device_dmg // 多设备全平台 case add3Device_dmg // 单平台升级高级版 } typealias AppstorePurchaseComplete = (_ success: Bool,_ msg: String) -> Void @objcMembers class KMProductModel: ObservableObject { static let shared = KMProductModel() /** 比较表类型 */ @Published var state: KMCompareTableType = .trial /** 高级版半年 或 年订阅,true为年订阅,false为半年订阅,默认true为年订阅 */ @Published var isPurchaseSwitch: Bool = true // MARK: DMG Public Property /** DMG 版本所有已经上架产品记录(暂时无教育优惠) */ var dmgProductDatas: KMMemberProductResult? /** DMG 版本 已经登录用户 最后一次价格获取 */ var dmgLastGetProductPriceInfos: KMMemberProductResult? /** DMG 版本 已经登录用户 最后一次批量价格获取 */ var dmgLastGetBatchProductPriceInfos: KMMemberProductResult? /** DMG 版本 已经登录用户 最后一次验证商品优惠券价格获取 */ var dmgLastCheckCouponProductPriceInfos: KMMemberProductResult? /** DMG 版本 已经登录用户 最后一次创建的买断订单返回信息 */ var dmgLastCreatOrderProductInfos: KMMemberProductResult? /** DMG 版本 已经登录用户 最后一次创建的买断订单返回信息 */ var dmgLastCreatSubscriberProductInfos: KMMemberProductResult? // MARK: DMG Public Method func checkConnectionAvailable() -> Void { if KMMemberCenterManager.manager.isConnectionAvailable() == false { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Error Information", comment: "") alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() return } } /** @abstract 获取DMG服务器架上所有商品 (得到的价格是原始价格) @param */ func getDMGProductDatas( _ complete: @escaping KMMemberProductComplete) -> Void { checkConnectionAvailable() KMMemberCenterManager.manager.getListingProducts(isEducation: 0) { [weak self] success, result in guard let productsArrays : KMMemberProductResult = result else { return } self?.dmgProductDatas = productsArrays complete(success, result) } if KMMemberInfo.shared.isLogin { // getDMGProductPriceInfosForMember(productId: "SP2024102300004", isEducation: 0) { [weak self] success, result in // // // } // getDMGBatchProductPriceInfosForMember(productId: "SP2024102300004", num: 10) { [weak self] success, result in // // // } // getDMGProductListInfosForMember(orderStatus: 0) { [weak self] success, result in // // } //创建买断订单 // creatOrder(productId: "SP2024102300004", paymentMethod: 0, price: "119.99", discountFlag: 0, couponCode: "", num: 1) { [weak self] success, result in // // } //创建订阅订单(创建买断订单后会报错已经是购买用户,不能重复购买) // createSubscriber(productId: "SP2024102300003", paymentMethod: 0, price: "99.99", discountFlag: 0, couponCode: "", num: 1) { [weak self] success, result in // // } // getDMGProductOrderIdInfosForMember(orderId: "94b10d5f1ca193948e005503bff0df11") { [weak self] success, result in // // } } } /** @abstract 获取DMG产品价格(美元) */ func getDMGPrice(productCode: String) -> String { guard let productModels = dmgProductDatas?.listingProducts else { return "" } for model in productModels { if model.code == productCode { if model.upgradePriceString?.isEmpty == false { return String(format: "%.2f", Float(model.upgradePriceString ?? "0") ?? 0) } else if model.displayPriceString?.isEmpty == false { if model.displayPriceString == "0.00" { return String(format: "%.2f", Float(model.priceString ?? "0") ?? 0) } else { return String(format: "%.2f", Float(model.displayPriceString ?? "0") ?? 0) } } else { return String(format: "%.2f", Float(model.priceString ?? "0") ?? 0) } } } return "" } /** @abstract 获取DMG产品价格(人民币) */ func getDMGCNYPrice(productCode: String) -> String { guard let productModels = dmgProductDatas?.listingProducts else { return "" } for model in productModels { if model.code == productCode { if model.cnyUpgradePriceString?.isEmpty == false { return String(format: "%.2f", Float(model.cnyUpgradePriceString ?? "0") ?? 0) } else if model.displayCnyPriceString?.isEmpty == false { if model.displayCnyPriceString == "0.00" { return String(format: "%.2f", Float(model.cnyPriceString ?? "0") ?? 0) } else { return String(format: "%.2f", Float(model.displayCnyPriceString ?? "0") ?? 0) } } else { return String(format: "%.2f", Float(model.cnyPriceString ?? "0") ?? 0) } } } return "" } /** @abstract 获取DMG产品折扣价格(美元) */ func getDMGDisplayPrice(productCode: String) -> String { guard let productModels = dmgProductDatas?.listingProducts else { return "" } for model in productModels { if model.code == productCode { return String(format: "%.2f", Float(model.displayPriceString ?? "0") ?? 0) } } return "" } /** @abstract 获取DMG产品折扣价格(人民币) */ func getDMGDisplayCNYPrice(productCode: String) -> String { guard let productModels = dmgProductDatas?.listingProducts else { return "" } for model in productModels { if model.code == productCode { return String(format: "%.2f", Float(model.displayCnyPriceString ?? "0") ?? 0) } } return "" } /** @abstract 获取登录用户价格(建立订单时需要用到) @param productId 购买的产品id @param isEducation 是否教育优惠 @param complete 回调 */ func getDMGProductPriceInfosForMember(productId: String, isEducation: Int, _ complete: @escaping KMMemberProductComplete) { checkConnectionAvailable() //暂时无教育优惠,先固定传 0 KMMemberCenterManager.manager.getProductPriceForBuy(productId: productId, isEducation: 0, userId:KMMemberInfo.shared.userID) { [weak self] success, result in if success { guard let productsArrays : KMMemberProductResult = result else { complete(false, result) return } self?.dmgLastGetProductPriceInfos = productsArrays complete(true, productsArrays) } else { complete(false, result) } } } /** @abstract 获取批量阶段购买价格(建立订单时需要用到) @param productId 购买的产品id @param num 批量个数 @param complete 回调 */ func getDMGBatchProductPriceInfosForMember(productId: String, num: Int, _ complete: @escaping KMMemberProductComplete) { checkConnectionAvailable() KMMemberCenterManager.manager.getBatchProductPrice(productId: productId, num: num) { [weak self] success, result in if success { guard let productsArrays : KMMemberProductResult = result else { complete(false, result) return } self?.dmgLastGetBatchProductPriceInfos = productsArrays complete(true, productsArrays) } else { complete(false, result) } } } /** @abstract 验证商品优惠券(建立订单时需要用到) @param productId 购买的产品id @param code 优惠券 @param complete 回调 */ func getDMGCheckCouponProductPriceInfosForMember(productId: String, code: String, _ complete: @escaping KMMemberProductComplete) { checkConnectionAvailable() KMMemberCenterManager.manager.checkCoupon(productId: productId, userId: KMMemberInfo.shared.userID, code: code) { [weak self] success, result in if success { guard let productsArrays : KMMemberProductResult = result else { complete(false, result) return } self?.dmgLastCheckCouponProductPriceInfos = productsArrays complete(true, productsArrays) } else { complete(false, result) } } } /** @abstract 获取订单列表 @param orderStatus 0全部1待支付 @param complete 回调 */ func getDMGProductListInfosForMember(orderStatus: Int, _ complete: @escaping KMMemberRequestInfoComplete) { checkConnectionAvailable() KMMemberCenterManager.manager.getOrderListByStatus(orderStatus: orderStatus) { [weak self] success, result in if success { guard let productsInfos : NSDictionary = result else { complete(false, result) return } complete(true, productsInfos) } else { complete(false, result) } } } /** @abstract 创建订单(买断) @param productId 产品id @param paymentMethod 支付方式 PAYPAL(0),ALIPAY(1),WXPAY(2),PADDLE(3) @param price 价格 @param discountFlag 0原价,1优惠券,2升级,3教育优惠,4批量购买,5黑五折扣 @param couponCode 优惠卷 @param num 批量购买数量 @param complete 回调 */ func creatOrder(productId: String, paymentMethod: Int, price: String, discountFlag: Int, couponCode: String, num: Int, _ complete: @escaping KMMemberProductComplete) { checkConnectionAvailable() KMMemberCenterManager.manager.createOrder(productId: productId, paymentMethod: paymentMethod, price: price, discountFlag: discountFlag, couponCode: couponCode, num: num) { [weak self] success, result in if success { guard let productsArrays : KMMemberProductResult = result else { complete(false, result) return } self?.dmgLastCreatOrderProductInfos = productsArrays complete(true, productsArrays) } else { complete(false, result) } } } /** @abstract 创建订单(订阅) @param productId 产品id @param paymentMethod 支付方式 PAYPAL(0),ALIPAY(1),WXPAY(2),PADDLE(3) @param price 价格 @param discountFlag 0原价,1优惠券,2升级,3教育优惠,4批量购买,5黑五折扣 @param couponCode 优惠卷 @param num 批量购买数量 @param complete 回调 */ func createSubscriber(productId: String, paymentMethod: Int, price: String, discountFlag: Int, couponCode: String, num: Int, _ complete: @escaping KMMemberProductComplete) { checkConnectionAvailable() KMMemberCenterManager.manager.createSubscriber(productId: productId, paymentMethod: paymentMethod, price: price, discountFlag: discountFlag, couponCode: couponCode, num: num) { [weak self] success, result in if success { guard let productsArrays : KMMemberProductResult = result else { complete(false, result) return } self?.dmgLastCreatSubscriberProductInfos = productsArrays complete(true, productsArrays) } else { complete(false, result) } } } /** @abstract 支付后查询订单状态 @param productId 购买的产品id @param complete 回调 */ func getDMGProductOrderIdInfosForMember(orderId: String, _ complete: @escaping KMMemberRequestInfoComplete) { checkConnectionAvailable() KMMemberCenterManager.manager.getStateByOrderId(orderId: orderId) { [weak self] success, result in if success { guard let productsInfos : NSDictionary = result else { complete(false, result) return } complete(true, productsInfos) } else { complete(false, result) } } } // MARK: Public Method /** @abstract 根据当前权益获取比较表类型 @param */ func getCurrentComparisonTableType() -> Void { let userScenarioType = KMMemberInfo.shared.userScenarioType let platforms = KMMemberInfo.shared.vip_platforms let platformsArray = platforms .components(separatedBy: ",") .map { $0.trimmingCharacters(in: .whitespaces) } if userScenarioType == .lite_type1 || userScenarioType == .lite_type3 || userScenarioType == .lite_type11 || userScenarioType == .lite_type4 || userScenarioType == .lite_type5 || userScenarioType == .lite_type9 || userScenarioType == .lite_type13 || userScenarioType == .lite_type7 || userScenarioType == .lite_type8 { if userScenarioType == .lite_type1 { state = .trial } else if userScenarioType == .lite_type3 || userScenarioType == .lite_type11 { state = .lite_Base } else if userScenarioType == .lite_type4 || userScenarioType == .lite_type5 || userScenarioType == .lite_type9 || userScenarioType == .lite_type13 { state = .lite_MacWindows } else if userScenarioType == .lite_type7 || userScenarioType == .lite_type8 { if KMMemberInfo.shared.vip_paymentModel == "1" && KMMemberInfo.shared.vip_cycle == 4 && platformsArray.count == 4 { state = .lite_MacWindows } else { state = .lite_Base } } } else if userScenarioType == .pro_type1 || userScenarioType == .pro_type3 || userScenarioType == .pro_type4 { if userScenarioType == .pro_type1 || userScenarioType == .pro_type4 { state = .pro_Advanced } else if userScenarioType == .pro_type3 { state = .pro_Base } } else if userScenarioType == .dmg_type4 || userScenarioType == .dmg_type5 || userScenarioType == .dmg_type6 || userScenarioType == .dmg_type7 || userScenarioType == .dmg_type8 || userScenarioType == .dmg_type9 || userScenarioType == .dmg_type10 || userScenarioType == .dmg_type11 || userScenarioType == .dmg_type12 || userScenarioType == .dmg_type13 || userScenarioType == .dmg_type14 || userScenarioType == .dmg_type15 || userScenarioType == .dmg_type16 || userScenarioType == .dmg_type17 || userScenarioType == .dmg_type18 || userScenarioType == .dmg_type19 || userScenarioType == .dmg_type20 || userScenarioType == .dmg_type21 || userScenarioType == .dmg_type22 || userScenarioType == .dmg_type23 || userScenarioType == .dmg_type24 || userScenarioType == .dmg_type25 || userScenarioType == .dmg_type26 || userScenarioType == .dmg_type27 || userScenarioType == .dmg_type28 || userScenarioType == .dmg_type29 || userScenarioType == .dmg_type30 || userScenarioType == .dmg_type31 || userScenarioType == .dmg_type32 || userScenarioType == .dmg_type33 || userScenarioType == .dmg_type34 || userScenarioType == .dmg_type35 || userScenarioType == .dmg_type36 || userScenarioType == .dmg_type37 || userScenarioType == .dmg_type38 || userScenarioType == .dmg_type39 || userScenarioType == .dmg_type40 || userScenarioType == .dmg_type41 || userScenarioType == .dmg_type42 || userScenarioType == .dmg_type43 || userScenarioType == .dmg_type44 || userScenarioType == .dmg_type45 || userScenarioType == .dmg_type46 || userScenarioType == .dmg_type47 || userScenarioType == .dmg_type48 { if userScenarioType == .dmg_type4 || userScenarioType == .dmg_type19 || userScenarioType == .dmg_type34 { state = .trial } else if userScenarioType == .dmg_type5 || userScenarioType == .dmg_type28 || userScenarioType == .dmg_type43 { state = .dmg_Upgrades1 } else if userScenarioType == .dmg_type6 || userScenarioType == .dmg_type7 || userScenarioType == .dmg_type29 || userScenarioType == .dmg_type30 || userScenarioType == .dmg_type44 || userScenarioType == .dmg_type45 { state = .dmg_Upgrades2 } else if userScenarioType == .dmg_type11 || userScenarioType == .dmg_type18 || userScenarioType == .dmg_type22 || userScenarioType == .dmg_type33 || userScenarioType == .dmg_type37 || userScenarioType == .dmg_type48 { state = .dmg_Base } } } /** 对应商品价格 */ func getProductPrice(_ type: KMPurchasedProductType) -> String { #if VERSION_FREE #if VERSION_DMG // DMG if type == .pdfReaderProStandard_dmg { if NSLocalizedString("USD", tableName: "MemberCenterLocalizable", comment: "") == "USD" { return String(format: "USD $%@", getDMGPrice(productCode: KMStandardAnnualSubscriptionCodeKey_DMG)) } else { return String(format: "CNY ¥%@", getDMGCNYPrice(productCode: KMStandardAnnualSubscriptionCodeKey_DMG)) } } else if type == .pdfReaderProAdvanced_dmg { if state == .dmg_Base { if isBlackFive { if NSLocalizedString("USD", tableName: "MemberCenterLocalizable", comment: "") == "USD" { return String(format: "USD $%@", getDMGPrice(productCode: KMAdvancedAnnualSubscriptionBlackFiveCodeKey_DMG)) } else { return String(format: "CNY ¥%@", getDMGCNYPrice(productCode: KMAdvancedAnnualSubscriptionBlackFiveCodeKey_DMG)) } } else { if NSLocalizedString("USD", tableName: "MemberCenterLocalizable", comment: "") == "USD" { return String(format: "USD $%@", getDMGPrice(productCode: KMAdvancedAnnualSubscriptionCodeKey_DMG)) } else { return String(format: "CNY ¥%@", getDMGCNYPrice(productCode: KMAdvancedAnnualSubscriptionCodeKey_DMG)) } } } else { if KMMemberInfo.shared.canTrail && state == .trial { if NSLocalizedString("USD", tableName: "MemberCenterLocalizable", comment: "") == "USD" { return String(format: "USD $%@", getDMGPrice(productCode: KMAdvancedAnnualSubscriptionTrailCodeKey_DMG)) } else { return String(format: "CNY ¥%@", getDMGCNYPrice(productCode: KMAdvancedAnnualSubscriptionTrailCodeKey_DMG)) } } else { if NSLocalizedString("USD", tableName: "MemberCenterLocalizable", comment: "") == "USD" { return String(format: "USD $%@", getDMGPrice(productCode: KMAdvancedAnnualSubscriptionCodeKey_DMG)) } else { return String(format: "CNY ¥%@", getDMGCNYPrice(productCode: KMAdvancedAnnualSubscriptionCodeKey_DMG)) } } } } else if type == .pdfReaderProPermanent_dmg { if state == .dmg_Base { if isBlackFive { if NSLocalizedString("USD", tableName: "MemberCenterLocalizable", comment: "") == "USD" { return String(format: "USD $%@", getDMGPrice(productCode: KMAdvancedPermanentBlackFiveCodeKey_DMG)) } else { return String(format: "CNY ¥%@", getDMGCNYPrice(productCode: KMAdvancedPermanentBlackFiveCodeKey_DMG)) } } else { if NSLocalizedString("USD", tableName: "MemberCenterLocalizable", comment: "") == "USD" { return String(format: "USD $%@", getDMGPrice(productCode: KMAdvancedPermanentCodeKey_DMG)) } else { return String(format: "CNY ¥%@", getDMGCNYPrice(productCode: KMAdvancedPermanentCodeKey_DMG)) } } } else { } } else if type == .pdfReaderProAIAnnual_dmg { if NSLocalizedString("USD", tableName: "MemberCenterLocalizable", comment: "") == "USD" { return String(format: "USD $%@", getDMGPrice(productCode: KMAISubscriptionYearTrailCodeKey_DMG)) } else { return String(format: "CNY ¥%@", getDMGCNYPrice(productCode: KMAISubscriptionYearTrailCodeKey_DMG)) } } else if type == .pdfReaderProAIMonthly_dmg { if NSLocalizedString("USD", tableName: "MemberCenterLocalizable", comment: "") == "USD" { return String(format: "USD $%@", getDMGPrice(productCode: KMAISubscriptionMonthCodeKey_DMG)) } else { return String(format: "CNY ¥%@", getDMGCNYPrice(productCode: KMAISubscriptionMonthCodeKey_DMG)) } } else if type == .pdfToOffice_dmg { } else if type == .add2Device_dmg { } else if type == .add3Device_dmg { } #else // AppStore 免费版本 if type == .fourDevicesAllAccessPackNew6months_lite { if let product = IAPProductsManager.default().fourDevicesAllAccessPackNew6Months_lite, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().fourDevicesAllAccessPackNew6Months_lite.price() } } else if type == .fourDevicesAllAccessPackNew12months_lite { if let product = IAPProductsManager.default().fourDevicesAllAccessPackNew12months_lite, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().fourDevicesAllAccessPackNew12months_lite.price() } } else if type == .aiAllAccessPack1month_lite { if let product = IAPProductsManager.default().aiAllAccessPack1month_lite, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().aiAllAccessPack1month_lite.price() } } else if type == .aiAllAccessPack12month_lite { if let product = IAPProductsManager.default().aiAllAccessPack12month_lite, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().aiAllAccessPack12month_lite.price() } } else if type == .allAccessPackPermanent_lite { if let product = IAPProductsManager.default().allAccessPackPermanent_lite, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().allAccessPackPermanent_lite.price() } } else if type == .advancedAddDevicesAllAccessPack12months_lite { if let product = IAPProductsManager.default().advancedAddDevicesAllAccessPack12months_lite, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().advancedAddDevicesAllAccessPack12months_lite.price() } } else if type == .advancedAdd2DevicesAllAccessPack12months_lite { if let product = IAPProductsManager.default().advancedAdd2DevicesAllAccessPack12months_lite, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().advancedAdd2DevicesAllAccessPack12months_lite.price() } } #endif #else // AppStore 付费版 if type == .aiAllAccessPack1month_pro { if let product = IAPProductsManager.default().aiAllAccessPack1month_pro, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().aiAllAccessPack1month_pro.price() } } else if type == .aiAllAccessPack12month_pro { if let product = IAPProductsManager.default().aiAllAccessPack12month_pro, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().aiAllAccessPack12month_pro.price() } } else if type == .pdfToOfficePackPermanent_pro { if let product = IAPProductsManager.default().pdfToOfficePackPermanent_pro, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().pdfToOfficePackPermanent_pro.price() } } else if type == .fourDevicesAllAccessPack12months_pro { if let product = IAPProductsManager.default().fourDevicesAllAccessPack12months_pro, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().fourDevicesAllAccessPack12months_pro.price() } } else if type == .standardAddDevicesAllAccessPack12months_pro { if let product = IAPProductsManager.default().standardAddDevicesAllAccessPack12months_pro, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().standardAddDevicesAllAccessPack12months_pro.price() } } else if type == .advancedAddDevicesAllAccessPack12months_pro { if let product = IAPProductsManager.default().advancedAddDevicesAllAccessPack12months_pro, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().advancedAddDevicesAllAccessPack12months_pro.price() } } else if type == .advancedAdd2DevicesAllAccessPack12months_pro { if let product = IAPProductsManager.default().advancedAdd2DevicesAllAccessPack12months_pro, product.isOffers { return product.offersPrice() } else { return IAPProductsManager.default().advancedAdd2DevicesAllAccessPack12months_pro.price() } } #endif return "" } func appstorePurchaseAction(_ tag: Int, _ complete: @escaping AppstorePurchaseComplete) -> Void { if state == .dmg_Base { var code = "" if tag == 1 { code = KMStandardAnnualSubscriptionCodeKey_DMG } else if tag == 3 { if isBlackFive { code = KMAdvancedPermanentBlackFiveCodeKey_DMG } else { code = KMAdvancedPermanentCodeKey_DMG } } else { if isBlackFive { code = KMAdvancedAnnualSubscriptionBlackFiveCodeKey_DMG } else { code = KMAdvancedAnnualSubscriptionCodeKey_DMG } } #if VERSION_DMG let embeddedWC = KMPurchaseEmbeddedWindowController.currentCode(code) embeddedWC.showWindow(nil) embeddedWC.window?.center() #endif } else if state == .dmg_Upgrades1 { #if VERSION_DMG let embeddedWC = KMPurchaseEmbeddedWindowController.currentCode(KMAdvancedAnnualSubscriptionCodeKey_DMG) embeddedWC.showWindow(nil) embeddedWC.window?.center() #endif } else if state == .dmg_Upgrades2 { #if VERSION_DMG let embeddedWC = KMPurchaseEmbeddedWindowController.currentCode(KMAdvancedAnnualSubscriptionCodeKey_DMG) embeddedWC.showWindow(nil) embeddedWC.window?.center() #endif } else if state == .lite_Base { if tag == 0 { if isPurchaseSwitch { membershipPurchase(.fourDevicesAllAccessPackNew12months_lite) } else { membershipPurchase(.fourDevicesAllAccessPackNew6months_lite) } } else if tag == 3 { membershipPurchase(.allAccessPackPermanent_lite) } else { membershipPurchase(.fourDevicesAllAccessPackNew12months_lite) } } else if state == .lite_MacWindows { if tag == 2 { let platforms = KMMemberInfo.shared.vip_platforms let platformsArray = platforms .components(separatedBy: ",") .map { $0.trimmingCharacters(in: .whitespaces) } if KMMemberInfo.shared.userScenarioType == .lite_type5 { if platformsArray.count == 1 { membershipPurchase(.advancedAddDevicesAllAccessPack12months_lite) } else if platformsArray.count == 2 { membershipPurchase(.advancedAdd2DevicesAllAccessPack12months_lite) } } else { if platformsArray.count == 1 { membershipPurchase(.advancedAddDevicesAllAccessPack12months_lite) } else if platformsArray.count == 2 { membershipPurchase(.advancedAdd2DevicesAllAccessPack12months_lite) } else { membershipPurchase(.advancedAdd2DevicesAllAccessPack12months_lite) } } } } else if state == .pro_Base { if KMMemberInfo.shared.userScenarioType == .pro_type3 { if tag == 2 { membershipPurchase(.standardAddDevicesAllAccessPack12months_pro) } else if tag == 3 { membershipPurchase(.pdfToOfficePackPermanent_pro) } } } else if state == .pro_Advanced { let platforms = KMMemberInfo.shared.vip_platforms let platformsArray = platforms .components(separatedBy: ",") .map { $0.trimmingCharacters(in: .whitespaces) } if KMMemberInfo.shared.userScenarioType == .pro_type1 { if platformsArray.count == 1 { membershipPurchase(.advancedAddDevicesAllAccessPack12months_pro) } else if platformsArray.count == 2 { membershipPurchase(.advancedAdd2DevicesAllAccessPack12months_pro) } else if KMMemberInfo.shared.vip_levels == "1" { membershipPurchase(.advancedAddDevicesAllAccessPack12months_pro) } else { membershipPurchase(.advancedAdd2DevicesAllAccessPack12months_pro) } } else if KMMemberInfo.shared.userScenarioType == .pro_type4 { if platformsArray.count == 1 { membershipPurchase(.advancedAddDevicesAllAccessPack12months_pro) } else if platformsArray.count == 2 { membershipPurchase(.advancedAdd2DevicesAllAccessPack12months_pro) } else { membershipPurchase(.advancedAdd2DevicesAllAccessPack12months_pro) } } } else { #if VERSION_FREE #if VERSION_DMG // DMG var code = "" if state == .dmg_Base { if isBlackFive { code = KMAdvancedAnnualSubscriptionBlackFiveCodeKey_DMG } else { code = KMAdvancedAnnualSubscriptionCodeKey_DMG } } else { if KMMemberInfo.shared.canTrail && state == .trial { code = KMAdvancedAnnualSubscriptionTrailCodeKey_DMG } else { code = KMAdvancedAnnualSubscriptionCodeKey_DMG } } let embeddedWC = KMPurchaseEmbeddedWindowController.currentCode(code) embeddedWC.showWindow(nil) embeddedWC.window?.center() #else // AppStore 免费版本 if tag == 2 { membershipPurchase(.fourDevicesAllAccessPackNew12months_lite) } #endif #else // AppStore 付费版 #endif } } func appStoreEquityVerification(_ notification: Notification,_ complete: @escaping KMMemberProductComplete) -> Void { #if VERSION_FREE #if VERSION_DMG // DMG #else // AppStore 免费版本 if let userInfo = notification.object as? SKPaymentTransaction, let transactionId = userInfo.transactionIdentifier as? String, let productId = userInfo.payment.productIdentifier as? String { print("Transaction ID: \(transactionId)") print("product ID: \(productId)") var productCode = "" var isSubscribed = false if productId == "com.pdfreaderpro.mac_free.member.all_access_pack_advanced_6months.001" { productCode = "advanced-annual-subscription-six-month" if IAPProductsManager.default().fourDevicesAllAccessPackNew6Months_lite.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac_free.member.all_access_pack_advanced_annual.001" { productCode = "advanced-annual-subscription" if IAPProductsManager.default().fourDevicesAllAccessPackNew12months_lite.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac_free.member.all_access_pack_new_6months.001" { productCode = "advanced-annual-subscription-six-month" if IAPProductsManager.default().allAccessPackNew6months_lite.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac_free.member.all_access_pack_12months.001" { productCode = "advanced-annual-subscription" if IAPProductsManager.default().allAccessPack12months_lite.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac_free.member.all_access_pack_6months.001" { productCode = "advanced-annual-subscription-six-month" if IAPProductsManager.default().allAccessPack6months_lite.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac_free.member.ai_pack_1_month" { productCode = "ai-subscription-month" if IAPProductsManager.default().aiAllAccessPack1month_lite.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac_free.member.ai_pack_12_month" { productCode = "ai-subscription-year-trail" if IAPProductsManager.default().aiAllAccessPack12month_lite.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac_free.member.all_access_pack_advanced_permanent_license.001" { productCode = "advanced-permanent" if IAPProductsManager.default().allAccessPackPermanent_lite.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac_free.member.advanced_add_devices_all_access_pack_advanced_annual.001" { productCode = "advanced-annual-subscription-single-upgrade" if IAPProductsManager.default().advancedAddDevicesAllAccessPack12months_lite.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac_free.member.advanced_add_2_devices_all_access_pack_advanced_annual.001" { productCode = "advanced-annual-subscription-multi-upgrade" if IAPProductsManager.default().advancedAdd2DevicesAllAccessPack12months_lite.isSubscribed { isSubscribed = true } } if isSubscribed { KMMemberCenterManager.manager.appStoreEquityVerification(applePayProductId: productId, transactionId: transactionId, productCode: productCode) { success, result in DispatchQueue.main.async { if success { complete(true, result) } else { complete(false, result) } } } } } else { print(NSLocalizedString("Order does not exist.", tableName: "MemberCenterLocalizable", comment: "")) } #endif #else // AppStore 付费版 if let userInfo = notification.object as? SKPaymentTransaction, let transactionId = userInfo.transactionIdentifier as? String, let productId = userInfo.payment.productIdentifier as? String { print("Transaction ID: \(transactionId)") print("product ID: \(productId)") var productCode = "" var isSubscribed = false if productId == "com.pdfreaderpro.mac.ai_pack_1_month" { productCode = "ai-subscription-month" if IAPProductsManager.default().aiAllAccessPack1month_pro.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac.ai_pack_12_month" { productCode = "ai-subscription-year-trail" if IAPProductsManager.default().aiAllAccessPack12month_pro.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac.pdf_to_office_pack_permanent_license.001" { productCode = "advanced-permanent-mac-upgrade" if IAPProductsManager.default().pdfToOfficePackPermanent_pro.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac.all_access_pack_advanced_annual.001" { productCode = "advanced-permanent-mac-upgrade" if IAPProductsManager.default().fourDevicesAllAccessPack12months_pro.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac.standard_add_devices_all_access_pack_advanced_annual.001" { productCode = "advanced-annual-subscription-standard-upgrade" if IAPProductsManager.default().standardAddDevicesAllAccessPack12months_pro.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac.advanced_add_devices_all_access_pack_advanced_annual.001" { productCode = "advanced-annual-subscription-single-upgrade" if IAPProductsManager.default().advancedAddDevicesAllAccessPack12months_pro.isSubscribed { isSubscribed = true } } else if productId == "com.pdfreaderpro.mac.advanced_add_2_devices_all_access_pack_advanced_annual.001" { productCode = "advanced-annual-subscription-multi-upgrade" if IAPProductsManager.default().advancedAdd2DevicesAllAccessPack12months_pro.isSubscribed { isSubscribed = true } } if isSubscribed { KMMemberCenterManager.manager.appStoreEquityVerification(applePayProductId: productId, transactionId: transactionId, productCode: productCode) { success, result in if success { complete(true, result) } else { complete(false, result) } } } } else { print(NSLocalizedString("Order does not exist.", tableName: "MemberCenterLocalizable", comment: "")) } #endif } var isCancelAutoRenew: Bool { return IAPProductsManager.default().isCancelAutoRenew() } var isShowSale: Bool { if #available(macOS 10.14.4, *), isCancelAutoRenew { let manager = IAPProductsManager.default() let isSubscribed_newlyMonth = manager?.allAccessPackNew6months_lite.isSubscribed ?? false let isSubscribed_year = manager?.allAccessPack12months_lite.isSubscribed ?? false if isSubscribed_newlyMonth || isSubscribed_year { return false } if let info = KMAdvertisementManager.manager.info.StoreUserRecovery?.content?.first, !(info.show! as NSString).boolValue { return false } return true } return false } // MARK: Private Method /** 会员购买 */ private func membershipPurchase(_ type: KMPurchasedProductType) -> Void { #if !VERSION_DMG if type == .fourDevicesAllAccessPackNew6months_lite || type == .fourDevicesAllAccessPackNew12months_lite { if isPurchaseSwitch { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().fourDevicesAllAccessPackNew12months_lite, discount: isCancelAutoRenew) } else { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().fourDevicesAllAccessPackNew6Months_lite, discount: isCancelAutoRenew) } } else if type == .aiAllAccessPack1month_lite { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().aiAllAccessPack1month_lite, discount: isCancelAutoRenew) } else if type == .aiAllAccessPack12month_lite { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().aiAllAccessPack12month_lite, discount: isCancelAutoRenew) } else if type == .allAccessPackPermanent_lite { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().allAccessPackPermanent_lite, discount: isCancelAutoRenew) } else if type == .advancedAddDevicesAllAccessPack12months_lite { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().advancedAddDevicesAllAccessPack12months_lite, discount: isCancelAutoRenew) } else if type == .advancedAdd2DevicesAllAccessPack12months_lite { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().advancedAdd2DevicesAllAccessPack12months_lite, discount: isCancelAutoRenew) } else if type == .aiAllAccessPack1month_pro { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().aiAllAccessPack1month_pro, discount: isCancelAutoRenew) } else if type == .aiAllAccessPack12month_pro { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().aiAllAccessPack12month_pro, discount: isCancelAutoRenew) } else if type == .pdfToOfficePackPermanent_pro { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().pdfToOfficePackPermanent_pro, discount: isCancelAutoRenew) } else if type == .fourDevicesAllAccessPack12months_pro { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().fourDevicesAllAccessPack12months_pro, discount: isCancelAutoRenew) } else if type == .standardAddDevicesAllAccessPack12months_pro { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().standardAddDevicesAllAccessPack12months_pro, discount: isCancelAutoRenew) } else if type == .advancedAddDevicesAllAccessPack12months_pro { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().advancedAddDevicesAllAccessPack12months_pro, discount: isCancelAutoRenew) } else if type == .advancedAdd2DevicesAllAccessPack12months_pro { IAPProductsManager.default().makeSubProduct(IAPProductsManager.default().advancedAdd2DevicesAllAccessPack12months_pro, discount: isCancelAutoRenew) } #endif } // MARK: Action Method /** 恢复购买 */ func productRestore() -> Void { IAPProductsManager.default().restoreSubscriptions() } func privacyPolicyAction() -> Void { NSWorkspace.shared.open(URL(string: "https://www.pdfreaderpro.com/privacy-policy")!) } func termOfSerAction() -> Void { NSWorkspace.shared.open(URL(string: "https://www.pdfreaderpro.com/terms_of_service")!) } // MARK: Get & Set /** 当前比较表产品列表内容 */ var products: [KMCompareProductType] { if state == .trial { return [.free, .freeTrial] } else if state == .dmg_Base { return [.free, .allPlatformStandard, .allPlatformAdvanced_12, .dualPlatformAdvanced] } else if state == .dmg_Upgrades1 { return [.allPlatformAdvanced_12] } else if state == .dmg_Upgrades1 { return [.allPlatformAdvanced_12] } else if state == .lite_Base { return [.free, .allPlatformAdvanced_6, .allPlatformAdvanced_12, .dualPlatformAdvanced] } else if state == .lite_MacWindows { return [.allPlatformAdvanced_12] } else if state == .pro_Base { return [.allPlatformAdvanced_12, .macPlatformAdvanced] } else if state == .pro_Advanced { return [.allPlatformAdvanced_12] } return [] } /** 比较表数据源 */ var dataSource: [Any] { if isPurchaseSwitch { // 试用 全平台标准版年订阅 全平台高级版6/12个月订阅 Mac&Windows双平台高级版永久 MAC单平台高级版永久 //MAC单平台标准版永久 return [ "Benefit", ["Supported platforms", "mac, windows, ios, android", "mac, windows, ios, android", "mac, windows, ios, android", "mac, windows", "mac"], ["Maximum number of accessible devices", "4 devices", "4 devices", "4 devices", "1 device", "1 device"], "PDF to Office", ["Convert PDFs to Word, HTML, TXT, JPEG or PNG files", "Only first 10 pages", "Standard", "Advanced", "Advanced", "Advanced"], ["Turn PDF to PPT, Excel, RTF, CSV, and more", "Only first 10 pages", "Only first 10 pages", "✓", "✓", "✓"], ["Convert PDF to TIFF, BMP, GIF or TGA files", "Only first 10 pages", "Only first 10 pages", "✓", "✓", "✓"], "Edit PDF", ["Add and edit text in PDF", "X", "✓", "✓", "✓", "✓"], ["Edit, crop, replace image in PDF", "X", "✓", "✓", "✓", "✓"], "OCR", ["Extract texts from image-based or scanned PDF", "X", "✓", "✓", "✓", "✓"], "Organize Pages", ["Extract, rotate, rearrange, replace, add, delete pages", "X", "✓", "✓", "✓", "✓"], ["Split PDFs into multiple files", "X", "✓", "✓", "✓", "✓"], "Advanced Editing Tools", ["Merge multiple documents into a new PDF", "Up to 2 files or 20 MB", "✓", "✓", "✓", "∞", "∞"], ["Add & edit watermark", "X", "✓", "✓", "✓", "✓"], ["Add header, footer, page numbers", "X", "✓", "✓", "✓", "✓"], ["Add Bates Number", "X", "✓", "✓", "✓", "✓"], ["Insert PDF page background by color or image", "X", "✓", "✓", "✓", "✓"], ["Create fattened copies", "X", "✓", "✓", "✓", "✓"], ["Extract Images", "X", "✓", "✓", "✓", "✓"], ["Extract tables", "Only first 10 pages", "Only first 10 pages", "✓", "✓", "✓"], ["Measuring Tools", "X", "✓", "✓", "✓", "✓"], "Fill & Sign", ["Create digital signature", "X", "✓", "✓", "✓", "✓"], ["Create & Edit & Fill Adobe Fillable PDF Forms", "X", "✓", "✓", "✓", "✓"], "Security", ["Batch encrypting PDF documents", "X", "✓", "✓", "✓", "✓"], ["PDF Password Remover", "X", "✓", "✓", "✓", "✓"], ["Redact sensitive information", "X", "✓", "✓", "✓", "✓"], "Create PDF", ["Convert JPEG, JPG, PNG, TIFF, BMP or PSD files to PDFs", "1 file", "✓", "✓", "✓", "✓"], ["Create PDFs from a scanner and iOS devices", "X", "✓", "✓", "✓", "✓"], "Annotations", ["Customize PDF stamps", "X", "✓", "✓", "✓", "✓"], ["Hyperlink", "Page Number", "Page Number, URL, Email", "Page Number, URL, Email", "Page Number, URL, Email", "Page Number, URL, Email"], ["Signature", "Standard", "Advanced", "Advanced", "Advanced", "Advanced"], ["Table", "X", "✓", "✓", "✓", "✓"], "View PDF", ["Multi-tab viewer", "X", "✓", "✓", "✓", "✓"], ["Various printing types: poster, booklet, multi-page printing", "X", "✓", "✓", "✓", "✓"], ["Customize theme colors: Light Mode, Dark Mode, Sepia Mode and more", "X", "✓", "✓", "✓", "✓"], ["Split View to compare files", "X", "✓", "✓", "✓", "✓"], "Subscription Based Solution", ["Access all premium features in app", "X", "12 months", "12 months", "∞", "∞"], ["Priority customer support", "X", "✓", "✓", "✓", "✓"], ["Ad-free", "X", "✓", "✓", "✓", "✓"] ] } else { return [ "Benefit", ["Supported platforms", "mac, windows, ios, android", "mac, windows, ios, android", "mac, windows, ios, android", "mac, windows", "mac"], ["Maximum number of accessible devices", "4 devices", "4 devices", "4 devices", "1 device", "1 device"], "PDF to Office", ["Convert PDFs to Word, HTML, TXT, JPEG or PNG files", "Only first 10 pages", "Standard", "Advanced", "Advanced", "Advanced"], ["Turn PDF to PPT, Excel, RTF, CSV, and more", "Only first 10 pages", "Only first 10 pages", "✓", "✓", "✓"], ["Convert PDF to TIFF, BMP, GIF or TGA files", "Only first 10 pages", "Only first 10 pages", "✓", "✓", "✓"], "Edit PDF", ["Add and edit text in PDF", "X", "✓", "✓", "✓", "✓"], ["Edit, crop, replace image in PDF", "X", "✓", "✓", "✓", "✓"], "OCR", ["Extract texts from image-based or scanned PDF", "X", "✓", "✓", "✓", "✓"], "Organize Pages", ["Extract, rotate, rearrange, replace, add, delete pages", "X", "✓", "✓", "✓", "✓"], ["Split PDFs into multiple files", "X", "✓", "✓", "✓", "✓"], "Advanced Editing Tools", ["Merge multiple documents into a new PDF", "Up to 2 files or 20 MB", "✓", "✓", "✓", "∞", "∞"], ["Add & edit watermark", "X", "✓", "✓", "✓", "✓"], ["Add header, footer, page numbers", "X", "✓", "✓", "✓", "✓"], ["Add Bates Number", "X", "✓", "✓", "✓", "✓"], ["Insert PDF page background by color or image", "X", "✓", "✓", "✓", "✓"], ["Create fattened copies", "X", "✓", "✓", "✓", "✓"], ["Extract Images", "X", "✓", "✓", "✓", "✓"], ["Extract tables", "Only first 10 pages", "Only first 10 pages", "✓", "✓", "✓"], ["Measuring Tools", "X", "✓", "✓", "✓", "✓"], "Fill & Sign", ["Create digital signature", "X", "✓", "✓", "✓", "✓"], ["Create & Edit & Fill Adobe Fillable PDF Forms", "X", "✓", "✓", "✓", "✓"], "Security", ["Batch encrypting PDF documents", "X", "✓", "✓", "✓", "✓"], ["PDF Password Remover", "X", "✓", "✓", "✓", "✓"], ["Redact sensitive information", "X", "✓", "✓", "✓", "✓"], "Create PDF", ["Convert JPEG, JPG, PNG, TIFF, BMP or PSD files to PDFs", "1 file", "✓", "✓", "✓", "✓"], ["Create PDFs from a scanner and iOS devices", "X", "✓", "✓", "✓", "✓"], "Annotations", ["Customize PDF stamps", "X", "✓", "✓", "✓", "✓"], ["Hyperlink", "Page Number", "Page Number, URL, Email", "Page Number, URL, Email", "Page Number, URL, Email", "Page Number, URL, Email"], ["Signature", "Standard", "Advanced", "Advanced", "Advanced", "Advanced"], ["Table", "X", "✓", "✓", "✓", "✓"], "View PDF", ["Multi-tab viewer", "X", "✓", "✓", "✓", "✓"], ["Various printing types: poster, booklet, multi-page printing", "X", "✓", "✓", "✓", "✓"], ["Customize theme colors: Light Mode, Dark Mode, Sepia Mode and more", "X", "✓", "✓", "✓", "✓"], ["Split View to compare files", "X", "✓", "✓", "✓", "✓"], "Subscription Based Solution", ["Access all premium features in app", "X", "6 months", "6 months", "∞", "∞"], ["Priority customer support", "X", "✓", "✓", "✓", "✓"], ["Ad-free", "X", "✓", "✓", "✓", "✓"] ] } } /** 是否黑五活动期 */ var isBlackFive: Bool { if let loginContent = KMAdvertisementManager.manager.info.topRightInfoContent { if loginContent.content?.isEmpty == false { return true } } return false } }