// // KMPurchaseEmbeddedWindowController.swift // PDF Reader Pro // // Created by wanjun on 2024/8/29. // import Cocoa // paypal alipay wxpay paddle @objc enum KMPaymentType: UInt32 { case paypal = 0 case paddle case wxpay case alipay } class KMPurchaseEmbeddedWindowController: NSWindowController { @IBOutlet weak var yourOrderLabel: NSTextField! @IBOutlet weak var pdfReaderProLabel: NSTextField! @IBOutlet weak var prmiumLabel: NSTextField! @IBOutlet weak var oneLicenseLabel: NSTextField! @IBOutlet weak var removeButton1: NSButton! // 减少按钮1 @IBOutlet weak var addButton1: NSButton! // 增加按钮1 @IBOutlet weak var amountTextField1: NSTextField! // 数目1 @IBOutlet weak var originalPriceLabel1: NSTextField! // 原价 @IBOutlet weak var discountPriceLabel1: NSTextField! // 折扣 @IBOutlet weak var aiAddOnView: NSView! @IBOutlet weak var aiAddOnButton: NSButton! @IBOutlet weak var aiAddOnLabel: NSTextField! @IBOutlet weak var IndividualLabel: NSTextField! @IBOutlet weak var removeButton2: NSButton! // 减少按钮2 @IBOutlet weak var addButton2: NSButton! // 增加按钮2 @IBOutlet weak var amountTextField2: NSTextField! // 数目2 @IBOutlet weak var amountView2: NSView! @IBOutlet weak var originalPriceLabel2: NSTextField! // 原价 @IBOutlet weak var discountPriceLabel2: NSTextField! // 折扣 @IBOutlet weak var extendedView: NSView! @IBOutlet weak var extendedButton: NSButton! @IBOutlet weak var extendedLabel: NSTextField! @IBOutlet weak var extendedImageView: NSImageView! @IBOutlet weak var accessLabel: NSTextField! @IBOutlet weak var removeButton3: NSButton! // 减少按钮3 @IBOutlet weak var addButton3: NSButton! // 增加按钮3 @IBOutlet weak var amountTextField3: NSTextField! // 数目3 @IBOutlet weak var amountView3: NSView! @IBOutlet weak var originalPriceLabel3: NSTextField! // 原价 @IBOutlet weak var discountPriceLabel3: NSTextField! // 折扣 @IBOutlet weak var couponButton: NSButton! @IBOutlet weak var couponBox: NSBox! @IBOutlet weak var coupomTextField: NSTextField! @IBOutlet weak var applyBox: NSBox! @IBOutlet weak var applyButton: NSButton! @IBOutlet weak var lastPriceLabel: NSTextField! @IBOutlet weak var lastPriceLabel1: NSTextField! @IBOutlet weak var discountLabel: NSTextField! @IBOutlet weak var discountLabel1: NSTextField! @IBOutlet weak var paySumLabel: NSTextField! @IBOutlet weak var paySumLabel1: NSTextField! @IBOutlet weak var privacyLabel: NSTextField! @IBOutlet weak var billInformationLabel: NSTextField! @IBOutlet weak var emailLabel: NSTextField! @IBOutlet weak var emailTextField: NSTextField! @IBOutlet weak var errorView: NSView! @IBOutlet weak var errorLabel: NSTextField! @IBOutlet weak var errorLabelTopLayout: NSLayoutConstraint! @IBOutlet weak var paymentMethodLabel: NSTextField! @IBOutlet weak var paypalButton: NSButton! @IBOutlet weak var cardButton: NSButton! @IBOutlet weak var wechatPayButton: NSButton! @IBOutlet weak var alipayButton: NSButton! @IBOutlet weak var wechatPayButton2: NSButton! @IBOutlet weak var payBox: NSBox! @IBOutlet weak var payBoxHeight: NSLayoutConstraint! @IBOutlet weak var payExplainLabel: NSTextField! @IBOutlet var paypalView: NSView! @IBOutlet weak var paypalBox: NSBox! @IBOutlet weak var paypalBuyNowLabel: NSTextField! @IBOutlet var cardView: NSView! @IBOutlet var paddleView: NSView! @IBOutlet weak var paddleButton: NSButton! @IBOutlet weak var paddlePopUpButton: KMPopUpButton! @IBOutlet weak var paddleBox: NSBox! @IBOutlet weak var paddleTextField: NSTextField! @IBOutlet var weChatPayView: NSView! @IBOutlet weak var weChatBox: NSBox! @IBOutlet weak var weChatButton: NSButton! @IBOutlet var payResult: NSView! @IBOutlet weak var scanLabel: NSTextField! @IBOutlet weak var qrCodeImageView: NSImageView! @IBOutlet weak var payTypeImageView: NSImageView! @IBOutlet weak var successfullyView: NSView! @IBOutlet weak var purchasedLabel: NSTextField! @IBOutlet weak var successfullyLabel: NSTextField! private var pdfCount: Int = 1 private var pdfOriginalPrice: Float = 79.99 private var pdfDiscountPrice: Float = 59.99 private var aiAddOnOriginalPrice: Float = 14.99 private var aiAddOnDiscountPrice: Float = 14.99 private var extendedOriginalPrice: Float = 39.99 private var extendedDiscountPrice: Float = 79.99 private var listPrice: Float = 79.99 private var discount: Float = 79.99 private var _paymentMethod: KMPaymentType = .paypal private var _productType: ProductType = .ipaConvert private var productID: String = "com.brother.pdfreaderpro.mac.product_2" private var originalProductID: String = "com.brother.pdfreaderpro.mac.product_1" // private var discountId: String = "" // 优惠码 private var discountAmount: String = "" // 优惠金额 private var discountScale: String = "" // 优惠比例 private var orderID: String = "" // 订单ID private var timer: Timer? private var pollCount = 0 private let maxPolls = 18 private let interval: TimeInterval = 5 private let countryKeys = [ "Afghanistan", "Aland Islands", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bonaire, Sint Eustatius and Saba", "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "Brit. Indian Ocean", "British Virgin Islands", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Christmas Island", "Cocos Islands", "Colombia", "Comoros", "Congo", "Cook Islands", "Costa Rica", "Cote D'Ivoire", "Croatia", "Curaçao", "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands", "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia", "French Southern Terr.", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Heard/ Mcdonald Islands", "Holy See/ Vatican City", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iraq", "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Lao People's DR", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya", "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova", "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau", "Palestinian Territory", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Republic of Serbia", "Reunion", "Romania", "Russian Federation", "Rwanda", "S. Georgia/ Sandwich Islands", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia", "Saint Martin", "Saint Pierre and Miquelon", "Saint Vincent/ Grenadines", "Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Korea", "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "U.S. Virgin Islands", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "United States (M.O.I.)", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela", "Viet Nam", "Wallis and Futuna", "Western Sahara", "Yemen", "Zambia", "Zimbabwe" ] private let countryAbbreviationValues = [ "AF", "AX", "AL", "DZ", "AS", "AD", "AO", "AI", "AG", "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", "BJ", "BM", "BT", "BO", "BQ", "BA", "BW", "BV", "BR", "IO", "VG", "BN", "BG", "BF", "BI", "KH", "CM", "CA", "CV", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CG", "CK", "CR", "CI", "HR", "CW", "CY", "CZ", "DK", "DJ", "DM", "DO", "EC", "EG", "SV", "GQ", "ER", "EE", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA", "GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", "GW", "GY", "HT", "HM", "VA", "HN", "HK", "HU", "IS", "IN", "ID", "IQ", "IE", "IM", "IL", "IT", "JM", "JP", "JE", "JO", "KZ", "KE", "KI", "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MK", "MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "ME", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "AN", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MP", "NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "RS", "RE", "RO", "RU", "RW", "GS", "SH", "KN", "LC", "MF", "PM", "VC", "WS", "SM", "ST", "SA", "SN", "SC", "SL", "SG", "SK", "SI", "SB", "SO", "ZA", "KR", "ES", "LK", "SD", "SR", "SJ", "SZ", "SE", "CH", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC", "TV", "VI", "UG", "UA", "AE", "GB", "US", "UM", "UY", "UZ", "VU", "VE", "VN", "WF", "EH", "YE", "ZM", "ZW" ] private var handler: ((Int) -> Void)! static var currentWindowController: KMPurchaseEmbeddedWindowController! private var embeddedPaymentPopWC: KMEmbeddedPaymentPopWC? @objc static func currentFirstTrialWC(_ productId: String) -> KMPurchaseEmbeddedWindowController { if currentWindowController != nil { currentWindowController.productID = productId return currentWindowController } else { let configWC: KMPurchaseEmbeddedWindowController = KMPurchaseEmbeddedWindowController.init(windowNibName: "KMPurchaseEmbeddedWindowController") currentWindowController = configWC; currentWindowController.productID = productId return currentWindowController } } override func windowDidLoad() { super.windowDidLoad() // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. productType = self.productToType(productID) originalProductID = productID xibInitialization() paymentMethod = .paypal priceRefresh() self.window?.delegate = self; } // MARK: UI private func xibInitialization() -> Void { yourOrderLabel.stringValue = NSLocalizedString("Your Order", comment: "") yourOrderLabel.textColor = NSColor(named: "KMPurchaseTitleColor") yourOrderLabel.font = NSFont.SFProTextBoldFont(20.0) pdfReaderProLabel.textColor = NSColor(named: "KMPurchaseTitleColor") pdfReaderProLabel.font = NSFont.SFProTextRegularFont(14.0) prmiumLabel.textColor = NSColor(named: "KMPurchaseSubTitleColor") prmiumLabel.font = NSFont.SFProTextRegularFont(12.0) oneLicenseLabel.textColor = NSColor(named: "KMPurchaseSubTitleColor") oneLicenseLabel.font = NSFont.SFProTextRegularFont(12.0) originalPriceLabel1.textColor = NSColor(named: "KMPurchaseTitleColor") originalPriceLabel1.font = NSFont.SFProTextRegularFont(16.0) discountPriceLabel1.textColor = NSColor(named: "KMPurchaseDiscountColor") discountPriceLabel1.font = NSFont.SFProTextRegularFont(9.0) if productType == .ipaConvert || productType == .ipaAI { aiAddOnView.isHidden = true extendedView.isHidden = true if productType == .ipaConvert { pdfReaderProLabel.stringValue = NSLocalizedString("PDF to Office", comment: "") prmiumLabel.stringValue = NSLocalizedString("Export PDF to Word(.docx), Excel (.xlsx), PowerPoint(.pptx) and more offline. It's one time purchase.", comment: "") oneLicenseLabel.isHidden = true } else if productType == .ipaAI { pdfReaderProLabel.stringValue = NSLocalizedString("PDF Reader Pro AI Tools", comment: "") prmiumLabel.stringValue = NSLocalizedString("50 credits for 30 days", comment: "") oneLicenseLabel.stringValue = NSLocalizedString("Manually renew at USD 14.99", comment: "") } } else { pdfReaderProLabel.stringValue = NSLocalizedString("PDF Reader Pro for Mac", comment: "") prmiumLabel.stringValue = NSLocalizedString("Premium and PDF to Office Converter", comment: "") oneLicenseLabel.stringValue = NSLocalizedString("One License for One Mac. One Time Purchase.", comment: "") aiAddOnButton.image = NSImage(named: "EmbeddedPayment06") aiAddOnLabel.stringValue = NSLocalizedString("AI Add-on", comment: "") aiAddOnLabel.textColor = NSColor(named: "KMPurchaseTitleColor") aiAddOnLabel.font = NSFont.SFProTextRegularFont(14.0) IndividualLabel.stringValue = NSLocalizedString("Individual monthly plan. Manually renew.", comment: "") IndividualLabel.textColor = NSColor(named: "KMPurchaseSubTitleColor") IndividualLabel.font = NSFont.SFProTextRegularFont(12.0) originalPriceLabel2.textColor = NSColor(named: "KMPurchaseTitleColor") originalPriceLabel2.font = NSFont.SFProTextRegularFont(16.0) discountPriceLabel2.textColor = NSColor(named: "KMPurchaseDiscountColor") discountPriceLabel2.font = NSFont.SFProTextRegularFont(9.0) if originalProductID == "com.brother.pdfreaderpro.mac.product_3" { extendedLabel.stringValue = NSLocalizedString("Extended Device Access", comment: "") accessLabel.stringValue = NSLocalizedString("Get access to your plan on up to 2 devices. (Mac or Windows)", comment: "") extendedImageView.isHidden = false } else { extendedLabel.stringValue = NSLocalizedString("PDF to Office Pack", comment: "") accessLabel.stringValue = NSLocalizedString("One time purchase", comment: "") extendedImageView.isHidden = true } extendedButton.image = NSImage(named: "EmbeddedPayment06") extendedLabel.textColor = NSColor(named: "KMPurchaseTitleColor") extendedLabel.font = NSFont.SFProTextRegularFont(14.0) accessLabel.textColor = NSColor(named: "KMPurchaseSubTitleColor") accessLabel.font = NSFont.SFProTextRegularFont(12.0) originalPriceLabel3.textColor = NSColor(named: "KMPurchaseTitleColor") originalPriceLabel3.font = NSFont.SFProTextRegularFont(16.0) discountPriceLabel3.textColor = NSColor(named: "KMPurchaseDiscountColor") discountPriceLabel3.font = NSFont.SFProTextRegularFont(9.0) } removeButton1.isEnabled = false amountTextField1.delegate = self amountTextField2.isEditable = false amountTextField3.isEditable = false amountView2.isHidden = true amountView3.isHidden = true couponButton.title = NSLocalizedString("PDF Reader Pro for Mac", comment: "") couponButton.setTitleColor(color: NSColor(named: "KMPurchaseCouponColor")!, font: NSFont.SFProTextRegularFont(14)) coupomTextField.placeholderString = NSLocalizedString("Enter your coupon code and Apply it", comment: "") applyButton.title = NSLocalizedString("Apply", comment: "") applyButton.setTitleColor(color: NSColor(named: "KMPurchaseApplyColor") ?? NSColor.black, font: NSFont.SFProTextRegularFont(13)) couponBox.isHidden = true couponBox.borderColor = NSColor(named: "KMPurchaseCouponBoxColor") ?? NSColor.gray couponBox.fillColor = NSColor(named: "KMPurchaseCouponBoxFillColor") ?? NSColor.gray applyBox.isHidden = true applyBox.borderColor = NSColor(named: "KMPurchaseApplyColor") ?? NSColor.black lastPriceLabel.stringValue = NSLocalizedString("List Price", comment: "") lastPriceLabel.textColor = NSColor(named: "KMPurchaseListPriceColor") lastPriceLabel.font = NSFont.SFProTextRegularFont(16.0) discountLabel.stringValue = NSLocalizedString("Discount", comment: "") discountLabel.textColor = NSColor(named: "KMPurchaseListPriceColor") discountLabel.font = NSFont.SFProTextRegularFont(16.0) paySumLabel.stringValue = NSLocalizedString("Pay sum", comment: "") paySumLabel.textColor = NSColor(named: "KMPurchaseTitleColor1") paySumLabel.font = NSFont.SFProTextBoldFont(24.0) paySumLabel1.textColor = NSColor(named: "KMPurchaseCouponColor") paySumLabel1.font = NSFont.SFProTextBoldFont(24.0) privacyLabel.textColor = NSColor.black let tipsString = NSLocalizedString("Are you a student or a professor? %@ / Want a volume purchase? Please %@.", comment: "") let specialOffer = NSLocalizedString("Get Special Offer", comment: "") let contactsUs = NSLocalizedString("Contact Us", comment: "") let fullString = String(format: tipsString, specialOffer, contactsUs) let attributedString = NSMutableAttributedString(string: fullString) let specialOfferRange = (fullString as NSString).range(of: specialOffer) let contactsUsRange = (fullString as NSString).range(of: contactsUs) attributedString.addAttribute(.foregroundColor, value: NSColor(red: 73/255.0, green: 130/255.0, blue: 230/255.0, alpha: 1.0), range: specialOfferRange) attributedString.addAttribute(.link, value: "GetSpecialOffer://", range: specialOfferRange) attributedString.addAttribute(.foregroundColor, value: NSColor(red: 73/255.0, green: 130/255.0, blue: 230/255.0, alpha: 1.0), range: contactsUsRange) attributedString.addAttribute(.link, value: "www.baidu.com", range: contactsUsRange) // attributedString.addAttributes([.link : "www.baidu.com"], range: contactsUsRange) privacyLabel.attributedStringValue = attributedString privacyLabel.font = NSFont.SFProTextRegularFont(16.0) privacyLabel.delegate = self billInformationLabel.stringValue = NSLocalizedString("Bill Information", comment: "") billInformationLabel.textColor = NSColor(named: "KMPurchaseTitleColor1") billInformationLabel.font = NSFont.SFProTextRegularFont(14.0) emailLabel.stringValue = NSLocalizedString("Email", comment: "") emailLabel.textColor = NSColor(named: "KMPurchaseTitleColor1") emailLabel.font = NSFont.SFProTextRegularFont(14.0) emailTextField.placeholderString = NSLocalizedString("Email to receive license code", comment: "") errorLabel.stringValue = NSLocalizedString("Please enter the email address number to receive the sequence code", comment: "") if VerificationManager.default().email != nil { emailTextField.stringValue = VerificationManager.default().email } errorLabel.textColor = NSColor(named: "KMPurchaseErrorColor") errorLabel.font = NSFont.SFProTextRegularFont(11.0) errorLabel.isHidden = true errorLabelTopLayout.constant = -CGRectGetHeight(errorView.bounds) paymentMethodLabel.stringValue = NSLocalizedString("Payment Method", comment: "") paymentMethodLabel.textColor = NSColor(named: "KMPurchaseTitleColor1") paymentMethodLabel.font = NSFont.SFProTextRegularFont(14.0) wechatPayButton2.isHidden = true payExplainLabel.textColor = NSColor.black let localizedString = NSLocalizedString("By submitting this order, I agree to the %@ and %@ for subscription products", comment: "") let privacyPolicy = NSLocalizedString("Privacy Policy", comment: "") let termsOfService = NSLocalizedString("Terms of Service", comment: "") let fullString1 = String(format: localizedString, privacyPolicy, termsOfService) let attributedString1 = NSMutableAttributedString(string: fullString1) let privacyPolicyRange = (fullString as NSString).range(of: privacyPolicy) let termsOfServiceRange = (fullString as NSString).range(of: termsOfService) attributedString1.addAttribute(.foregroundColor, value: NSColor(red: 73/255.0, green: 130/255.0, blue: 230/255.0, alpha: 1.0), range: privacyPolicyRange) attributedString1.addAttribute(.link, value: "PrivacyPolicy://", range: privacyPolicyRange) attributedString1.addAttribute(.foregroundColor, value: NSColor(red: 73/255.0, green: 130/255.0, blue: 230/255.0, alpha: 1.0), range: termsOfServiceRange) // attributedString1.addAttribute(.link, value: "TermsofService://", range: termsOfServiceRange) attributedString1.addAttributes([.link : "www.baidu.com"], range: termsOfServiceRange) payExplainLabel.attributedStringValue = attributedString payExplainLabel.font = NSFont.SFProTextRegularFont(11.0) payExplainLabel.delegate = self paypalBuyNowLabel.stringValue = NSLocalizedString("Buy Now", comment: "") paypalBuyNowLabel.textColor = NSColor.white paypalBuyNowLabel.font = NSFont.SFProTextBoldFont(16.0) paddleButton.title = NSLocalizedString("Continue to Pay", comment: "") paddleButton.setTitleColor(color: NSColor.white, font: NSFont.SFProTextBoldFont(16)) paddlePopUpButton.type = .arrowDown paddlePopUpButton.removeAllItems() paddlePopUpButton.addItems(withTitles: countryKeys) paddlePopUpButton.selectItem(at: 229) paddlePopUpButton.wantsLayer = true paddlePopUpButton.layer?.backgroundColor = NSColor(named: "KMPurchase_FFFFFF")?.cgColor paddlePopUpButton.layer?.borderColor = NSColor(named: "KMPurchase_DADBDE")?.cgColor paddleBox.fillColor = NSColor(named: "KMPurchase_FFFFFF") ?? NSColor.white paddleBox.borderColor = NSColor(named: "KMPurchase_DADBDE") ?? NSColor.gray paddleTextField.delegate = self weChatButton.title = NSLocalizedString("Continue to Pay", comment: "") weChatButton.setTitleColor(color: NSColor.white, font: NSFont.SFProTextBoldFont(16)) qrCodeImageView.imageScaling = .scaleProportionallyUpOrDown scanLabel.textColor = NSColor(named: "KMPurchase_000000") scanLabel.font = NSFont.SFProTextRegularFont(12) successfullyView.isHidden = true purchasedLabel.stringValue = NSLocalizedString("Purchased", comment: "") purchasedLabel.textColor = NSColor(named: "KMPurchase_002143") purchasedLabel.font = NSFont(name: "Segoe UI", size: 18.0) successfullyLabel.stringValue = NSLocalizedString("Successfully", comment: "") successfullyLabel.textColor = NSColor(named: "KMPurchase_002143") successfullyLabel.font = NSFont(name: "Segoe UI", size: 18.0) } private func priceRefresh() -> Void { if KMDMGProductsManager.shareInstance.productDatas == nil { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Connection Error", comment: "") alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) { alert.beginSheetModal(for: self.window!, completionHandler: nil) } else { alert.runModal() } return } KMDMGProductsManager.shareInstance.getAllPrice(productID) let activity_cny_price = KMDMGProductsManager.shareInstance.activityPrice_CNY let activity_price = KMDMGProductsManager.shareInstance.activityPrice let price = KMDMGProductsManager.shareInstance.price let cny_price = KMDMGProductsManager.shareInstance.price_CNY var discountPrice = activity_price var originalPrice = price var abbreviation = "USD" var discountTotalPrice = activity_price var discountAmount1 = "0.00" var originalTotalPrice = price if NSLocalizedString("USD", comment: "") == "CNY" { abbreviation = "CNY" discountPrice = activity_cny_price originalPrice = cny_price } if productType == .ipaConvert_checkout || productType == .ipaAI { originalPriceLabel1.stringValue = String(format: "%@ %@", abbreviation, discountPrice) if Float(originalPrice) == Float(discountPrice) { discountPriceLabel1.isHidden = true } else { discountPriceLabel1.isHidden = false let attributedString = NSMutableAttributedString(string: String(format: "%@", originalPrice)) attributedString.addAttribute(.strikethroughStyle, value: NSNumber(value: NSUnderlineStyle.single.rawValue), range: NSMakeRange(0, attributedString.length)) attributedString.addAttribute(.strikethroughColor, value: NSColor(named: "KMPurchaseDiscountColor") as Any, range: NSMakeRange(0, attributedString.length)) discountPriceLabel1.attributedStringValue = attributedString } discountTotalPrice = String(format: "%.2f", Float(discountPrice)! * Float(amountTextField1.stringValue)!) originalTotalPrice = String(format: "%.2f", Float(originalPrice)! * Float(amountTextField1.stringValue)!) discountAmount1 = String(format: "%.2f", Float(originalPrice)! - Float(discountPrice)!) } else if productType == .ipaPremium || productType == .ipaPermanent || productType == .ipaPremiumCrossPlatform || productType == .ipaPermanentCrossPlatform || productType == .ipaPremiumAI || productType == .ipaPermanentAI || productType == .ipaPermanentCrossPlatformAI || productType == .ipaConvert { var pdfDiscountPrice = "0.00" var pdfOriginalPrice = "0.00" var aiDiscountPrice = "0.00" // AI捆绑包 折扣 var aiOriginalPrice = "0.00" // AI捆绑包 原始 var crossDiscountPrice = "0.00" // 跨平台捆绑包 折扣 var crossOriginalPrice = "0.00" // 跨平台捆绑包 原始 if NSLocalizedString("USD", comment: "") == "CNY" { if productType == .ipaPermanent || productType == .ipaPermanentCrossPlatform || productType == .ipaPermanentAI || productType == . ipaPermanentCrossPlatformAI { pdfDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.mac.product_3") pdfOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.mac.product_3") aiDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1") aiOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1") if originalProductID == "com.brother.pdfreaderpro.mac.product_3" { crossDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.cross.platform.product_3") crossOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.cross.platform.product_3") } else { crossDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.mac.product_2.checkout") crossOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.mac.product_2.checkout") } } else if productType == .ipaConvert { pdfDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.mac.product_3") pdfOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.mac.product_3") aiDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1") aiOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1") crossDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.mac.product_2.checkout") crossOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.mac.product_2.checkout") } else { pdfDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.mac.product_1") pdfOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.mac.product_1") aiDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1") aiOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1") if originalProductID == "com.brother.pdfreaderpro.mac.product_3" { crossDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.cross.platform.product_3") crossOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.cross.platform.product_3") } else { crossDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPriceCNY("com.brother.pdfreaderpro.mac.product_2.checkout") crossOriginalPrice = KMDMGProductsManager.shareInstance.getPriceCNY("com.brother.pdfreaderpro.mac.product_2.checkout") } } } else { if productType == .ipaPermanent || productType == .ipaPermanentCrossPlatform || productType == .ipaPermanentAI || productType == . ipaPermanentCrossPlatformAI { pdfDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3") pdfOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3") aiDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1") aiOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1") if originalProductID == "com.brother.pdfreaderpro.mac.product_3" { crossDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.cross.platform.product_3") crossOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.cross.platform.product_3") } else { crossDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_2.checkout") crossOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_2.checkout") } } else if productType == .ipaConvert { pdfDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3") pdfOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3") aiDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1") aiOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1") crossDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_2.checkout") crossOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_2.checkout") } else { pdfDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_1") pdfOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_") aiDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1") aiOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1") if originalProductID == "com.brother.pdfreaderpro.mac.product_3" { crossDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.cross.platform.product_3") crossOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.cross.platform.product_3") } else { crossDiscountPrice = KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_2.checkout") crossOriginalPrice = KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_2.checkout") } } } let discount2 = String(format: "%.2f", Float(aiDiscountPrice)! - Float(pdfDiscountPrice)!) let original2 = String(format: "%.2f", Float(aiOriginalPrice)! - Float(pdfOriginalPrice)!) var discount3 = "" var original3 = "" if originalProductID == "com.brother.pdfreaderpro.mac.product_3" { discount3 = String(format: "%.2f", Float(crossDiscountPrice)! - Float(pdfOriginalPrice)!) original3 = String(format: "%.2f", Float(crossOriginalPrice)! - Float(pdfOriginalPrice)!) } else { discount3 = crossDiscountPrice original3 = crossOriginalPrice } // if productType == .ipaPremium || productType == .ipaPermanent { // // } else if productType == .ipaPremiumCrossPlatform || productType == .ipaPermanentCrossPlatform { // // } else if productType == .ipaPremiumAI || productType == .ipaPermanentAI || productType == .ipaPermanentCrossPlatformAI { // // } let dis1 = Float(pdfDiscountPrice)! * Float(amountTextField1.stringValue)! let dis2 = Float(discount2)! * Float(amountTextField2.stringValue)! let dis3 = Float(discount3)! * Float(amountTextField3.stringValue)! let ori1 = Float(pdfOriginalPrice)! * Float(amountTextField1.stringValue)! let ori2 = Float(original2)! * Float(amountTextField2.stringValue)! let ori3 = Float(original3)! * Float(amountTextField3.stringValue)! if aiAddOnButton.state == .on { if extendedButton.state == .on { discountTotalPrice = String(format: "%.2f", dis1 + dis2 + dis3) originalTotalPrice = String(format: "%.2f", ori1 + ori2 + ori3) } else { discountTotalPrice = String(format: "%.2f", dis1 + dis2) originalTotalPrice = String(format: "%.2f", ori1 + ori2) } } else { if extendedButton.state == .on { discountTotalPrice = String(format: "%.2f", dis1 + dis3) originalTotalPrice = String(format: "%.2f", ori1 + ori3) } else { discountTotalPrice = String(format: "%.2f", dis1) originalTotalPrice = String(format: "%.2f", ori1) } } discountAmount1 = String(format: "%.2f", Float(originalPrice)! - Float(discountPrice)!) originalPriceLabel1.stringValue = String(format: "%@ %@", abbreviation, pdfDiscountPrice) if Float(originalPrice) == Float(discountPrice) { discountPriceLabel1.isHidden = true } else { discountPriceLabel1.isHidden = false let attributedString = NSMutableAttributedString(string: String(format: "%@", pdfOriginalPrice)) attributedString.addAttribute(.strikethroughStyle, value: NSNumber(value: NSUnderlineStyle.single.rawValue), range: NSMakeRange(0, attributedString.length)) attributedString.addAttribute(.strikethroughColor, value: NSColor(named: "KMPurchaseDiscountColor") as Any, range: NSMakeRange(0, attributedString.length)) discountPriceLabel1.attributedStringValue = attributedString } originalPriceLabel2.stringValue = String(format: "%@ %@", abbreviation, discount2) if Float(original2) == Float(discount2) { discountPriceLabel2.isHidden = true } else { discountPriceLabel2.isHidden = false let attributedString = NSMutableAttributedString(string: String(format: "%@", original2)) attributedString.addAttribute(.strikethroughStyle, value: NSNumber(value: NSUnderlineStyle.single.rawValue), range: NSMakeRange(0, attributedString.length)) attributedString.addAttribute(.strikethroughColor, value: NSColor(named: "KMPurchaseDiscountColor") as Any, range: NSMakeRange(0, attributedString.length)) discountPriceLabel2.attributedStringValue = attributedString } originalPriceLabel3.stringValue = String(format: "%@ %@", abbreviation, discount3) if Float(original3) == Float(discount3) { discountPriceLabel3.isHidden = true } else { discountPriceLabel3.isHidden = false let attributedString = NSMutableAttributedString(string: String(format: "%@", original3)) attributedString.addAttribute(.strikethroughStyle, value: NSNumber(value: NSUnderlineStyle.single.rawValue), range: NSMakeRange(0, attributedString.length)) attributedString.addAttribute(.strikethroughColor, value: NSColor(named: "KMPurchaseDiscountColor") as Any, range: NSMakeRange(0, attributedString.length)) discountPriceLabel3.attributedStringValue = attributedString } } if self.discountScale != "" || self.discountAmount != "" { var discountTotalPriceF = Float(discountTotalPrice) let originalTotalPriceF = Float(originalTotalPrice) if self.discountScale != "" { discountTotalPrice = String(format: "%.2f", discountTotalPriceF! * Float(self.discountScale)!) discountTotalPriceF = discountTotalPriceF! * Float(self.discountScale)! discountAmount1 = String(format: "%.2f", originalTotalPriceF! - discountTotalPriceF!) } else { var discountAmountF = Float(self.discountAmount) if NSLocalizedString("USD", comment: "") == "CNY" { discountAmountF = discountAmountF! * 6.5 discountTotalPrice = String(format: "%.2f", discountTotalPriceF! - discountAmountF!) discountTotalPriceF = discountTotalPriceF! - discountAmountF! discountAmount1 = String(format: "%.2f", originalTotalPriceF! - discountTotalPriceF!) } } } lastPriceLabel1.stringValue = String(format: "%@ %@", abbreviation, originalTotalPrice) discountLabel1.stringValue = String(format: "%@ %@", abbreviation, discountAmount1) paySumLabel1.stringValue = String(format: "%@ %@", abbreviation, discountTotalPrice) } // MARK: Active @IBAction func amountButtonAction(_ sender: NSButton) { if sender.tag == 0 || sender.tag == 1 { if sender.tag == 0 { if pdfCount > 1 { pdfCount -= 1 } } if sender.tag == 1 { pdfCount += 1 } if pdfCount > 1 { removeButton1.isEnabled = true } else { removeButton1.isEnabled = false } if pdfCount > 100 { wechatPayButton2.isHidden = false cardButton.isHidden = true wechatPayButton.isHidden = true if _paymentMethod == .paddle { paymentMethod = .paypal } } else { wechatPayButton2.isHidden = true cardButton.isHidden = false wechatPayButton.isHidden = false } amountTextField1.stringValue = String(pdfCount) if extendedButton.state == .on { amountTextField2.stringValue = String(pdfCount * 2) } else { amountTextField2.stringValue = String(pdfCount * 1) } amountTextField3.stringValue = String(pdfCount) } // 价格刷新 priceRefresh() } @IBAction func aiAddOnButtonAction(_ sender: NSButton) { let type: ProductType = productType if sender.state == .on { amountView2.isHidden = false aiAddOnButton.image = NSImage(named: "EmbeddedPayment07") if extendedButton.state == .on { if originalProductID == "com.brother.pdfreaderpro.mac.product_3" { productType = .ipaPermanentCrossPlatformAI } else { productType = .ipaConvert } } else { if type == .ipaPremium || type == .ipaPremiumCrossPlatform || type == .ipaPremiumAI || type == .ipaPermanentCrossPlatformAI || type == .ipaConvert { productType = .ipaPremiumAI } else if type == .ipaPermanent || type == .ipaPermanentCrossPlatform || type == .ipaPermanentAI || type == .ipaPermanentCrossPlatformAI || type == .ipaConvert { productType = .ipaPermanentAI } } } else { amountView2.isHidden = true aiAddOnButton.image = NSImage(named: "EmbeddedPayment06") if extendedButton.state == .on { if originalProductID == "com.brother.pdfreaderpro.mac.product_3" { if type == .ipaPremium || type == .ipaPremiumCrossPlatform || type == .ipaPremiumAI || type == .ipaPermanentCrossPlatformAI { productType = .ipaPremiumCrossPlatform } else if type == .ipaPermanent || type == .ipaPermanentCrossPlatform || type == .ipaPermanentAI || type == .ipaPermanentCrossPlatformAI { productType = .ipaPermanentCrossPlatform } } else { productType = .ipaConvert } } else { if type == .ipaPremium || type == .ipaPremiumCrossPlatform || type == .ipaPremiumAI || type == .ipaPermanentCrossPlatformAI || type == .ipaConvert { productType = .ipaPremium } else if type == .ipaPermanent || type == .ipaPermanentCrossPlatform || type == .ipaPermanentAI || type == .ipaPermanentCrossPlatformAI || type == .ipaConvert { productType = .ipaPermanent } } } // 价格刷新 priceRefresh() } @IBAction func extendedButtonAction(_ sender: NSButton) { let type: ProductType = productType if sender.state == .on { amountView3.isHidden = false amountTextField2.stringValue = String(pdfCount * 2) extendedButton.image = NSImage(named: "EmbeddedPayment07") if originalProductID == "com.brother.pdfreaderpro.mac.product_3" { if aiAddOnButton.state == .on { productType = .ipaPermanentCrossPlatformAI } else { if type == .ipaPremium || type == .ipaPremiumCrossPlatform || type == .ipaPremiumAI || type == .ipaPermanentCrossPlatformAI || type == .ipaPermanentCrossPlatformAI { productType = .ipaPremiumCrossPlatform } else if type == .ipaPermanent || type == .ipaPermanentCrossPlatform || type == .ipaPermanentAI || type == .ipaPermanentCrossPlatformAI || type == .ipaPermanentCrossPlatformAI { productType = .ipaPermanentCrossPlatform } } } else { productType = .ipaConvert } } else { amountView3.isHidden = true amountTextField2.stringValue = String(pdfCount) extendedButton.image = NSImage(named: "EmbeddedPayment06") if aiAddOnButton.state == .on { if type == .ipaPremium || type == .ipaPremiumCrossPlatform || type == .ipaPremiumAI || type == .ipaPermanentCrossPlatformAI || type == .ipaPermanentCrossPlatformAI || type == .ipaConvert { productType = .ipaPremiumAI } else if type == .ipaPermanent || type == .ipaPermanentCrossPlatform || type == .ipaPermanentAI || type == .ipaPermanentCrossPlatformAI || type == .ipaPermanentCrossPlatformAI || type == .ipaConvert { productType = .ipaPermanentAI } } else { if type == .ipaPremium || type == .ipaPremiumCrossPlatform || type == .ipaPremiumAI || type == .ipaPermanentCrossPlatformAI || type == .ipaConvert { productType = .ipaPremium } else if type == .ipaPermanent || type == .ipaPermanentCrossPlatform || type == .ipaPermanentAI || type == .ipaPermanentCrossPlatformAI || type == .ipaPermanentCrossPlatformAI || type == .ipaConvert { productType = .ipaPermanent } } } // 价格刷新 priceRefresh() } @IBAction func payButtonAction(_ sender: NSButton) { paymentMethod = KMPaymentType(rawValue: uint32(sender.tag)) ?? .paypal } @IBAction func couponButtonAction(_ sender: NSButton) { couponButton.isHidden = true couponBox.isHidden = false applyBox.isHidden = false } @IBAction func applyButtonAction(_ sender: NSButton) { if coupomTextField.stringValue == "" { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Coupon Error", comment: "") alert.informativeText = NSLocalizedString("Please enter the coupon.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) { alert.beginSheetModal(for: self.window!, completionHandler: nil) } else { alert.runModal() } return } self._getDiscount(productId: productID, discountId: coupomTextField.stringValue) { [weak self] info, err in guard let self = self else { return } if let dataInfo = info { if dataInfo.keys.contains("status") { let status = dataInfo["status"] as? String ?? "" if status == "" { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Connection error", comment: "") alert.informativeText = NSLocalizedString("Promotional volume exception please try again.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) { alert.beginSheetModal(for: self.window!, completionHandler: nil) } else { alert.runModal() } return } if status == "unused" { if dataInfo["discount"] is NSNull && dataInfo["price"] is NSNull { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Connection error", comment: "") alert.informativeText = NSLocalizedString("Non-concessionary amount.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) { alert.beginSheetModal(for: self.window!, completionHandler: nil) } else { alert.runModal() } return } else { if dataInfo["discount"] is NSNull { if dataInfo["price"] is NSNull { } else { if let price1 = dataInfo["price"] { self.discountAmount = String(format: "%@", price1 as! CVarArg) } } } else { if let discount1 = dataInfo["discount"] { self.discountScale = String(format: "%@", discount1 as! CVarArg) } } } } } else { if dataInfo["discount"] is NSNull && dataInfo["price"] is NSNull { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Connection error", comment: "") alert.informativeText = NSLocalizedString("Non-concessionary amount.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) { alert.beginSheetModal(for: self.window!, completionHandler: nil) } else { alert.runModal() } return } else { if dataInfo["discount"] is NSNull { if dataInfo["price"] is NSNull { } else { if let price1 = dataInfo["price"] { self.discountAmount = String(format: "%@", price1 as! CVarArg) } } } else { if let discount1 = dataInfo["discount"] { self.discountScale = String(format: "%@", discount1 as! CVarArg) } } } } } self.priceRefresh() } } @IBAction func paddlePopUpAction(_ sender: NSPopUpButton) { buyAction(sender) } @IBAction func buyAction(_ sender: NSButton) { if emailTextField.stringValue == "" { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Connection Error", comment: "") alert.informativeText = NSLocalizedString("The email address is empty.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) { alert.beginSheetModal(for: self.window!, completionHandler: nil) } else { alert.runModal() } return } if paymentMethod == .paddle { if !isNumeric(paddleTextField.stringValue) && paddleTextField.stringValue != "" { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Connection Error", comment: "") alert.informativeText = NSLocalizedString("Please enter the correct postcode.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) { alert.beginSheetModal(for: self.window!, completionHandler: nil) } else { alert.runModal() } return } } var licenseCode = "" if let license = VerificationManager.default().originLicenseCode, license.count > 0 { licenseCode = license } self._buyProduct(productID, count: pdfCount, discountId: coupomTextField.stringValue, payment: paymentMethod, license: licenseCode, email: emailTextField.stringValue) { [weak self] info, err in guard let self = self else { return } if err != nil {return} if let dataInfo = info { self.orderID = dataInfo["trade_no"] as! String let page_pay_url = dataInfo["page_pay_url"] as! String if self.paymentMethod == .paddle || self.paymentMethod == .paypal { if page_pay_url != "" { self.openWebView(page_pay_url) } } else if self.paymentMethod == .wxpay || self.paymentMethod == .alipay { if page_pay_url != "" { self.scanCode(page_pay_url) } } } else { // 数据错误 } } } // MARK: get & set private var paymentMethod : KMPaymentType { get { return _paymentMethod } set { _paymentMethod = newValue paypalButton.image = NSImage(named: "EmbeddedPayment19") cardButton.image = NSImage(named: "EmbeddedPayment21") wechatPayButton.image = NSImage(named: "EmbeddedPayment23") wechatPayButton2.image = NSImage(named: "EmbeddedPayment23") alipayButton.image = NSImage(named: "EmbeddedPayment25") if _paymentMethod == .paypal { paypalButton.image = NSImage(named: "EmbeddedPayment18") payBox.contentView = paypalView paypalBox.fillColor = NSColor(named: "KMPurchaseBoxColor") ?? NSColor.blue payBoxHeight.constant = 60.0 } else if _paymentMethod == .paddle { cardButton.image = NSImage(named: "EmbeddedPayment20") payBox.contentView = cardView paddleView.wantsLayer = true paddleView.layer?.backgroundColor = NSColor(named: "KMPurchaseBoxColor")?.cgColor ?? NSColor.blue.cgColor payBoxHeight.constant = 150.0 } else if _paymentMethod == .wxpay { wechatPayButton.image = NSImage(named: "EmbeddedPayment22") wechatPayButton2.image = NSImage(named: "EmbeddedPayment22") payBox.contentView = weChatPayView weChatBox.fillColor = NSColor(named: "KMPurchaseBoxColor") ?? NSColor.blue payBoxHeight.constant = 92.0 } else if _paymentMethod == .alipay { alipayButton.image = NSImage(named: "EmbeddedPayment24") payBox.contentView = weChatPayView weChatBox.fillColor = NSColor(named: "KMPurchaseBoxColor") ?? NSColor.blue payBoxHeight.constant = 92.0 } } } var productType: ProductType { get { return _productType } set { _productType = newValue if _productType == .ipaConvert { productID = "com.brother.pdfreaderpro.mac.product_2" } else if _productType == .ipaConvert_checkout { productID = "com.brother.pdfreaderpro.mac.product_2.checkout" } else if _productType == .ipaPremium { productID = "com.brother.pdfreaderpro.mac.product_1" } else if _productType == .ipaPermanent { productID = "com.brother.pdfreaderpro.mac.product_3" } else if _productType == .ipaPremiumCrossPlatform { productID = "com.brother.pdfreaderpro.cross.platform.product_1" } else if _productType == .ipaPermanentCrossPlatform { productID = "com.brother.pdfreaderpro.cross.platform.product_3" } else if _productType == .ipaAI { productID = "com.brother.pdfreaderpro.ai.product_1" } else if _productType == .ipaPremiumAI { productID = "com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1" } else if _productType == .ipaPermanentAI { productID = "com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1" } else if _productType == .ipaPermanentCrossPlatformAI { productID = "com.brother.pdfreaderpro.cross.platform.product_3+com.brother.pdfreaderpro.ai.product_1" } } } // MARK: —— // 获取价格 private func _getProductDatas(callback: @escaping (([String:Any]?, Any?)->Void)) { // func getPriceUrl() { let urlString = kVerificationServer + "/api/product/get-price/v2" KMAdvertisementRequestServer.requestServer.request(urlString: urlString, method: "GET", params: nil) { task, responseObject, error in if (error == nil && responseObject != nil) { let array = responseObject?["data"] as? NSDictionary if array != nil { //解析数据 let productsDict = array?.object(forKey: "data") as? NSDictionary callback(productsDict as? [String : Any], nil) } else { callback([:], error.debugDescription) } } else { callback(nil, error.debugDescription) } } } // 获取优惠卷 private func _getDiscount(productId: String, discountId: String, callback: @escaping (([String : Any]?, Any?)->Void)) { let urlString = kVerificationServer + "/api/coupons/retrieval" let app_code = MainBundle.km_infoDictionary()?["CFBundleIdentifier"] ?? "" let params = [ // 优惠卷id "code" : discountId, "app_code" : app_code, "product_code" : productId] KMAdvertisementRequestServer.requestServer.request(urlString: urlString, method: "GET", params: params) { task, responseObject, error in if (error == nil && responseObject != nil) { if let dataDict = responseObject?["data"] as? NSDictionary { if let swiftDict = dataDict as? [String: Any] { if swiftDict.keys.contains("price") || swiftDict.keys.contains("discount") { callback(dataDict as? [String : Any], nil) } else if swiftDict.keys.contains("coupon_provider") { if let couponDict = swiftDict["coupon_provider"] as? [String: Any] { callback(couponDict, nil) } } } } else if let coupon_provider = responseObject?["coupon_provider"] as? NSDictionary { callback(coupon_provider as? [String : Any], nil) } else { callback([:], error.debugDescription) } } else { callback(nil, error.debugDescription) } } } // 获取订单状态 private func _getOrderStatus(tradeNo: String, callback: @escaping (([String:Any]?, Any?)->Void)) { let urlString = kVerificationServer + "/api/orders/getOrderStatus" var jsonStr: String = "" if let jsonData = try?JSONSerialization.data(withJSONObject: ["trade_no" : tradeNo], options:[]), let data = String(data: jsonData, encoding: .utf8) { jsonStr = data } let rsa = KMVerificationRSA() let publicKey = rsa.loadPublicKey() let encryptedData = rsa.encrypt(plainText: jsonStr, publicKey: publicKey!) let tokenStr = encryptedData?.base64EncodedString() var postData = try!JSONSerialization.data(withJSONObject: ["token" : tokenStr]) var request = URLRequest(url: URL(string: urlString)!,timeoutInterval: Double.infinity) request.addValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.httpMethod = "POST" request.httpBody = postData let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data else { callback(nil, String(describing: error)) return } if let jsonDict = try?JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary ?? [:] { let dataStr = jsonDict["data"] as? String let rsa = KMVerificationRSA() if let deData = (rsa.decrypt(source: dataStr as? NSString ?? "") as? String)?.data(using: .utf8) { if let dict = try?JSONSerialization.jsonObject(with: deData, options: []) as? NSDictionary ?? [:] { return callback(dict as? [String : Any], nil) } } callback([:], String(describing: error)) } else { // 数据错误 callback([:], String(describing: error)) } } task.resume() } private func _buyProduct(_ productId: String, count: Int, discountId: String = "", payment: KMPaymentType, license: String = "", email: String, username: String = "", callback: @escaping (([String:Any]?, Any?)->Void)) { let urlString = kVerificationServer + "/api/subscriptions" let app_code = MainBundle.km_infoDictionary()?["CFBundleIdentifier"] ?? "" let paymentStr = self._paymentTypeString(type: payment) let country = countryAbbreviationValues[paddlePopUpButton.indexOfSelectedItem] let postcode = paddleTextField.stringValue ?? "" let paraDict = ["data" : ["product_code": productId, "app_code": app_code, // 购买数量 "amount": "\(count)", // 优惠卷id "coupon_code": discountId, // 支付类型 paypal alipay wxpay paddle "payment": paymentStr, // 地区 "customer_country": country, // 邮编码 "customer_postcode" : postcode, "unique_sn" : uuid(), // 序列码 标准包 升级 高级包 需要 "upgrade_cdkey" : license, "email" : email, // 用户名 "contact_name" : username]] var postData = try! JSONSerialization.data(withJSONObject: paraDict) var request = URLRequest(url: URL(string: urlString)!,timeoutInterval: Double.infinity) request.addValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent") request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.httpMethod = "POST" request.httpBody = postData let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let theData = data else { callback(nil, String(describing: error)) return } if let jsonDict = try? JSONSerialization.jsonObject(with: theData, options: []) as? NSDictionary ?? [:] { let data1: NSDictionary = jsonDict["data"] as? NSDictionary ?? [:] let subscriptionInfo = data1.object(forKey: "subscription") as? NSDictionary let orderKey = self._paymentTypeString(type: payment) + "_order" let order_info = subscriptionInfo?.object(forKey: orderKey) as? NSDictionary if let dataInfo = order_info, dataInfo.count > 0 { callback(dataInfo as? [String : Any], nil) } else { // 数据错误 callback([:], String(describing: error)) } } else { // 数据错误 callback([:], String(describing: error)) } } task.resume() } // MARK: Private private func uuid() -> String { return GetHardwareUUID()! } private func _paymentTypeString(type: KMPaymentType) -> String { if type == .paddle { return "paddle" } else if type == .alipay { return "alipay" } else if type == .wxpay { return "wxpay" } else if type == .paypal { return "paypal" } return "" } private let tabDict: [ProductType: String] = [ .ipaConvert: "com.brother.pdfreaderpro.mac.product_2", .ipaConvert_checkout: "com.brother.pdfreaderpro.mac.product_2.checkout", .ipaPremium: "com.brother.pdfreaderpro.mac.product_1", .ipaPermanent: "com.brother.pdfreaderpro.mac.product_3", .ipaPremiumCrossPlatform: "com.brother.pdfreaderpro.cross.platform.product_1", .ipaPermanentCrossPlatform: "com.brother.pdfreaderpro.cross.platform.product_3", .ipaAI: "com.brother.pdfreaderpro.ai.product_1", .ipaPremiumAI: "com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1", .ipaPermanentAI: "com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1", .ipaPermanentCrossPlatformAI: "com.brother.pdfreaderpro.cross.platform.product_3+com.brother.pdfreaderpro.ai.product_1" ] private func getProductID() -> String { return GetHardwareUUID()! } private func productToType(_ productId: String) -> ProductType { if productId == "com.brother.pdfreaderpro.mac.product_2" { return .ipaConvert } else if productId == "com.brother.pdfreaderpro.mac.product_2.checkout" { return .ipaConvert_checkout } else if productId == "com.brother.pdfreaderpro.mac.product_1" { return .ipaPremium } else if productId == "com.brother.pdfreaderpro.mac.product_3" { return .ipaPermanent } else if productId == "com.brother.pdfreaderpro.cross.platform.product_1" { return .ipaPremiumCrossPlatform } else if productId == "com.brother.pdfreaderpro.cross.platform.product_3" { return .ipaPermanentCrossPlatform } else if productId == "com.brother.pdfreaderpro.ai.product_1" { return .ipaAI } else if productId == "com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1" { return .ipaPremiumAI } else if productId == "com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1" { return .ipaPermanentAI } else if productId == "com.brother.pdfreaderpro.cross.platform.product_3+com.brother.pdfreaderpro.ai.product_1" { return .ipaPermanentCrossPlatformAI } return .ipaConvert } private func isNumeric(_ text: String) -> Bool { return !text.isEmpty && text.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil } private func openWebView(_ urlPath: String) -> Void { DispatchQueue.main.async { [weak self] in guard let self = self else { return } // let wc = KMEmbeddedPaymentPopWC.init(windowNibName: "KMEmbeddedPaymentPopWC") self.embeddedPaymentPopWC = KMEmbeddedPaymentPopWC.currentFirstTrialWC(urlPath) self.embeddedPaymentPopWC?.showWindow(nil) } startPolling() } private func scanCode(_ urlPath: String) -> Void { DispatchQueue.main.async { [weak self] in guard let self = self else { return } self.payBox.contentView = self.payResult self.payBoxHeight.constant = 262 if self.paymentMethod == .wxpay { self.scanLabel.stringValue = NSLocalizedString("Scan QR Code with WeChat", comment: "") self.payTypeImageView.image = NSImage(named: "EmbeddedPayment27") } else if self.paymentMethod == .alipay { self.scanLabel.stringValue = NSLocalizedString("Scan QR Code with AliPay", comment: "") self.payTypeImageView.image = NSImage(named: "EmbeddedPayment28") } if let url = URL(string: urlPath) { URLSession.shared.dataTask(with: url) { data, response, error in if let data = data, let image = NSImage(data: data) { DispatchQueue.main.async { self.qrCodeImageView.image = image self.startPolling() } } else { print("Failed to load image or there was an error: \(error?.localizedDescription ?? "Unknown error")") } }.resume() } else { print("Invalid URL.") } } } private func pollingResult() -> Void { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in guard let self = self else { return } if self.orderID == "" { return } self._getOrderStatus(tradeNo: self.orderID, callback: { info, err in if let dataInfo = info { if dataInfo.keys.contains("status") { let status = dataInfo["status"] as? Int if status == 2 { self.stopPolling() if dataInfo.keys.contains("license") { let license = dataInfo["license"] as? [String] if license!.count > 0 { self.verificationActivate(license: license![0]) } // else { // let alert = NSAlert() // alert.alertStyle = .critical // alert.messageText = NSLocalizedString("Connection Error", comment: "") // alert.informativeText = NSLocalizedString("Get License Code is empty.", comment: "") // alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) // if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) { // alert.beginSheetModal(for: self.window!, completionHandler: nil) // } else { // alert.runModal() // } // return // } } if dataInfo.keys.contains("ai_license") { let ai_license = dataInfo["ai_license"] as? [String] if ai_license!.count > 0 { self.verificationActivateAIInfo(license: ai_license![0]) } // else { // let alert = NSAlert() // alert.alertStyle = .critical // alert.messageText = NSLocalizedString("Connection Error", comment: "") // alert.informativeText = NSLocalizedString("Get AI License Code is empty.", comment: "") // alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) // if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) { // alert.beginSheetModal(for: self.window!, completionHandler: nil) // } else { // alert.runModal() // } // return // } } } else { self.startPolling() } } } }) } } private func startPolling() { timer = Timer(timeInterval: interval, repeats: false) { [weak self] _ in guard let self = self else { return } self.performTask() } RunLoop.main.add(timer!, forMode: .common) timer!.fire() } @objc private func performTask() { guard pollCount < maxPolls else { stopPolling() return } // 执行你的轮询任务 print("Performing polling task \(pollCount + 1)/\(maxPolls)") pollCount += 1 pollingResult() } private func stopPolling() { timer?.invalidate() timer = nil print("Polling task completed.") if self.embeddedPaymentPopWC != nil { DispatchQueue.main.async { [weak self] in guard let self = self else { return } self.embeddedPaymentPopWC?.close() self.embeddedPaymentPopWC = nil } } pollCount = 0 } private func verificationActivateAIInfo(license: String) { guard !license.isEmpty else { return } let infoDic = ["cdkey": license] AIInfoManager.default().activateAI(withInfo: infoDic) { info, error in if self.paymentMethod == .wxpay || self.paymentMethod == .alipay { self.qrCodeImageView.isHidden = true self.successfullyView.isHidden = false } } } private func verificationActivate(license: String) { guard !license.isEmpty else { return } let infoDic = ["cdkey": license] VerificationManager.default().activateDevice(withInfo: infoDic) { status, info, error in if self.paymentMethod == .wxpay || self.paymentMethod == .alipay { self.qrCodeImageView.isHidden = true self.successfullyView.isHidden = false } } } // MARK: Show Methods // @IBAction private func dismissSheet(_ sender: NSButton) { // NSApp.endSheet(window!) // window!.orderOut(self) // } // // // @objc private func didEndSheet(_ sheet: NSWindow?, returnCode: Int, contextInfo: UnsafeMutableRawPointer?) { // if contextInfo != nil && self.handler != nil { // self.handler!(returnCode) // } // } // // @objc func beginSheetModal(for window: NSWindow?, completionHandler handler: ((Int) -> Void)?) { // if window != nil { // window!.beginSheet(self.window!) { ModalResponse in // self.handler?(ModalResponse.rawValue) // } // } // self.handler = handler // } // MARK: - Notification func controlTextDidEndEditing(_ obj: Notification) { let textField = obj.object as? NSTextField if textField == amountTextField1 { if !isNumeric(textField!.stringValue) { if textField == amountTextField1 { textField?.stringValue = String(pdfCount) } } else { if textField == amountTextField1 { pdfCount = Int(textField!.stringValue) ?? 1 } if pdfCount > 100 { wechatPayButton2.isHidden = false cardButton.isHidden = true wechatPayButton.isHidden = true if _paymentMethod == .paddle { paymentMethod = .paypal } } else { wechatPayButton2.isHidden = true cardButton.isHidden = false wechatPayButton.isHidden = false } } } else if textField == emailTextField { } else if textField == paddleTextField { } } } extension KMPurchaseEmbeddedWindowController: NSTextFieldDelegate { func textView(_ textView: NSTextView, clickedOnLink link: Any, at charIndex: Int) -> Bool { if let url = link as? String { switch url { case "GetSpecialOffer://": NSWorkspace.shared.open(URL(string: NSLocalizedString("https://www.pdfreaderpro.com/store?mode=edu", comment: ""))!) break case "ContactUs://": NSWorkspace.shared.open(URL(string: NSLocalizedString("https://www.pdfreaderpro.com/vpp-purchase-program", comment: ""))!) break case "PrivacyPolicy://": NSWorkspace.shared.open(URL(string: "https://www.pdfreaderpro.com/privacy-policy")!) break case "TermsofService://": NSWorkspace.shared.open(URL(string: "https://www.pdfreaderpro.com/terms_of_service")!) break default: break } } return true } } extension KMPurchaseEmbeddedWindowController: NSWindowDelegate { func windowWillClose(_ notification: Notification) { if orderID != "" { pollingResult() } if self.embeddedPaymentPopWC != nil { self.embeddedPaymentPopWC?.close() self.embeddedPaymentPopWC = nil } KMPurchaseEmbeddedWindowController.currentWindowController = nil } }