KMPurchaseEmbeddedWindowController.swift 89 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659
  1. //
  2. // KMPurchaseEmbeddedWindowController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by wanjun on 2024/8/29.
  6. //
  7. import Cocoa
  8. #if VERSION_DMG
  9. // paypal alipay wxpay paddle
  10. @objc enum KMPaymentType: UInt32 {
  11. case paypal = 0
  12. case paddle
  13. case wxpay
  14. case alipay
  15. }
  16. class KMPurchaseEmbeddedWindowController: NSWindowController {
  17. @IBOutlet weak var yourOrderLabel: NSTextField!
  18. @IBOutlet weak var pdfReaderProLabel: NSTextField!
  19. @IBOutlet weak var prmiumLabel: NSTextField!
  20. @IBOutlet weak var oneLicenseLabel: NSTextField!
  21. @IBOutlet weak var removeButton1: NSButton! // 减少按钮1
  22. @IBOutlet weak var addButton1: NSButton! // 增加按钮1
  23. @IBOutlet weak var amountTextField1: NSTextField! // 数目1
  24. @IBOutlet weak var originalPriceLabel1: NSTextField! // 原价
  25. @IBOutlet weak var discountPriceLabel1: NSTextField! // 折扣
  26. @IBOutlet weak var aiAddOnView: NSView!
  27. @IBOutlet weak var aiAddOnButton: NSButton!
  28. @IBOutlet weak var aiAddOnLabel: NSTextField!
  29. @IBOutlet weak var IndividualLabel: NSTextField!
  30. @IBOutlet weak var removeButton2: NSButton! // 减少按钮2
  31. @IBOutlet weak var addButton2: NSButton! // 增加按钮2
  32. @IBOutlet weak var amountTextField2: NSTextField! // 数目2
  33. @IBOutlet weak var amountView2: NSView!
  34. @IBOutlet weak var originalPriceLabel2: NSTextField! // 原价
  35. @IBOutlet weak var discountPriceLabel2: NSTextField! // 折扣
  36. @IBOutlet weak var aiAddOnButton1: NSButton!
  37. @IBOutlet weak var extendedView: NSView!
  38. @IBOutlet weak var extendedButton: NSButton!
  39. @IBOutlet weak var extendedLabel: NSTextField!
  40. @IBOutlet weak var extendedImageView: NSImageView!
  41. @IBOutlet weak var accessLabel: NSTextField!
  42. @IBOutlet weak var removeButton3: NSButton! // 减少按钮3
  43. @IBOutlet weak var addButton3: NSButton! // 增加按钮3
  44. @IBOutlet weak var amountTextField3: NSTextField! // 数目3
  45. @IBOutlet weak var amountView3: NSView!
  46. @IBOutlet weak var originalPriceLabel3: NSTextField! // 原价
  47. @IBOutlet weak var discountPriceLabel3: NSTextField! // 折扣
  48. @IBOutlet weak var extendedButton1: NSButton!
  49. @IBOutlet weak var couponButton: NSButton!
  50. @IBOutlet weak var couponBox: NSBox!
  51. @IBOutlet weak var coupomTextField: NSTextField!
  52. @IBOutlet weak var couponClearButton: NSButton!
  53. @IBOutlet weak var applyBox: NSBox!
  54. @IBOutlet weak var applyButton: NSButton!
  55. @IBOutlet weak var lastPriceLabel: NSTextField!
  56. @IBOutlet weak var lastPriceLabel1: NSTextField!
  57. @IBOutlet weak var discountView: NSView!
  58. @IBOutlet weak var discountLabel: NSTextField!
  59. @IBOutlet weak var discountLabel1: NSTextField!
  60. @IBOutlet weak var paySumLabel: NSTextField!
  61. @IBOutlet weak var paySumLabel1: NSTextField!
  62. @IBOutlet weak var discountLayoutConstraint: NSLayoutConstraint!
  63. @IBOutlet weak var privacyLabel: NSTextField!
  64. @IBOutlet weak var billInformationLabel: NSTextField!
  65. @IBOutlet weak var emailLabel: NSTextField!
  66. @IBOutlet weak var emailTextField: NSTextField!
  67. @IBOutlet weak var errorView: NSView!
  68. @IBOutlet weak var errorLabel: NSTextField!
  69. @IBOutlet weak var errorLabelTopLayout: NSLayoutConstraint!
  70. @IBOutlet weak var paymentMethodLabel: NSTextField!
  71. @IBOutlet weak var paypalButton: NSButton!
  72. @IBOutlet weak var cardButton: NSButton!
  73. @IBOutlet weak var wechatPayButton: NSButton!
  74. @IBOutlet weak var alipayButton: NSButton!
  75. @IBOutlet weak var wechatPayButton2: NSButton!
  76. @IBOutlet weak var payBox: NSBox!
  77. @IBOutlet weak var payBoxHeight: NSLayoutConstraint!
  78. @IBOutlet weak var payExplainLabel: NSTextField!
  79. @IBOutlet var paypalView: NSView!
  80. @IBOutlet weak var paypalBox: NSBox!
  81. @IBOutlet weak var paypalBuyNowLabel: NSTextField!
  82. @IBOutlet var cardView: NSView!
  83. @IBOutlet var paddleView: NSView!
  84. @IBOutlet weak var paddleButton: NSButton!
  85. @IBOutlet weak var paddlePopUpButton: KMPopUpButton!
  86. @IBOutlet weak var paddleBox: NSBox!
  87. @IBOutlet weak var paddleTextField: NSTextField!
  88. @IBOutlet var weChatPayView: NSView!
  89. @IBOutlet weak var weChatBox: NSBox!
  90. @IBOutlet weak var weChatButton: NSButton!
  91. @IBOutlet var payResult: NSView!
  92. @IBOutlet weak var scanLabel: NSTextField!
  93. @IBOutlet weak var qrCodeImageView: NSImageView!
  94. @IBOutlet weak var payTypeImageView: NSImageView!
  95. @IBOutlet weak var successfullyView: NSView!
  96. @IBOutlet weak var purchasedLabel: NSTextField!
  97. @IBOutlet weak var successfullyLabel: NSTextField!
  98. private var pdfCount: Int = 1
  99. private var _paymentMethod: KMPaymentType = .paypal
  100. private var _productType: ProductType = .ipaConvert
  101. private var productID: String = "com.brother.pdfreaderpro.mac.product_2"
  102. private var originalProductID: String = "com.brother.pdfreaderpro.mac.product_1"
  103. var couponCode: String = "" //优惠卷
  104. private var discountAmount: String = "" // 优惠金额
  105. private var discountScale: String = "" // 优惠比例
  106. private var orderID: String = "" // 订单ID
  107. private var timer: Timer?
  108. private var pollCount = 0
  109. private let maxPolls = 18
  110. private let interval: TimeInterval = 5.0
  111. private let countryKeys = [
  112. "Afghanistan", "Aland Islands", "Albania", "Algeria", "American Samoa",
  113. "Andorra", "Angola", "Anguilla", "Antigua and Barbuda", "Argentina",
  114. "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas",
  115. "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize",
  116. "Benin", "Bermuda", "Bhutan", "Bolivia", "Bonaire, Sint Eustatius and Saba",
  117. "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
  118. "Brit. Indian Ocean", "British Virgin Islands", "Brunei Darussalam", "Bulgaria",
  119. "Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde",
  120. "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
  121. "Christmas Island", "Cocos Islands", "Colombia", "Comoros", "Congo",
  122. "Cook Islands", "Costa Rica", "Cote D'Ivoire", "Croatia", "Curaçao", "Cyprus",
  123. "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic",
  124. "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia",
  125. "Ethiopia", "Falkland Islands", "Faroe Islands", "Fiji", "Finland", "France",
  126. "French Guiana", "French Polynesia", "French Southern Terr.", "Gabon", "Gambia",
  127. "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada",
  128. "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea", "Guinea-Bissau",
  129. "Guyana", "Haiti", "Heard/ Mcdonald Islands", "Holy See/ Vatican City", "Honduras",
  130. "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iraq", "Ireland",
  131. "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan",
  132. "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Lao People's DR",
  133. "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya", "Liechtenstein",
  134. "Lithuania", "Luxembourg", "Macao", "Macedonia", "Madagascar", "Malawi",
  135. "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique",
  136. "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova",
  137. "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique",
  138. "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands", "Netherlands Antilles",
  139. "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue",
  140. "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan",
  141. "Palau", "Palestinian Territory", "Panama", "Papua New Guinea", "Paraguay",
  142. "Peru", "Philippines", "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar",
  143. "Republic of Serbia", "Reunion", "Romania", "Russian Federation", "Rwanda",
  144. "S. Georgia/ Sandwich Islands", "Saint Helena", "Saint Kitts and Nevis",
  145. "Saint Lucia", "Saint Martin", "Saint Pierre and Miquelon", "Saint Vincent/ Grenadines",
  146. "Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal",
  147. "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands",
  148. "Somalia", "South Africa", "South Korea", "Spain", "Sri Lanka", "Sudan",
  149. "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Taiwan",
  150. "Tajikistan", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tokelau", "Tonga",
  151. "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos Islands",
  152. "Tuvalu", "U.S. Virgin Islands", "Uganda", "Ukraine", "United Arab Emirates",
  153. "United Kingdom", "United States", "United States (M.O.I.)", "Uruguay", "Uzbekistan",
  154. "Vanuatu", "Venezuela", "Viet Nam", "Wallis and Futuna", "Western Sahara", "Yemen",
  155. "Zambia", "Zimbabwe"
  156. ]
  157. private let countryAbbreviationValues = [
  158. "AF", "AX", "AL", "DZ", "AS", "AD", "AO", "AI", "AG", "AR", "AM", "AW", "AU", "AT", "AZ", "BS", "BH", "BD", "BB",
  159. "BY", "BE", "BZ", "BJ", "BM", "BT", "BO", "BQ", "BA", "BW", "BV", "BR", "IO", "VG", "BN", "BG", "BF", "BI", "KH",
  160. "CM", "CA", "CV", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CG", "CK", "CR", "CI", "HR", "CW", "CY",
  161. "CZ", "DK", "DJ", "DM", "DO", "EC", "EG", "SV", "GQ", "ER", "EE", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF",
  162. "TF", "GA", "GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", "GW", "GY", "HT", "HM",
  163. "VA", "HN", "HK", "HU", "IS", "IN", "ID", "IQ", "IE", "IM", "IL", "IT", "JM", "JP", "JE", "JO", "KZ", "KE", "KI",
  164. "KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MK", "MG", "MW", "MY", "MV", "ML", "MT",
  165. "MH", "MQ", "MR", "MU", "YT", "MX", "FM", "MD", "MC", "MN", "ME", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL",
  166. "AN", "NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MP", "NO", "OM", "PK", "PW", "PS", "PA", "PG", "PY", "PE", "PH",
  167. "PN", "PL", "PT", "PR", "QA", "RS", "RE", "RO", "RU", "RW", "GS", "SH", "KN", "LC", "MF", "PM", "VC", "WS", "SM",
  168. "ST", "SA", "SN", "SC", "SL", "SG", "SK", "SI", "SB", "SO", "ZA", "KR", "ES", "LK", "SD", "SR", "SJ", "SZ", "SE",
  169. "CH", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", "TO", "TT", "TN", "TR", "TM", "TC", "TV", "VI", "UG", "UA", "AE",
  170. "GB", "US", "UM", "UY", "UZ", "VU", "VE", "VN", "WF", "EH", "YE", "ZM", "ZW"
  171. ]
  172. private var handler: ((Int) -> Void)!
  173. static var currentWindowController: KMPurchaseEmbeddedWindowController!
  174. private var embeddedPaymentPopWC: KMEmbeddedPaymentPopWC?
  175. @objc static func currentFirstTrialWC(_ productId: String) -> KMPurchaseEmbeddedWindowController {
  176. if currentWindowController != nil {
  177. currentWindowController.productID = productId
  178. return currentWindowController
  179. } else {
  180. let configWC: KMPurchaseEmbeddedWindowController = KMPurchaseEmbeddedWindowController.init(windowNibName: "KMPurchaseEmbeddedWindowController")
  181. currentWindowController = configWC;
  182. currentWindowController.productID = productId
  183. return currentWindowController
  184. }
  185. }
  186. override func windowDidLoad() {
  187. super.windowDidLoad()
  188. // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
  189. productType = self.productToType(productID)
  190. originalProductID = productID
  191. if couponCode.count > 0 {
  192. coupomTextField.stringValue = couponCode
  193. }
  194. xibInitialization()
  195. paymentMethod = .paypal
  196. priceRefresh()
  197. confirmPayment(isConfirm: false)
  198. self.window?.delegate = self;
  199. }
  200. override func close() {
  201. super.close()
  202. self.clearEventData()
  203. }
  204. // MARK: UI
  205. private func xibInitialization() -> Void {
  206. yourOrderLabel.stringValue = NSLocalizedString("Your Order", comment: "")
  207. yourOrderLabel.textColor = NSColor(named: "KMPurchaseTitleColor")
  208. yourOrderLabel.font = NSFont.SFProTextBoldFont(20.0)
  209. pdfReaderProLabel.textColor = NSColor(named: "KMPurchaseTitleColor")
  210. pdfReaderProLabel.font = NSFont.SFProTextRegularFont(14.0)
  211. prmiumLabel.textColor = NSColor(named: "KMPurchaseSubTitleColor")
  212. prmiumLabel.font = NSFont.SFProTextRegularFont(12.0)
  213. oneLicenseLabel.textColor = NSColor(named: "KMPurchaseSubTitleColor")
  214. oneLicenseLabel.font = NSFont.SFProTextRegularFont(12.0)
  215. originalPriceLabel1.textColor = NSColor(named: "KMPurchaseTitleColor")
  216. originalPriceLabel1.font = NSFont.SFProTextRegularFont(16.0)
  217. discountPriceLabel1.textColor = NSColor(named: "KMPurchaseDiscountColor")
  218. discountPriceLabel1.font = NSFont.SFProTextRegularFont(9.0)
  219. if productType == .ipaConvert || productType == .ipaAI {
  220. aiAddOnView.isHidden = true
  221. extendedView.isHidden = true
  222. if productType == .ipaConvert {
  223. pdfReaderProLabel.stringValue = NSLocalizedString("PDF to Office", comment: "")
  224. prmiumLabel.stringValue = NSLocalizedString("Export PDF to Word(.docx), Excel (.xlsx), PowerPoint(.pptx) and more offline. It's one time purchase.", comment: "")
  225. oneLicenseLabel.isHidden = true
  226. } else if productType == .ipaAI {
  227. pdfReaderProLabel.stringValue = NSLocalizedString("PDF Reader Pro AI Tools", comment: "")
  228. prmiumLabel.stringValue = NSLocalizedString("50 credits for 30 days", comment: "")
  229. oneLicenseLabel.stringValue = NSLocalizedString("Manually renew at USD 14.99", comment: "")
  230. }
  231. } else {
  232. pdfReaderProLabel.stringValue = NSLocalizedString("PDF Reader Pro for Mac", comment: "")
  233. prmiumLabel.stringValue = NSLocalizedString("Premium and PDF to Office Converter", comment: "")
  234. oneLicenseLabel.stringValue = NSLocalizedString("One License for One Mac. One Time Purchase.", comment: "")
  235. aiAddOnButton.image = NSImage(named: "EmbeddedPayment06")
  236. aiAddOnLabel.stringValue = NSLocalizedString("AI Add-on", comment: "")
  237. aiAddOnLabel.textColor = NSColor(named: "KMPurchaseTitleColor")
  238. aiAddOnLabel.font = NSFont.SFProTextRegularFont(14.0)
  239. IndividualLabel.stringValue = NSLocalizedString("Individual monthly plan. Manually renew.", comment: "")
  240. IndividualLabel.textColor = NSColor(named: "KMPurchaseSubTitleColor")
  241. IndividualLabel.font = NSFont.SFProTextRegularFont(12.0)
  242. originalPriceLabel2.textColor = NSColor(named: "KMPurchaseTitleColor")
  243. originalPriceLabel2.font = NSFont.SFProTextRegularFont(16.0)
  244. discountPriceLabel2.textColor = NSColor(named: "KMPurchaseDiscountColor")
  245. discountPriceLabel2.font = NSFont.SFProTextRegularFont(9.0)
  246. if originalProductID == "com.brother.pdfreaderpro.mac.product_3" {
  247. extendedLabel.stringValue = NSLocalizedString("Extended Device Access", comment: "")
  248. accessLabel.stringValue = NSLocalizedString("Get access to your plan on up to 2 devices. (Mac or Windows)", comment: "")
  249. extendedImageView.isHidden = false
  250. } else {
  251. extendedLabel.stringValue = NSLocalizedString("PDF to Office Pack", comment: "")
  252. accessLabel.stringValue = NSLocalizedString("One time purchase", comment: "")
  253. extendedImageView.isHidden = true
  254. }
  255. extendedButton.image = NSImage(named: "EmbeddedPayment06")
  256. extendedLabel.textColor = NSColor(named: "KMPurchaseTitleColor")
  257. extendedLabel.font = NSFont.SFProTextRegularFont(14.0)
  258. accessLabel.textColor = NSColor(named: "KMPurchaseSubTitleColor")
  259. accessLabel.font = NSFont.SFProTextRegularFont(12.0)
  260. originalPriceLabel3.textColor = NSColor(named: "KMPurchaseTitleColor")
  261. originalPriceLabel3.font = NSFont.SFProTextRegularFont(16.0)
  262. discountPriceLabel3.textColor = NSColor(named: "KMPurchaseDiscountColor")
  263. discountPriceLabel3.font = NSFont.SFProTextRegularFont(9.0)
  264. }
  265. removeButton1.isEnabled = false
  266. amountTextField1.delegate = self
  267. amountTextField2.isEditable = false
  268. amountTextField3.isEditable = false
  269. amountView2.isHidden = true
  270. amountView3.isHidden = true
  271. couponButton.title = NSLocalizedString("I have a coupon?", comment: "")
  272. couponButton.setTitleColor(color: NSColor(named: "KMPurchaseCouponColor")!, font: NSFont.SFProTextRegularFont(14))
  273. coupomTextField.placeholderString = NSLocalizedString("Enter your coupon code and Apply it", comment: "")
  274. applyButton.title = NSLocalizedString("Apply", comment: "")
  275. applyButton.setTitleColor(color: NSColor(named: "KMPurchaseApplyColor") ?? NSColor.black, font: NSFont.SFProTextRegularFont(13))
  276. couponBox.isHidden = true
  277. couponBox.borderColor = NSColor(named: "KMPurchaseCouponBoxColor") ?? NSColor.gray
  278. couponBox.fillColor = NSColor(named: "KMPurchaseCouponBoxFillColor") ?? NSColor.gray
  279. couponClearButton.isHidden = true
  280. applyBox.isHidden = true
  281. applyBox.borderColor = NSColor(named: "KMPurchaseApplyColor") ?? NSColor.black
  282. lastPriceLabel.stringValue = NSLocalizedString("List Price", comment: "")
  283. lastPriceLabel.textColor = NSColor(named: "KMPurchaseListPriceColor")
  284. lastPriceLabel.font = NSFont.SFProTextRegularFont(16.0)
  285. discountLabel.stringValue = NSLocalizedString("Discount", comment: "")
  286. discountLabel.textColor = NSColor(named: "KMPurchaseListPriceColor")
  287. discountLabel.font = NSFont.SFProTextRegularFont(16.0)
  288. paySumLabel.stringValue = NSLocalizedString("Pay sum", comment: "")
  289. paySumLabel.textColor = NSColor(named: "KMPurchaseTitleColor1")
  290. paySumLabel.font = NSFont.SFProTextBoldFont(24.0)
  291. paySumLabel1.textColor = NSColor(named: "KMPurchaseCouponColor")
  292. paySumLabel1.font = NSFont.SFProTextBoldFont(24.0)
  293. privacyLabel.isEditable = false
  294. privacyLabel.isSelectable = true
  295. privacyLabel.allowsEditingTextAttributes = true
  296. privacyLabel.textColor = NSColor.black
  297. privacyLabel.font = NSFont.SFProTextRegularFont(16.0)
  298. let tipsString = NSLocalizedString("Are you a student or a professor? %@ / Want a volume purchase? Please %@.", comment: "")
  299. let specialOffer = NSLocalizedString("Get Special Offer", comment: "")
  300. let contactsUs = NSLocalizedString("Contact Us", comment: "")
  301. let fullString = String(format: tipsString, specialOffer, contactsUs)
  302. let attributedString = NSMutableAttributedString(string: fullString)
  303. // 定义链接的范围
  304. let specialOfferRange = (fullString as NSString).range(of: specialOffer)
  305. let contactsUsRange = (fullString as NSString).range(of: contactsUs)
  306. let linkColor = NSColor(red: 73/255.0, green: 130/255.0, blue: 230/255.0, alpha: 1.0)
  307. let font = NSFont.SFProTextRegularFont(16.0) // 与普通文本相同的字体
  308. attributedString.addAttributes([
  309. .foregroundColor: linkColor,
  310. .link: NSLocalizedString("https://www.pdfreaderpro.com/store?mode=edu", comment: ""),
  311. .font: font
  312. ], range: specialOfferRange)
  313. attributedString.addAttributes([
  314. .foregroundColor: linkColor,
  315. .link: NSLocalizedString("https://www.pdfreaderpro.com/vpp-purchase-program", comment: ""),
  316. .font: font
  317. ], range: contactsUsRange)
  318. attributedString.addAttribute(.font, value: font, range: (fullString as NSString).range(of: fullString))
  319. privacyLabel.attributedStringValue = attributedString
  320. billInformationLabel.stringValue = NSLocalizedString("Bill Information", comment: "")
  321. billInformationLabel.textColor = NSColor(named: "KMPurchaseTitleColor1")
  322. billInformationLabel.font = NSFont.SFProTextRegularFont(14.0)
  323. emailLabel.stringValue = NSLocalizedString("Email", comment: "")
  324. emailLabel.textColor = NSColor(named: "KMPurchaseTitleColor1")
  325. emailLabel.font = NSFont.SFProTextRegularFont(14.0)
  326. emailTextField.placeholderString = NSLocalizedString("Email to receive license code", comment: "")
  327. errorLabel.stringValue = NSLocalizedString("Please enter the email address number to receive the sequence code", comment: "")
  328. if VerificationManager.default().email != nil {
  329. emailTextField.stringValue = VerificationManager.default().email
  330. }
  331. errorLabel.textColor = NSColor(named: "KMPurchaseErrorColor")
  332. errorLabel.font = NSFont.SFProTextRegularFont(11.0)
  333. emailErrorLabel(isReveal: false)
  334. paymentMethodLabel.stringValue = NSLocalizedString("Payment Method", comment: "")
  335. paymentMethodLabel.textColor = NSColor(named: "KMPurchaseTitleColor1")
  336. paymentMethodLabel.font = NSFont.SFProTextRegularFont(14.0)
  337. wechatPayButton2.isHidden = true
  338. payExplainLabel.isEditable = false
  339. payExplainLabel.isSelectable = true
  340. payExplainLabel.allowsEditingTextAttributes = true
  341. payExplainLabel.textColor = NSColor.black
  342. payExplainLabel.font = NSFont.SFProTextRegularFont(11.0)
  343. let localizedString = NSLocalizedString("By submitting this order, I agree to the %@ and %@ for subscription products", comment: "")
  344. let privacyPolicy = NSLocalizedString("Privacy Policy", comment: "")
  345. let termsOfService = NSLocalizedString("Terms of Service", comment: "")
  346. let fullString1 = String(format: localizedString, privacyPolicy, termsOfService)
  347. let attributedString1 = NSMutableAttributedString(string: fullString1)
  348. let privacyPolicyRange = (fullString1 as NSString).range(of: privacyPolicy)
  349. let termsOfServiceRange = (fullString1 as NSString).range(of: termsOfService)
  350. let linkColor1 = NSColor(red: 73/255.0, green: 130/255.0, blue: 230/255.0, alpha: 1.0)
  351. let font1 = NSFont.SFProTextRegularFont(11.0) // 与普通文本相同的字体
  352. attributedString1.addAttributes([
  353. .foregroundColor: linkColor1,
  354. .link: NSLocalizedString("https://www.pdfreaderpro.com/privacy-policy", comment: ""),
  355. .font: font1
  356. ], range: privacyPolicyRange)
  357. attributedString1.addAttributes([
  358. .foregroundColor: linkColor1,
  359. .link: NSLocalizedString("https://www.pdfreaderpro.com/terms_of_service", comment: ""),
  360. .font: font1
  361. ], range: termsOfServiceRange)
  362. attributedString1.addAttribute(.font, value: font1, range: (fullString1 as NSString).range(of: fullString1))
  363. payExplainLabel.attributedStringValue = attributedString1
  364. paypalBuyNowLabel.stringValue = NSLocalizedString("Buy Now", comment: "")
  365. paypalBuyNowLabel.textColor = NSColor.white
  366. paypalBuyNowLabel.font = NSFont.SFProTextBoldFont(16.0)
  367. paddleButton.title = NSLocalizedString("Continue to Pay", comment: "")
  368. paddleButton.setTitleColor(color: NSColor.white, font: NSFont.SFProTextBoldFont(16))
  369. paddlePopUpButton.type = .arrowDown
  370. paddlePopUpButton.removeAllItems()
  371. paddlePopUpButton.addItems(withTitles: countryKeys)
  372. let preferredLanguage = Locale.preferredLanguages.first ?? "en"
  373. if preferredLanguage.hasPrefix("zh-Hans") || preferredLanguage.hasPrefix("zh-Hant") {
  374. paddlePopUpButton.selectItem(at: 45)
  375. } else {
  376. paddlePopUpButton.selectItem(at: 229)
  377. }
  378. paddlePopUpButton.wantsLayer = true
  379. paddlePopUpButton.layer?.backgroundColor = NSColor(named: "KMPurchase_FFFFFF")?.cgColor
  380. paddlePopUpButton.layer?.borderColor = NSColor(named: "KMPurchase_DADBDE")?.cgColor
  381. paddleBox.fillColor = NSColor(named: "KMPurchase_FFFFFF") ?? NSColor.white
  382. paddleBox.borderColor = NSColor(named: "KMPurchase_DADBDE") ?? NSColor.gray
  383. paddleTextField.delegate = self
  384. weChatButton.title = NSLocalizedString("Continue to Pay", comment: "")
  385. weChatButton.setTitleColor(color: NSColor.white, font: NSFont.SFProTextBoldFont(16))
  386. qrCodeImageView.imageScaling = .scaleProportionallyUpOrDown
  387. scanLabel.textColor = NSColor(named: "KMPurchase_000000")
  388. scanLabel.font = NSFont.SFProTextRegularFont(12)
  389. successfullyView.isHidden = true
  390. purchasedLabel.stringValue = NSLocalizedString("Purchased", comment: "")
  391. purchasedLabel.textColor = NSColor(named: "KMPurchase_002143")
  392. purchasedLabel.font = NSFont(name: "Segoe UI", size: 18.0)
  393. successfullyLabel.stringValue = NSLocalizedString("Successfully", comment: "")
  394. successfullyLabel.textColor = NSColor(named: "KMPurchase_002143")
  395. successfullyLabel.font = NSFont(name: "Segoe UI", size: 18.0)
  396. }
  397. private func priceRefresh() -> Void {
  398. if KMDMGProductsManager.shareInstance.productDatas == nil {
  399. let alert = NSAlert()
  400. alert.alertStyle = .critical
  401. alert.messageText = NSLocalizedString("Connection Error", comment: "")
  402. alert.informativeText = NSLocalizedString("Please make sure your internet connection is available.", comment: "")
  403. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  404. if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  405. alert.beginSheetModal(for: self.window!, completionHandler: nil)
  406. } else {
  407. alert.runModal()
  408. }
  409. return
  410. }
  411. var abbreviation = "USD"
  412. if NSLocalizedString("USD", comment: "") == "CNY" {
  413. abbreviation = "CNY"
  414. }
  415. var discount1: Float = 0.0
  416. var original1: Float = 0.0
  417. var discount2: Float = 0.0
  418. var original2: Float = 0.0
  419. var discount3: Float = 0.0
  420. var original3: Float = 0.0
  421. var listPrice: Float = 0.0
  422. var discount: Float = 0.0
  423. var paySum: Float = 0.0
  424. let originalType: ProductType = productToType(originalProductID)
  425. if originalType == .ipaConvert || originalType == .ipaAI {
  426. if originalType == .ipaConvert {
  427. discount1 = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_2")) ?? 19.99
  428. original1 = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_2")) ?? 19.99
  429. } else {
  430. discount1 = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.ai.product_1")) ?? 14.99
  431. original1 = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.ai.product_1")) ?? 14.99
  432. }
  433. listPrice = original1 * Float(amountTextField1.stringValue)!
  434. paySum = discount1 * Float(amountTextField1.stringValue)!
  435. discount = listPrice - paySum
  436. originalPriceLabel1.stringValue = String(format: "%@ %@", abbreviation, String(format: "%.2f", discount1))
  437. if String(format: "%.2f", original1) == String(format: "%.2f", discount1) {
  438. discountPriceLabel1.isHidden = true
  439. } else {
  440. discountPriceLabel1.isHidden = false
  441. let attributedString = NSMutableAttributedString(string: String(format: "%.2f", original1))
  442. attributedString.addAttribute(.strikethroughStyle, value: NSNumber(value: NSUnderlineStyle.single.rawValue), range: NSMakeRange(0, attributedString.length))
  443. attributedString.addAttribute(.strikethroughColor, value: NSColor(named: "KMPurchaseDiscountColor") as Any, range: NSMakeRange(0, attributedString.length))
  444. discountPriceLabel1.attributedStringValue = attributedString
  445. }
  446. } else {
  447. if productType == .ipaPremium {
  448. let aiBinding_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1")) ?? 74.98
  449. let aiBinding_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1")) ?? 74.98
  450. discount2 = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.ai.product_1")) ?? 14.99
  451. original2 = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.ai.product_1")) ?? 14.99
  452. discount1 = aiBinding_discount - discount2
  453. original1 = aiBinding_original - original2
  454. discount3 = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_2.checkout")) ?? 20.00
  455. original3 = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_2.checkout")) ?? 20.00
  456. listPrice = (original1 * Float(amountTextField1.stringValue)!)
  457. paySum = (discount1 * Float(amountTextField1.stringValue)!)
  458. discount = listPrice - paySum
  459. } else if productType == .ipaPermanent {
  460. if originalType == .ipaPremium {
  461. listPrice = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  462. paySum = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  463. discount3 = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_2.checkout")) ?? 20.00
  464. original3 = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_2.checkout")) ?? 20.00
  465. discount1 = paySum - discount3
  466. original1 = listPrice - original3
  467. let aiBinding_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  468. let aiBinding_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  469. let advanced_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  470. let advanced_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  471. discount2 = aiBinding_discount - advanced_discount
  472. original2 = aiBinding_original - advanced_original
  473. listPrice = (original1 * Float(amountTextField1.stringValue)!) + (original3 * Float(amountTextField3.stringValue)!)
  474. paySum = (discount1 * Float(amountTextField1.stringValue)!) + (discount3 * Float(amountTextField3.stringValue)!)
  475. discount = listPrice - paySum
  476. } else if originalType == .ipaPermanent {
  477. listPrice = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  478. paySum = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  479. discount1 = paySum
  480. original1 = listPrice
  481. let aiBinding_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  482. let aiBinding_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  483. let cross_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.cross.platform.product_3")) ?? 119.98
  484. let cross_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.cross.platform.product_3")) ?? 119.98
  485. discount2 = aiBinding_discount - discount1
  486. original2 = aiBinding_original - original1
  487. discount3 = cross_discount - discount1
  488. original3 = cross_original - original1
  489. listPrice = (original1 * Float(amountTextField1.stringValue)!)
  490. paySum = (discount1 * Float(amountTextField1.stringValue)!)
  491. discount = listPrice - paySum
  492. }
  493. } else if productType == .ipaPremiumCrossPlatform {
  494. } else if productType == .ipaPermanentCrossPlatform {
  495. listPrice = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  496. paySum = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  497. discount1 = paySum
  498. original1 = listPrice
  499. let aiBinding_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  500. let aiBinding_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  501. let cross_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.cross.platform.product_3")) ?? 119.98
  502. let cross_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.cross.platform.product_3")) ?? 119.98
  503. discount2 = aiBinding_discount - discount1
  504. original2 = aiBinding_original - original1
  505. discount3 = cross_discount - discount1
  506. original3 = cross_original - original1
  507. listPrice = (original1 * Float(amountTextField1.stringValue)!) + (original3 * Float(amountTextField3.stringValue)!)
  508. paySum = (discount1 * Float(amountTextField1.stringValue)!) + (discount3 * Float(amountTextField3.stringValue)!)
  509. discount = listPrice - paySum
  510. } else if productType == .ipaPremiumAI {
  511. let aiBinding_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1")) ?? 74.98
  512. let aiBinding_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1")) ?? 74.98
  513. discount2 = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.ai.product_1")) ?? 14.99
  514. original2 = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.ai.product_1")) ?? 14.99
  515. discount1 = aiBinding_discount - discount2
  516. original1 = aiBinding_original - original2
  517. discount3 = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_2.checkout")) ?? 20.00
  518. original3 = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_2.checkout")) ?? 20.00
  519. listPrice = (original1 * Float(amountTextField1.stringValue)!) + (original2 * Float(amountTextField2.stringValue)!)
  520. paySum = (discount1 * Float(amountTextField1.stringValue)!) + (discount2 * Float(amountTextField2.stringValue)!)
  521. discount = listPrice - paySum
  522. } else if productType == .ipaPermanentAI {
  523. if originalType == .ipaPremium {
  524. listPrice = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  525. paySum = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  526. discount3 = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_2.checkout")) ?? 20.00
  527. original3 = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_2.checkout")) ?? 20.00
  528. discount1 = paySum - discount3
  529. original1 = listPrice - original3
  530. let aiBinding_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  531. let aiBinding_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  532. let advanced_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  533. let advanced_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  534. discount2 = aiBinding_discount - advanced_discount
  535. original2 = aiBinding_original - advanced_original
  536. listPrice = (original1 * Float(amountTextField1.stringValue)!) + (original2 * Float(amountTextField2.stringValue)!) + (original3 * Float(amountTextField3.stringValue)!)
  537. paySum = (discount1 * Float(amountTextField1.stringValue)!) + (discount2 * Float(amountTextField2.stringValue)!) + (discount3 * Float(amountTextField3.stringValue)!)
  538. discount = listPrice - paySum
  539. } else if originalType == .ipaPermanent {
  540. listPrice = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  541. paySum = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  542. discount1 = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  543. original1 = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  544. let aiBinding_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  545. let aiBinding_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  546. let cross_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.cross.platform.product_3")) ?? 119.98
  547. let cross_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.cross.platform.product_3")) ?? 119.98
  548. discount2 = aiBinding_discount - discount1
  549. original2 = aiBinding_original - original1
  550. discount3 = cross_discount - discount1
  551. original3 = cross_original - original1
  552. listPrice = (original1 * Float(amountTextField1.stringValue)!) + (original2 * Float(amountTextField2.stringValue)!)
  553. paySum = (discount1 * Float(amountTextField1.stringValue)!) + (discount2 * Float(amountTextField2.stringValue)!)
  554. discount = listPrice - paySum
  555. }
  556. } else if productType == .ipaPermanentCrossPlatformAI {
  557. listPrice = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.cross.platform.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 149.96
  558. paySum = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 149.96
  559. discount1 = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  560. original1 = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3")) ?? 79.99
  561. let aiBinding_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  562. let aiBinding_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1")) ?? 94.98
  563. let cross_discount = Float(KMDMGProductsManager.shareInstance.getActivityPrice("com.brother.pdfreaderpro.cross.platform.product_3")) ?? 119.98
  564. let cross_original = Float(KMDMGProductsManager.shareInstance.getPrice("com.brother.pdfreaderpro.cross.platform.product_3")) ?? 119.98
  565. discount2 = aiBinding_discount - discount1
  566. original2 = aiBinding_original - original1
  567. discount3 = cross_discount - discount1
  568. original3 = cross_original - original1
  569. listPrice = (original1 * Float(amountTextField1.stringValue)!) + (original2 * Float(amountTextField2.stringValue)!) + (original3 * Float(amountTextField3.stringValue)!)
  570. paySum = (discount1 * Float(amountTextField1.stringValue)!) + (discount2 * Float(amountTextField2.stringValue)!) + (discount3 * Float(amountTextField3.stringValue)!)
  571. discount = listPrice - paySum
  572. }
  573. originalPriceLabel1.stringValue = String(format: "%@ %@", abbreviation, String(format: "%.2f", discount1))
  574. if String(format: "%.2f", original1) == String(format: "%.2f", discount1) {
  575. discountPriceLabel1.isHidden = true
  576. } else {
  577. discountPriceLabel1.isHidden = false
  578. let attributedString = NSMutableAttributedString(string: String(format: "%.2f", original1))
  579. attributedString.addAttribute(.strikethroughStyle, value: NSNumber(value: NSUnderlineStyle.single.rawValue), range: NSMakeRange(0, attributedString.length))
  580. attributedString.addAttribute(.strikethroughColor, value: NSColor(named: "KMPurchaseDiscountColor") as Any, range: NSMakeRange(0, attributedString.length))
  581. discountPriceLabel1.attributedStringValue = attributedString
  582. }
  583. originalPriceLabel2.stringValue = String(format: "%@ %@", abbreviation, String(format: "%.2f", discount2))
  584. if String(format: "%.2f", original2) == String(format: "%.2f", discount2) {
  585. discountPriceLabel2.isHidden = true
  586. } else {
  587. discountPriceLabel2.isHidden = false
  588. let attributedString = NSMutableAttributedString(string: String(format: "%.2f", original2))
  589. attributedString.addAttribute(.strikethroughStyle, value: NSNumber(value: NSUnderlineStyle.single.rawValue), range: NSMakeRange(0, attributedString.length))
  590. attributedString.addAttribute(.strikethroughColor, value: NSColor(named: "KMPurchaseDiscountColor") as Any, range: NSMakeRange(0, attributedString.length))
  591. discountPriceLabel2.attributedStringValue = attributedString
  592. }
  593. originalPriceLabel3.stringValue = String(format: "%@ %@", abbreviation, String(format: "%.2f", discount3))
  594. if String(format: "%.2f", original3) == String(format: "%.2f", discount3) {
  595. discountPriceLabel3.isHidden = true
  596. } else {
  597. discountPriceLabel3.isHidden = false
  598. let attributedString = NSMutableAttributedString(string: String(format: "%.2f", original3))
  599. attributedString.addAttribute(.strikethroughStyle, value: NSNumber(value: NSUnderlineStyle.single.rawValue), range: NSMakeRange(0, attributedString.length))
  600. attributedString.addAttribute(.strikethroughColor, value: NSColor(named: "KMPurchaseDiscountColor") as Any, range: NSMakeRange(0, attributedString.length))
  601. discountPriceLabel3.attributedStringValue = attributedString
  602. }
  603. }
  604. if self.discountScale != "" || self.discountAmount != "" {
  605. if self.discountScale != "" {
  606. paySum = paySum * Float(self.discountScale)!
  607. discount = listPrice - paySum
  608. } else {
  609. var discountAmountF = Float(self.discountAmount)
  610. if NSLocalizedString("USD", comment: "") == "CNY" {
  611. discountAmountF = discountAmountF! * 6.5
  612. }
  613. paySum = paySum - discountAmountF!
  614. discount = listPrice - paySum
  615. }
  616. }
  617. lastPriceLabel1.stringValue = String(format: "%@ %@", abbreviation, String(format: "%.2f", listPrice))
  618. discountLabel1.stringValue = String(format: "%@ %@", abbreviation, String(format: "%.2f", discount))
  619. paySumLabel1.stringValue = String(format: "%@ %@", abbreviation, String(format: "%.2f", paySum))
  620. if self.discountScale == "" && self.discountAmount == "" {
  621. if lastPriceLabel1.stringValue != paySumLabel1.stringValue {
  622. couponButton.isHidden = true
  623. }
  624. refreshApplyButton(isReveal: true)
  625. } else {
  626. refreshApplyButton(isReveal: false)
  627. }
  628. if discount == 0 {
  629. discountView.isHidden = true
  630. discountLayoutConstraint.constant = discountView.isHidden ? -CGRectGetHeight(discountView.bounds) : 8
  631. }
  632. }
  633. // MARK: Active
  634. @IBAction func amountButtonAction(_ sender: NSButton) {
  635. if sender.tag == 0 || sender.tag == 1 {
  636. if sender.tag == 0 {
  637. if pdfCount > 1 {
  638. pdfCount -= 1
  639. }
  640. }
  641. if sender.tag == 1 {
  642. if pdfCount < 9999 {
  643. pdfCount += 1
  644. }
  645. }
  646. if pdfCount > 1 {
  647. removeButton1.isEnabled = true
  648. } else {
  649. removeButton1.isEnabled = false
  650. }
  651. if pdfCount > 100 {
  652. wechatPayButton2.isHidden = false
  653. cardButton.isHidden = true
  654. wechatPayButton.isHidden = true
  655. if _paymentMethod == .paddle {
  656. paymentMethod = .paypal
  657. }
  658. } else {
  659. wechatPayButton2.isHidden = true
  660. cardButton.isHidden = false
  661. wechatPayButton.isHidden = false
  662. }
  663. amountTextField1.stringValue = String(pdfCount)
  664. if extendedButton.state == .on {
  665. amountTextField2.stringValue = String(pdfCount * 2)
  666. } else {
  667. amountTextField2.stringValue = String(pdfCount * 1)
  668. }
  669. amountTextField3.stringValue = String(pdfCount)
  670. }
  671. // 价格刷新
  672. priceRefresh()
  673. }
  674. @IBAction func aiAddOnButtonAction(_ sender: NSButton) {
  675. let type: ProductType = productToType(originalProductID)
  676. aiAddOnButton.state = sender.state
  677. if sender.state == .on {
  678. amountView2.isHidden = false
  679. aiAddOnButton.image = NSImage(named: "EmbeddedPayment07")
  680. if extendedButton.state == .on {
  681. if type == .ipaPremium {
  682. productType = .ipaPermanentAI
  683. } else if type == .ipaPermanent {
  684. productType = .ipaPermanentCrossPlatformAI
  685. }
  686. } else {
  687. if type == .ipaPremium {
  688. productType = .ipaPremiumAI
  689. } else if type == .ipaPermanent {
  690. productType = .ipaPermanentAI
  691. }
  692. }
  693. } else {
  694. amountView2.isHidden = true
  695. aiAddOnButton.image = NSImage(named: "EmbeddedPayment06")
  696. if extendedButton.state == .on {
  697. if type == .ipaPremium {
  698. productType = .ipaPermanent
  699. } else if type == .ipaPermanent {
  700. productType = .ipaPermanentCrossPlatform
  701. }
  702. } else {
  703. if type == .ipaPremium {
  704. productType = .ipaPremium
  705. } else if type == .ipaPermanent {
  706. productType = .ipaPermanent
  707. }
  708. }
  709. }
  710. // 价格刷新
  711. priceRefresh()
  712. }
  713. @IBAction func extendedButtonAction(_ sender: NSButton) {
  714. let type: ProductType = productToType(originalProductID)
  715. extendedButton.state = sender.state
  716. if sender.state == .on {
  717. amountView3.isHidden = false
  718. if type == .ipaPremium {
  719. amountTextField2.stringValue = String(pdfCount)
  720. } else {
  721. amountTextField2.stringValue = String(pdfCount * 2)
  722. }
  723. extendedButton.image = NSImage(named: "EmbeddedPayment07")
  724. if aiAddOnButton.state == .on {
  725. if type == .ipaPremium {
  726. productType = .ipaPermanentAI
  727. } else if type == .ipaPermanent {
  728. productType = .ipaPermanentCrossPlatformAI
  729. }
  730. } else {
  731. if type == .ipaPremium {
  732. productType = .ipaPermanent
  733. } else if type == .ipaPermanent {
  734. productType = .ipaPermanentCrossPlatform
  735. }
  736. }
  737. } else {
  738. amountView3.isHidden = true
  739. amountTextField2.stringValue = String(pdfCount)
  740. extendedButton.image = NSImage(named: "EmbeddedPayment06")
  741. if aiAddOnButton.state == .on {
  742. if type == .ipaPremium {
  743. productType = .ipaPremiumAI
  744. } else if type == .ipaPermanent {
  745. productType = .ipaPermanentAI
  746. }
  747. } else {
  748. if type == .ipaPremium {
  749. productType = .ipaPremium
  750. } else if type == .ipaPermanent {
  751. productType = .ipaPermanent
  752. }
  753. }
  754. }
  755. // 价格刷新
  756. priceRefresh()
  757. }
  758. @IBAction func payButtonAction(_ sender: NSButton) {
  759. confirmPayment(isConfirm: false)
  760. refreshApplyButton(isReveal: true)
  761. paymentMethod = KMPaymentType(rawValue: uint32(sender.tag)) ?? .paypal
  762. }
  763. @IBAction func couponButtonAction(_ sender: NSButton) {
  764. couponButton.isHidden = true
  765. couponBox.isHidden = false
  766. applyBox.isHidden = false
  767. }
  768. @IBAction func applyButtonAction(_ sender: NSButton) {
  769. if coupomTextField.stringValue == "" {
  770. let alert = NSAlert()
  771. alert.alertStyle = .critical
  772. alert.messageText = NSLocalizedString("Coupon Error", comment: "")
  773. alert.informativeText = NSLocalizedString("Please enter the coupon.", comment: "")
  774. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  775. if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  776. alert.beginSheetModal(for: self.window!, completionHandler: nil)
  777. } else {
  778. alert.runModal()
  779. }
  780. return
  781. }
  782. self._getDiscount(productId: productID, discountId: coupomTextField.stringValue) { [weak self] info, err in
  783. guard let self = self else { return }
  784. if err != nil {
  785. if let dataInfo = info {
  786. if dataInfo.keys.contains("status") {
  787. let status = dataInfo["status"] as? String ?? ""
  788. if status == "" {
  789. let alert = NSAlert()
  790. alert.alertStyle = .critical
  791. alert.messageText = NSLocalizedString("Connection error", comment: "")
  792. alert.informativeText = NSLocalizedString("Promotional volume exception please try again.", comment: "")
  793. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  794. if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  795. alert.beginSheetModal(for: self.window!, completionHandler: nil)
  796. } else {
  797. alert.runModal()
  798. }
  799. return
  800. }
  801. if status == "unused" {
  802. if dataInfo["discount"] is NSNull && dataInfo["price"] is NSNull {
  803. let alert = NSAlert()
  804. alert.alertStyle = .critical
  805. alert.messageText = NSLocalizedString("Connection error", comment: "")
  806. alert.informativeText = NSLocalizedString("Non-concessionary amount.", comment: "")
  807. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  808. if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  809. alert.beginSheetModal(for: self.window!, completionHandler: nil)
  810. } else {
  811. alert.runModal()
  812. }
  813. return
  814. } else {
  815. if dataInfo.keys.contains("coupon_provider") {
  816. if let coupon = dataInfo["coupon_provider"] {
  817. if let swiftDict = coupon as? [String: Any] {
  818. let limit_product_code = swiftDict["limit_product_code"]
  819. if let limitCode = limit_product_code as? String {
  820. if limitCode.count > 0 {
  821. if self.productID != limitCode {
  822. self.couponClearButton.isHidden = false
  823. return
  824. }
  825. }
  826. }
  827. }
  828. }
  829. }
  830. if dataInfo["discount"] is NSNull {
  831. if dataInfo["price"] is NSNull {
  832. } else {
  833. if let price1 = dataInfo["price"] {
  834. self.discountAmount = String(format: "%@", price1 as! CVarArg)
  835. }
  836. }
  837. } else {
  838. if let discount1 = dataInfo["discount"] {
  839. self.discountScale = String(format: "%@", discount1 as! CVarArg)
  840. }
  841. }
  842. }
  843. } else if status == "used" || status == "expired" {
  844. self.couponClearButton.isHidden = false
  845. }
  846. } else {
  847. if dataInfo["discount"] is NSNull && dataInfo["price"] is NSNull {
  848. let alert = NSAlert()
  849. alert.alertStyle = .critical
  850. alert.messageText = NSLocalizedString("Connection error", comment: "")
  851. alert.informativeText = NSLocalizedString("Non-concessionary amount.", comment: "")
  852. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  853. if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  854. alert.beginSheetModal(for: self.window!, completionHandler: nil)
  855. } else {
  856. alert.runModal()
  857. }
  858. return
  859. } else {
  860. self.couponClearButton.isHidden = true
  861. if dataInfo["discount"] is NSNull {
  862. if dataInfo["price"] is NSNull {
  863. } else {
  864. if let price1 = dataInfo["price"] {
  865. self.discountAmount = String(format: "%@", price1 as! CVarArg)
  866. }
  867. }
  868. } else {
  869. if let discount1 = dataInfo["discount"] {
  870. self.discountScale = String(format: "%@", discount1 as! CVarArg)
  871. }
  872. }
  873. }
  874. }
  875. }
  876. self.priceRefresh()
  877. } else {
  878. self.couponClearButton.isHidden = false
  879. }
  880. }
  881. }
  882. @IBAction func paddlePopUpAction(_ sender: NSPopUpButton) {
  883. buyAction(sender)
  884. }
  885. @IBAction func couponClearButton(_ sender: NSButton) {
  886. coupomTextField.stringValue = ""
  887. couponClearButton.isHidden = true
  888. }
  889. @IBAction func buyAction(_ sender: NSButton) {
  890. if emailTextField.stringValue == "" {
  891. // let alert = NSAlert()
  892. // alert.alertStyle = .critical
  893. // alert.messageText = NSLocalizedString("Connection Error", comment: "")
  894. // alert.informativeText = NSLocalizedString("The email address is empty.", comment: "")
  895. // alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  896. // if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  897. // alert.beginSheetModal(for: self.window!, completionHandler: nil)
  898. // } else {
  899. // alert.runModal()
  900. // }
  901. emailErrorLabel(isReveal: true)
  902. return
  903. }
  904. if paymentMethod == .paddle {
  905. if !isNumeric(paddleTextField.stringValue) && paddleTextField.stringValue != "" {
  906. let alert = NSAlert()
  907. alert.alertStyle = .critical
  908. alert.messageText = NSLocalizedString("Connection Error", comment: "")
  909. alert.informativeText = NSLocalizedString("Please enter the correct postcode.", comment: "")
  910. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  911. if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  912. alert.beginSheetModal(for: self.window!, completionHandler: nil)
  913. } else {
  914. alert.runModal()
  915. }
  916. return
  917. }
  918. }
  919. confirmPayment(isConfirm: true)
  920. if paymentMethod == .paypal {
  921. paypalBox.fillColor = NSColor(named: "KMPurchaseBoxColor1") ?? NSColor.blue
  922. } else if paymentMethod == .paddle {
  923. paddleView.wantsLayer = true
  924. paddleView.layer?.backgroundColor = NSColor(named: "KMPurchaseBoxColor1")?.cgColor ?? NSColor.blue.cgColor
  925. } else if paymentMethod == .wxpay {
  926. weChatBox.fillColor = NSColor(named: "KMPurchaseBoxColor1") ?? NSColor.blue
  927. } else if paymentMethod == .alipay {
  928. weChatBox.fillColor = NSColor(named: "KMPurchaseBoxColor1") ?? NSColor.blue
  929. }
  930. DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
  931. guard let self = self else { return }
  932. if self.paymentMethod == .paypal {
  933. self.paypalBox.fillColor = NSColor(named: "KMPurchaseBoxColor") ?? NSColor.blue
  934. } else if self._paymentMethod == .paddle {
  935. self.paddleView.wantsLayer = true
  936. self.paddleView.layer?.backgroundColor = NSColor(named: "KMPurchaseBoxColor")?.cgColor ?? NSColor.blue.cgColor
  937. } else if self._paymentMethod == .wxpay {
  938. self.weChatBox.fillColor = NSColor(named: "KMPurchaseBoxColor") ?? NSColor.blue
  939. } else if self._paymentMethod == .alipay {
  940. self.weChatBox.fillColor = NSColor(named: "KMPurchaseBoxColor") ?? NSColor.blue
  941. }
  942. }
  943. var licenseCode = ""
  944. if let license = VerificationManager.default().originLicenseCode, license.count > 0 {
  945. licenseCode = license
  946. }
  947. self._buyProduct(productID, count: pdfCount, discountId: coupomTextField.stringValue, payment: paymentMethod, license: licenseCode, email: emailTextField.stringValue) { [weak self] info, err in
  948. guard let self = self else { return }
  949. if err != nil {return}
  950. if let dataInfo = info {
  951. self.orderID = dataInfo["trade_no"] as! String
  952. let page_pay_url = dataInfo["page_pay_url"] as! String
  953. if self.paymentMethod == .paddle || self.paymentMethod == .paypal {
  954. if page_pay_url != "" {
  955. self.openWebView(page_pay_url)
  956. }
  957. } else if self.paymentMethod == .wxpay || self.paymentMethod == .alipay {
  958. if page_pay_url != "" {
  959. self.scanCode(page_pay_url)
  960. }
  961. }
  962. } else {
  963. // 数据错误
  964. }
  965. }
  966. }
  967. // MARK: get & set
  968. private var paymentMethod : KMPaymentType {
  969. get {
  970. return _paymentMethod
  971. }
  972. set {
  973. _paymentMethod = newValue
  974. paypalButton.image = NSImage(named: "EmbeddedPayment19")
  975. cardButton.image = NSImage(named: "EmbeddedPayment21")
  976. wechatPayButton.image = NSImage(named: "EmbeddedPayment23")
  977. wechatPayButton2.image = NSImage(named: "EmbeddedPayment23")
  978. alipayButton.image = NSImage(named: "EmbeddedPayment25")
  979. if _paymentMethod == .paypal {
  980. paypalButton.image = NSImage(named: "EmbeddedPayment18")
  981. payBox.contentView = paypalView
  982. paypalBox.fillColor = NSColor(named: "KMPurchaseBoxColor") ?? NSColor.blue
  983. payBoxHeight.constant = 60.0
  984. } else if _paymentMethod == .paddle {
  985. cardButton.image = NSImage(named: "EmbeddedPayment20")
  986. payBox.contentView = cardView
  987. paddleView.wantsLayer = true
  988. paddleView.layer?.backgroundColor = NSColor(named: "KMPurchaseBoxColor")?.cgColor ?? NSColor.blue.cgColor
  989. payBoxHeight.constant = 150.0
  990. } else if _paymentMethod == .wxpay {
  991. wechatPayButton.image = NSImage(named: "EmbeddedPayment22")
  992. wechatPayButton2.image = NSImage(named: "EmbeddedPayment22")
  993. payBox.contentView = weChatPayView
  994. weChatBox.fillColor = NSColor(named: "KMPurchaseBoxColor") ?? NSColor.blue
  995. payBoxHeight.constant = 92.0
  996. } else if _paymentMethod == .alipay {
  997. alipayButton.image = NSImage(named: "EmbeddedPayment24")
  998. payBox.contentView = weChatPayView
  999. weChatBox.fillColor = NSColor(named: "KMPurchaseBoxColor") ?? NSColor.blue
  1000. payBoxHeight.constant = 92.0
  1001. }
  1002. }
  1003. }
  1004. var productType: ProductType {
  1005. get {
  1006. return _productType
  1007. }
  1008. set {
  1009. _productType = newValue
  1010. if _productType == .ipaConvert {
  1011. productID = "com.brother.pdfreaderpro.mac.product_2"
  1012. } else if _productType == .ipaConvert_checkout {
  1013. productID = "com.brother.pdfreaderpro.mac.product_2.checkout"
  1014. } else if _productType == .ipaPremium {
  1015. productID = "com.brother.pdfreaderpro.mac.product_1"
  1016. } else if _productType == .ipaPermanent {
  1017. productID = "com.brother.pdfreaderpro.mac.product_3"
  1018. } else if _productType == .ipaPremiumCrossPlatform {
  1019. productID = "com.brother.pdfreaderpro.cross.platform.product_1"
  1020. } else if _productType == .ipaPermanentCrossPlatform {
  1021. productID = "com.brother.pdfreaderpro.cross.platform.product_3"
  1022. } else if _productType == .ipaAI {
  1023. productID = "com.brother.pdfreaderpro.ai.product_1"
  1024. } else if _productType == .ipaPremiumAI {
  1025. productID = "com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1"
  1026. } else if _productType == .ipaPermanentAI {
  1027. productID = "com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1"
  1028. } else if _productType == .ipaPermanentCrossPlatformAI {
  1029. productID = "com.brother.pdfreaderpro.cross.platform.product_3+com.brother.pdfreaderpro.ai.product_1"
  1030. }
  1031. }
  1032. }
  1033. // MARK: ——
  1034. // 获取价格
  1035. private func _getProductDatas(callback: @escaping (([String:Any]?, Any?)->Void)) {
  1036. // func getPriceUrl() {
  1037. let urlString = kVerificationServer + "/api/product/get-price/v2"
  1038. KMAdvertisementRequestServer.requestServer.request(urlString: urlString, method: "GET", params: nil) { task, responseObject, error in
  1039. if (error == nil && responseObject != nil) {
  1040. let array = responseObject?["data"] as? NSDictionary
  1041. if array != nil {
  1042. //解析数据
  1043. let productsDict = array?.object(forKey: "data") as? NSDictionary
  1044. callback(productsDict as? [String : Any], nil)
  1045. } else {
  1046. callback([:], error.debugDescription)
  1047. }
  1048. } else {
  1049. callback(nil, error.debugDescription)
  1050. }
  1051. }
  1052. }
  1053. // 获取优惠卷
  1054. private func _getDiscount(productId: String, discountId: String, callback: @escaping (([String : Any]?, Any?)->Void)) {
  1055. let urlString = kVerificationServer + "/api/coupons/retrieval"
  1056. let app_code = MainBundle.km_infoDictionary()?["CFBundleIdentifier"] ?? ""
  1057. let params = [
  1058. // 优惠卷id
  1059. "code" : discountId,
  1060. "app_code" : app_code,
  1061. "product_code" : productId]
  1062. KMAdvertisementRequestServer.requestServer.request(urlString: urlString, method: "GET", params: params) { task, responseObject, error in
  1063. if (error == nil && responseObject != nil) {
  1064. if let dataDict = responseObject?["data"] as? NSDictionary {
  1065. if let swiftDict = dataDict as? [String: Any] {
  1066. if swiftDict.keys.contains("price") || swiftDict.keys.contains("discount") {
  1067. callback(dataDict as? [String : Any], nil)
  1068. } else if swiftDict.keys.contains("coupon_provider") {
  1069. if let couponDict = swiftDict["coupon_provider"] as? [String: Any] {
  1070. callback(couponDict, nil)
  1071. }
  1072. }
  1073. }
  1074. } else if let coupon_provider = responseObject?["coupon_provider"] as? NSDictionary {
  1075. callback(coupon_provider as? [String : Any], nil)
  1076. } else {
  1077. callback([:], error.debugDescription)
  1078. }
  1079. } else {
  1080. callback(nil, error.debugDescription)
  1081. }
  1082. }
  1083. }
  1084. // 获取订单状态
  1085. private func _getOrderStatus(tradeNo: String, callback: @escaping (([String:Any]?, Any?)->Void)) {
  1086. let urlString = kVerificationServer + "/api/orders/getOrderStatus"
  1087. var jsonStr: String = ""
  1088. if let jsonData = try?JSONSerialization.data(withJSONObject: ["trade_no" : tradeNo], options:[]),
  1089. let data = String(data: jsonData, encoding: .utf8) {
  1090. jsonStr = data
  1091. }
  1092. let rsa = KMVerificationRSA()
  1093. let publicKey = rsa.loadPublicKey()
  1094. let encryptedData = rsa.encrypt(plainText: jsonStr, publicKey: publicKey!)
  1095. let tokenStr = encryptedData?.base64EncodedString()
  1096. var postData = try!JSONSerialization.data(withJSONObject: ["token" : tokenStr])
  1097. var request = URLRequest(url: URL(string: urlString)!,timeoutInterval: Double.infinity)
  1098. request.addValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
  1099. request.addValue("application/json", forHTTPHeaderField: "Content-Type")
  1100. request.httpMethod = "POST"
  1101. request.httpBody = postData
  1102. let task = URLSession.shared.dataTask(with: request) { data, response, error in
  1103. guard let data = data else {
  1104. callback(nil, String(describing: error))
  1105. return
  1106. }
  1107. if let jsonDict = try?JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary ?? [:] {
  1108. let dataStr = jsonDict["data"] as? String
  1109. let rsa = KMVerificationRSA()
  1110. if let deData = (rsa.decrypt(source: dataStr as? NSString ?? "") as? String)?.data(using: .utf8) {
  1111. if let dict = try?JSONSerialization.jsonObject(with: deData, options: []) as? NSDictionary ?? [:] {
  1112. return callback(dict as? [String : Any], nil)
  1113. }
  1114. }
  1115. callback([:], String(describing: error))
  1116. } else {
  1117. // 数据错误
  1118. callback([:], String(describing: error))
  1119. }
  1120. }
  1121. task.resume()
  1122. }
  1123. private func _buyProduct(_ productId: String, count: Int, discountId: String = "", payment: KMPaymentType, license: String = "", email: String, username: String = "", callback: @escaping (([String:Any]?, Any?)->Void)) {
  1124. let urlString = kVerificationServer + "/api/subscriptions"
  1125. let app_code = MainBundle.km_infoDictionary()?["CFBundleIdentifier"] ?? ""
  1126. let paymentStr = self._paymentTypeString(type: payment)
  1127. let country = countryAbbreviationValues[paddlePopUpButton.indexOfSelectedItem]
  1128. let postcode = paddleTextField.stringValue
  1129. let paraDict = ["data" :
  1130. ["product_code": productId,
  1131. "app_code": app_code,
  1132. // 购买数量
  1133. "amount": "\(count)",
  1134. // 优惠卷id
  1135. "coupon_code": discountId,
  1136. // 支付类型 paypal alipay wxpay paddle
  1137. "payment": paymentStr,
  1138. // 地区
  1139. "customer_country": country,
  1140. // 邮编码
  1141. "customer_postcode" : postcode,
  1142. "unique_sn" : uuid(),
  1143. // 序列码 标准包 升级 高级包 需要
  1144. "upgrade_cdkey" : license,
  1145. "email" : email,
  1146. // 用户名
  1147. "contact_name" : username,
  1148. "platform" : "DMG"]]
  1149. var postData = try! JSONSerialization.data(withJSONObject: paraDict)
  1150. var request = URLRequest(url: URL(string: urlString)!,timeoutInterval: Double.infinity)
  1151. request.addValue("Apifox/1.0.0 (https://www.apifox.cn)", forHTTPHeaderField: "User-Agent")
  1152. request.addValue("application/json", forHTTPHeaderField: "Content-Type")
  1153. request.httpMethod = "POST"
  1154. request.httpBody = postData
  1155. let task = URLSession.shared.dataTask(with: request) { data, response, error in
  1156. guard let theData = data else {
  1157. callback(nil, String(describing: error))
  1158. return
  1159. }
  1160. if let jsonDict = try? JSONSerialization.jsonObject(with: theData, options: []) as? NSDictionary ?? [:] {
  1161. let data1: NSDictionary = jsonDict["data"] as? NSDictionary ?? [:]
  1162. let subscriptionInfo = data1.object(forKey: "subscription") as? NSDictionary
  1163. let orderKey = self._paymentTypeString(type: payment) + "_order"
  1164. let order_info = subscriptionInfo?.object(forKey: orderKey) as? NSDictionary
  1165. if let dataInfo = order_info, dataInfo.count > 0 {
  1166. callback(dataInfo as? [String : Any], nil)
  1167. } else {
  1168. // 数据错误
  1169. callback([:], String(describing: error))
  1170. }
  1171. } else {
  1172. // 数据错误
  1173. callback([:], String(describing: error))
  1174. }
  1175. }
  1176. task.resume()
  1177. }
  1178. // MARK: Private
  1179. private func uuid() -> String {
  1180. return GetHardwareUUID()!
  1181. }
  1182. private func _paymentTypeString(type: KMPaymentType) -> String {
  1183. if type == .paddle {
  1184. return "paddle"
  1185. } else if type == .alipay {
  1186. return "alipay"
  1187. } else if type == .wxpay {
  1188. return "wxpay"
  1189. } else if type == .paypal {
  1190. return "paypal"
  1191. }
  1192. return ""
  1193. }
  1194. private func _trackEvent_paid() {
  1195. self.trackEvent_dmg(eventName: self.kEventName, params: self.kEventParams, platform: .AppCenter)
  1196. }
  1197. private let tabDict: [ProductType: String] = [
  1198. .ipaConvert: "com.brother.pdfreaderpro.mac.product_2",
  1199. .ipaConvert_checkout: "com.brother.pdfreaderpro.mac.product_2.checkout",
  1200. .ipaPremium: "com.brother.pdfreaderpro.mac.product_1",
  1201. .ipaPermanent: "com.brother.pdfreaderpro.mac.product_3",
  1202. .ipaPremiumCrossPlatform: "com.brother.pdfreaderpro.cross.platform.product_1",
  1203. .ipaPermanentCrossPlatform: "com.brother.pdfreaderpro.cross.platform.product_3",
  1204. .ipaAI: "com.brother.pdfreaderpro.ai.product_1",
  1205. .ipaPremiumAI: "com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1",
  1206. .ipaPermanentAI: "com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1",
  1207. .ipaPermanentCrossPlatformAI: "com.brother.pdfreaderpro.cross.platform.product_3+com.brother.pdfreaderpro.ai.product_1"
  1208. ]
  1209. private func getProductID() -> String {
  1210. return GetHardwareUUID()!
  1211. }
  1212. private func productToType(_ productId: String) -> ProductType {
  1213. if productId == "com.brother.pdfreaderpro.mac.product_2" {
  1214. return .ipaConvert
  1215. } else if productId == "com.brother.pdfreaderpro.mac.product_2.checkout" {
  1216. return .ipaConvert_checkout
  1217. } else if productId == "com.brother.pdfreaderpro.mac.product_1" {
  1218. return .ipaPremium
  1219. } else if productId == "com.brother.pdfreaderpro.mac.product_3" {
  1220. return .ipaPermanent
  1221. } else if productId == "com.brother.pdfreaderpro.cross.platform.product_1" {
  1222. return .ipaPremiumCrossPlatform
  1223. } else if productId == "com.brother.pdfreaderpro.cross.platform.product_3" {
  1224. return .ipaPermanentCrossPlatform
  1225. } else if productId == "com.brother.pdfreaderpro.ai.product_1" {
  1226. return .ipaAI
  1227. } else if productId == "com.brother.pdfreaderpro.mac.product_1+com.brother.pdfreaderpro.ai.product_1" {
  1228. return .ipaPremiumAI
  1229. } else if productId == "com.brother.pdfreaderpro.mac.product_3+com.brother.pdfreaderpro.ai.product_1" {
  1230. return .ipaPermanentAI
  1231. } else if productId == "com.brother.pdfreaderpro.cross.platform.product_3+com.brother.pdfreaderpro.ai.product_1" {
  1232. return .ipaPermanentCrossPlatformAI
  1233. }
  1234. return .ipaConvert
  1235. }
  1236. private func isNumeric(_ text: String) -> Bool {
  1237. return !text.isEmpty && text.rangeOfCharacter(from: CharacterSet.decimalDigits.inverted) == nil
  1238. }
  1239. private func openWebView(_ urlPath: String) -> Void {
  1240. DispatchQueue.main.async { [weak self] in
  1241. guard let self = self else { return }
  1242. // let wc = KMEmbeddedPaymentPopWC.init(windowNibName: "KMEmbeddedPaymentPopWC")
  1243. self.embeddedPaymentPopWC = KMEmbeddedPaymentPopWC.currentFirstTrialWC(urlPath)
  1244. self.embeddedPaymentPopWC?.showWindow(nil)
  1245. self.embeddedPaymentPopWC?.callback = { isClose in
  1246. // let alert = NSAlert()
  1247. // alert.alertStyle = .critical
  1248. // alert.messageText = NSLocalizedString("Checking payment status", comment: "")
  1249. //// alert.informativeText = NSLocalizedString("Get License Code is empty.", comment: "")
  1250. // alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  1251. // if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  1252. // alert.beginSheetModal(for: self.window!, completionHandler: nil)
  1253. // } else {
  1254. // alert.runModal()
  1255. // }
  1256. }
  1257. }
  1258. startPolling()
  1259. }
  1260. private func scanCode(_ urlPath: String) -> Void {
  1261. DispatchQueue.main.async { [weak self] in
  1262. guard let self = self else { return }
  1263. self.payBox.contentView = self.payResult
  1264. self.payBoxHeight.constant = 262
  1265. if self.paymentMethod == .wxpay {
  1266. self.scanLabel.stringValue = NSLocalizedString("Scan QR Code with WeChat", comment: "")
  1267. self.payTypeImageView.image = NSImage(named: "EmbeddedPayment27")
  1268. } else if self.paymentMethod == .alipay {
  1269. self.scanLabel.stringValue = NSLocalizedString("Scan QR Code with AliPay", comment: "")
  1270. self.payTypeImageView.image = NSImage(named: "EmbeddedPayment28")
  1271. }
  1272. if let url = URL(string: urlPath) {
  1273. URLSession.shared.dataTask(with: url) { data, response, error in
  1274. if let data = data, let image = NSImage(data: data) {
  1275. DispatchQueue.main.async {
  1276. self.qrCodeImageView.image = image
  1277. self.startPolling()
  1278. }
  1279. } else {
  1280. print("Failed to load image or there was an error: \(error?.localizedDescription ?? "Unknown error")")
  1281. }
  1282. }.resume()
  1283. } else {
  1284. print("Invalid URL.")
  1285. }
  1286. }
  1287. }
  1288. private func pollingResult() -> Void {
  1289. DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
  1290. guard let self = self else { return }
  1291. if self.orderID == "" { return }
  1292. self._getOrderStatus(tradeNo: self.orderID, callback: { info, err in
  1293. if err != nil {
  1294. if let dataInfo = info {
  1295. if dataInfo.keys.contains("status") {
  1296. let status = dataInfo["status"] as? Int
  1297. if status == 2 {
  1298. print("支付验证成功 status == 2")
  1299. self.orderID = ""
  1300. self.stopPolling()
  1301. if dataInfo.keys.contains("license") {
  1302. let license = dataInfo["license"] as? [String]
  1303. if license!.count > 0 {
  1304. self.verificationActivate(license: license![0])
  1305. self.embeddedPaymentPopWC?.close()
  1306. self.embeddedPaymentPopWC = nil
  1307. }
  1308. // else {
  1309. // let alert = NSAlert()
  1310. // alert.alertStyle = .critical
  1311. // alert.messageText = NSLocalizedString("Connection Error", comment: "")
  1312. // alert.informativeText = NSLocalizedString("Get License Code is empty.", comment: "")
  1313. // alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  1314. // if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  1315. // alert.beginSheetModal(for: self.window!, completionHandler: nil)
  1316. // } else {
  1317. // alert.runModal()
  1318. // }
  1319. // return
  1320. // }
  1321. }
  1322. if dataInfo.keys.contains("ai_license") {
  1323. let ai_license = dataInfo["ai_license"] as? [String]
  1324. if ai_license!.count > 0 {
  1325. self.verificationActivateAIInfo(license: ai_license![0])
  1326. self.embeddedPaymentPopWC?.close()
  1327. self.embeddedPaymentPopWC = nil
  1328. }
  1329. // else {
  1330. // let alert = NSAlert()
  1331. // alert.alertStyle = .critical
  1332. // alert.messageText = NSLocalizedString("Connection Error", comment: "")
  1333. // alert.informativeText = NSLocalizedString("Get AI License Code is empty.", comment: "")
  1334. // alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  1335. // if alert.responds(to: #selector(alert.beginSheetModal(for:completionHandler:))) {
  1336. // alert.beginSheetModal(for: self.window!, completionHandler: nil)
  1337. // } else {
  1338. // alert.runModal()
  1339. // }
  1340. // return
  1341. // }
  1342. }
  1343. } else {
  1344. self.startPolling()
  1345. }
  1346. }
  1347. }
  1348. } else {
  1349. self.startPolling()
  1350. }
  1351. })
  1352. }
  1353. }
  1354. private func startPolling() {
  1355. timer = Timer(timeInterval: interval, repeats: false) { [weak self] _ in
  1356. guard let self = self else { return }
  1357. self.performTask()
  1358. }
  1359. RunLoop.main.add(timer!, forMode: .common)
  1360. }
  1361. @objc private func performTask() {
  1362. guard pollCount < maxPolls else {
  1363. stopPolling()
  1364. return
  1365. }
  1366. // 执行你的轮询任务
  1367. print("Performing polling task \(pollCount + 1)/\(maxPolls)")
  1368. pollCount += 1
  1369. pollingResult()
  1370. }
  1371. private func stopPolling() {
  1372. timer?.invalidate()
  1373. timer = nil
  1374. print("Polling task completed.")
  1375. if self.embeddedPaymentPopWC != nil {
  1376. DispatchQueue.main.async { [weak self] in
  1377. guard let self = self else { return }
  1378. self.embeddedPaymentPopWC?.close()
  1379. self.embeddedPaymentPopWC = nil
  1380. }
  1381. }
  1382. pollCount = 0
  1383. }
  1384. private func verificationActivateAIInfo(license: String) {
  1385. guard !license.isEmpty else {
  1386. return
  1387. }
  1388. let infoDic = ["cdkey": license]
  1389. AIInfoManager.default().activateAI(withInfo: infoDic) { info, error in
  1390. if self.paymentMethod == .wxpay || self.paymentMethod == .alipay {
  1391. self.qrCodeImageView.isHidden = true
  1392. self.successfullyView.isHidden = false
  1393. }
  1394. if info.isEmpty == false {
  1395. self._trackEvent_paid()
  1396. }
  1397. }
  1398. }
  1399. private func verificationActivate(license: String) {
  1400. guard !license.isEmpty else {
  1401. return
  1402. }
  1403. let infoDic = ["cdkey": license]
  1404. VerificationManager.default().activateDevice(withInfo: infoDic) { status, info, error in
  1405. if self.paymentMethod == .wxpay || self.paymentMethod == .alipay {
  1406. self.qrCodeImageView.isHidden = true
  1407. self.successfullyView.isHidden = false
  1408. }
  1409. if let data = info, data.isEmpty == false {
  1410. self._trackEvent_paid()
  1411. }
  1412. }
  1413. }
  1414. private func confirmPayment(isConfirm: Bool) {
  1415. if isConfirm {
  1416. removeButton1.isEnabled = false
  1417. addButton1.isEnabled = false
  1418. aiAddOnButton1.isEnabled = false
  1419. extendedButton1.isEnabled = false
  1420. couponButton.isEnabled = false
  1421. coupomTextField.isEnabled = false
  1422. applyButton.isEnabled = false
  1423. } else {
  1424. removeButton1.isEnabled = true
  1425. addButton1.isEnabled = true
  1426. aiAddOnButton1.isEnabled = true
  1427. extendedButton1.isEnabled = true
  1428. couponButton.isEnabled = true
  1429. coupomTextField.isEnabled = true
  1430. applyButton.isEnabled = true
  1431. }
  1432. }
  1433. private func emailErrorLabel(isReveal: Bool) {
  1434. if isReveal {
  1435. errorLabel.isHidden = false
  1436. } else {
  1437. errorLabel.isHidden = true
  1438. }
  1439. errorLabelTopLayout.constant = errorLabel.isHidden ? -CGRectGetHeight(errorView.bounds) : 4
  1440. }
  1441. private func refreshApplyButton(isReveal: Bool) {
  1442. self.applyButton.isEnabled = isReveal
  1443. }
  1444. // MARK: Show Methods
  1445. // @IBAction private func dismissSheet(_ sender: NSButton) {
  1446. // NSApp.endSheet(window!)
  1447. // window!.orderOut(self)
  1448. // }
  1449. //
  1450. //
  1451. // @objc private func didEndSheet(_ sheet: NSWindow?, returnCode: Int, contextInfo: UnsafeMutableRawPointer?) {
  1452. // if contextInfo != nil && self.handler != nil {
  1453. // self.handler!(returnCode)
  1454. // }
  1455. // }
  1456. //
  1457. // @objc func beginSheetModal(for window: NSWindow?, completionHandler handler: ((Int) -> Void)?) {
  1458. // if window != nil {
  1459. // window!.beginSheet(self.window!) { ModalResponse in
  1460. // self.handler?(ModalResponse.rawValue)
  1461. // }
  1462. // }
  1463. // self.handler = handler
  1464. // }
  1465. }
  1466. extension KMPurchaseEmbeddedWindowController: NSTextFieldDelegate {
  1467. func controlTextDidEndEditing(_ obj: Notification) {
  1468. let textField = obj.object as? NSTextField
  1469. if textField == amountTextField1 {
  1470. if !isNumeric(textField!.stringValue) {
  1471. if textField == amountTextField1 { textField?.stringValue = String(pdfCount) }
  1472. } else {
  1473. if textField == amountTextField1 {
  1474. pdfCount = Int(textField!.stringValue) ?? 1
  1475. if Int(textField!.stringValue)! > 9999 {
  1476. pdfCount = 9999
  1477. textField?.stringValue = String(pdfCount)
  1478. }
  1479. }
  1480. if pdfCount > 100 {
  1481. wechatPayButton2.isHidden = false
  1482. cardButton.isHidden = true
  1483. wechatPayButton.isHidden = true
  1484. if _paymentMethod == .paddle {
  1485. paymentMethod = .paypal
  1486. }
  1487. } else {
  1488. wechatPayButton2.isHidden = true
  1489. cardButton.isHidden = false
  1490. wechatPayButton.isHidden = false
  1491. }
  1492. }
  1493. } else if textField == emailTextField {
  1494. emailErrorLabel(isReveal: false)
  1495. } else if textField == paddleTextField {
  1496. }
  1497. }
  1498. func controlTextDidChange(_ obj: Notification) {
  1499. let textField = obj.object as? NSTextField
  1500. if textField == amountTextField1 {
  1501. if !isNumeric(textField!.stringValue) {
  1502. if textField == amountTextField1 { textField?.stringValue = String(pdfCount) }
  1503. }
  1504. }
  1505. }
  1506. }
  1507. extension KMPurchaseEmbeddedWindowController: NSWindowDelegate {
  1508. func windowWillClose(_ notification: Notification) {
  1509. if orderID != "" {
  1510. pollingResult()
  1511. }
  1512. if self.embeddedPaymentPopWC != nil {
  1513. self.embeddedPaymentPopWC?.close()
  1514. self.embeddedPaymentPopWC = nil
  1515. }
  1516. KMPurchaseEmbeddedWindowController.currentWindowController = nil
  1517. }
  1518. }
  1519. #endif