KMWinBackWindowController.swift 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. //
  2. // KMWinBackWindowController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by User-Tangchao on 2025/1/13.
  6. //
  7. import Cocoa
  8. import StoreKit
  9. import SwiftUI
  10. @objcMembers class KMIAPTransaction: NSObject {
  11. var transactionIdentifier: String?
  12. var productIdentifier: String?
  13. override init() {
  14. super.init()
  15. self.transactionIdentifier = ""
  16. self.productIdentifier = ""
  17. }
  18. }
  19. let KMWinBackIAPProductPurchasedNotificationName = "KMWinBackIAPProductPurchasedNotification"
  20. //class KMWinBackWindowController: KMBaseWindowController {
  21. // @IBOutlet weak var contentBox: NSBox!
  22. // @IBOutlet weak var backgroundIv: NSImageView!
  23. // @IBOutlet weak var iconIv: NSImageView!
  24. // @IBOutlet weak var titleLabel: NSTextField!
  25. // @IBOutlet weak var subTitleLabel: NSTextField!
  26. // @IBOutlet weak var despBox: NSBox!
  27. // @IBOutlet weak var buttonBox: NSBox!
  28. //
  29. // static let shared = KMWinBackWindowController(windowNibName: "KMWinBackWindowController")
  30. //
  31. // private lazy var despView_: KMWinBackDespView = {
  32. // let view = KMWinBackDespView()
  33. // return view
  34. // }()
  35. //
  36. // private lazy var buttonView_: KMWinBackButtonView = {
  37. // let view = KMWinBackButtonView()
  38. // return view
  39. // }()
  40. //
  41. // private let showCountKey_ = "WinBackWindowShowCount"
  42. // private let lastShowTimeKey_ = "WinBackWindowLastShowTime"
  43. //
  44. // private var origialPrice_: String = ""
  45. //
  46. // private var offerId_: String?
  47. // private var displayPriceString_: String = ""
  48. //
  49. // override func windowDidLoad() {
  50. // super.windowDidLoad()
  51. //
  52. // window?.standardWindowButton(.zoomButton)?.isHidden = true
  53. // window?.standardWindowButton(.miniaturizeButton)?.isHidden = true
  54. // window?.delegate = self
  55. // let closeButton = window?.standardWindowButton(.closeButton)
  56. // closeButton?.target = self
  57. // closeButton?.action = #selector(closeAction)
  58. //
  59. // despBox.borderWidth = 0
  60. // despBox.cornerRadius = 4
  61. // despBox.contentView = despView_
  62. // buttonBox.borderWidth = 0
  63. // buttonBox.cornerRadius = 4
  64. // buttonBox.contentView = buttonView_
  65. //
  66. // backgroundIv.image = NSImage(named: "KMImageNameWinBackBg")
  67. // backgroundIv.image?.size = window?.frame.size ?? NSMakeSize(520, 540)
  68. // iconIv.image = NSImage(named: "KMImageNameWinBackIcon")
  69. //
  70. // titleLabel.stringValue = NSLocalizedString("PDF Reader Pro", comment: "")
  71. // titleLabel.font = .SFProTextRegularFont(20)
  72. //
  73. // despView_.titleLabel.stringValue = NSLocalizedString("PDF Reader Pro Advanced\n - 6 Months Plan", comment: "")
  74. // despView_.tipLabel.stringValue = NSLocalizedString("Because you were previously subscribed to PDF Reader Pro, we are now delivering a special offer to you. ", comment: "")
  75. // despView_.iconIv.image = NSImage(named: "KMImageNameWinBackDespIcon")
  76. //
  77. // buttonView_.backgroundView.xRadius = 4
  78. // buttonView_.backgroundView.yRadius = 4
  79. //
  80. // buttonView_.button.font = .SFProTextRegularFont(16)
  81. // buttonView_.itemClick = { [weak self] idx, _ in
  82. // self?.trackEvent_free(eventName: "PUW_3", params: ["PUW_Btn" : "WinBackPuw_Purchase_Click"], platform: .firebase)
  83. //
  84. // self?.purchase()
  85. // }
  86. //
  87. // origialPrice_ = _fetchOrigialPrice() ?? ""
  88. //
  89. // interfaceThemeDidChanged(self.window?.appearance?.name ?? .aqua)
  90. //
  91. // if #available(macOS 15.0, *) {
  92. // var rootView = CPDFOfferSubscriptionStoreView()
  93. // rootView.eligibleOffersCallback = { offertIds in
  94. // KMPrint("你符合赢回的优惠卷:")
  95. // KMPrint(offertIds)
  96. // if offertIds.isEmpty == false {
  97. // if let data = offertIds.first, data.isEmpty == false {
  98. // if let data = self.offerId_, data.isEmpty == false {
  99. // return
  100. // }
  101. //
  102. // if self.needShow() {
  103. // self.trackEvent_free(eventName: "PUW_3", params: ["PUW_Exposure" : "WinBackPuw_Exposure"], platform: .firebase)
  104. //
  105. // self._selectOffer(offerId: data)
  106. //
  107. // self.showWindow(nil)
  108. //
  109. // self._saveRecord()
  110. //
  111. // self.window?.makeKeyAndOrderFront(nil)
  112. // } else {
  113. // KMPrint("Win Back:不需要显示")
  114. //
  115. // self.window?.close()
  116. // }
  117. // }
  118. // }
  119. // }
  120. // let hostingView = NSHostingView(rootView: rootView)
  121. //
  122. // hostingView.frame = NSRect(x: 0, y: 0, width: 1000, height: 1000)
  123. // contentBox.addSubview(hostingView, positioned: .below, relativeTo: backgroundIv)
  124. //
  125. // hostingView.isHidden = true
  126. // } else {
  127. // self.window?.close()
  128. // }
  129. //
  130. //// https://api.storekit.itunes.apple.com/inApps/v1/subscriptions/{transactionId}
  131. //// https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions/{transactionId}
  132. //
  133. // // /2000000828945111
  134. //// let url = "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions"
  135. ////// let urlString = KMMemberCenterConfig().activityBaseURL() + url
  136. //// // ["transactionId" : "2000000828945111"]
  137. //// KMRequestServer.requestServer.request(urlString: url, method: .get, params: nil) { requestSerializer in
  138. ////// requestSerializer.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
  139. //// } completion: { task, responseObject, error in
  140. //// guard let dict = responseObject as? [String : Any] else {
  141. ////// callback(false, nil, error)
  142. //// return
  143. //// }
  144. ////
  145. //// let model = KMRequestResultModel(dict: dict)
  146. ////// callback(model.isSuccess(), model, error)
  147. //// }
  148. //// KMRequestServer.requestServer.request(urlString: url, method: .get, params: nil, completion:?)
  149. //
  150. //// Self.GET(urlString: url, parameter: nil) { success , result , err in
  151. //// KMPrint("")
  152. //// }
  153. // }
  154. //
  155. // public class func GET(urlString: String, parameter: [String : String]? = nil, headers: [String : String]? = nil, callback:@escaping ((Bool, [String : Any]?, String?)->Void)) {
  156. //// var _urlString = "\(self.baseUrl)"+urlString
  157. // var _urlString = urlString
  158. // if let data = parameter, !data.isEmpty {
  159. // _urlString.append("?")
  160. // var i = 0
  161. // for (key, value) in data {
  162. // _urlString.append("\(key)=\(value)")
  163. // if (data.count > 1 && i != data.count-1) {
  164. // _urlString.append("&")
  165. // }
  166. // i += 1
  167. // }
  168. // }
  169. //
  170. // let url: URL = URL(string: _urlString)!
  171. //
  172. // let session = URLSession.shared
  173. // var request = URLRequest(url: url)
  174. // request.httpMethod = "GET"
  175. // request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")
  176. // if let _headers = headers {
  177. // for (key, value) in _headers {
  178. // request.setValue(value, forHTTPHeaderField: key)
  179. // }
  180. // }
  181. // request.timeoutInterval = 60.0
  182. // session.configuration.timeoutIntervalForRequest = 30.0
  183. //
  184. // let task: URLSessionDataTask = session.dataTask(with: request) { data , response, error in
  185. // DispatchQueue.main.async {
  186. // if let _ = error {
  187. // callback(false, nil, error.debugDescription)
  188. // return
  189. // }
  190. // guard let _data = data else {
  191. // callback(false, nil, error.debugDescription)
  192. // return
  193. // }
  194. // if let result = self.JsonDataParse(data: _data) {
  195. //// let resultMap = KMRequestResultModel(dict: result)
  196. //// var dataDict: [String : Any] = [:]
  197. //// if let data = resultMap.data as? [String : Any] {
  198. //// dataDict = data
  199. //// } else {
  200. //// if let dataArray = resultMap.data as? [Any] {
  201. //// var i = 0
  202. //// for dict in dataArray {
  203. //// dataDict["\(i)"] = dict
  204. //// i += 1
  205. //// }
  206. //// }
  207. //// }
  208. ////
  209. //// callback(resultMap.isSuccess(), dataDict, error.debugDescription)
  210. //// return
  211. // }
  212. //// callback(false, nil, error.debugDescription)
  213. // }
  214. // }
  215. // task.resume()
  216. // }
  217. //
  218. // private class func JsonDataParse(data: Data) -> Dictionary<String,Any>? {
  219. // let result = try?JSONSerialization.jsonObject(with: data, options: .mutableContainers)
  220. // return result as? Dictionary<String, Any>
  221. // }
  222. //
  223. // @objc func closeAction() {
  224. // self.trackEvent_free(eventName: "PUW_3", params: ["PUW_Btn" : "WinBackPuw_Cancel_Click"], platform: .firebase)
  225. //
  226. // window?.close()
  227. // }
  228. //
  229. // override func interfaceThemeDidChanged(_ appearance: NSAppearance.Name) {
  230. // super.interfaceThemeDidChanged(appearance)
  231. //
  232. // KMMainThreadExecute {
  233. // if KMAppearance.isDarkMode() {
  234. // self.titleLabel.textColor = .white
  235. //
  236. // let attri = NSMutableAttributedString(string: NSLocalizedString("Special Offer - ", comment: ""), attributes: [.font : NSFont.SFProTextRegularFont(32), .foregroundColor : NSColor.white])
  237. // attri.append(.init(string: self.displayPriceString_, attributes: [.font : NSFont.SFProTextRegularFont(32), .foregroundColor : NSColor(hex: "#FD7272")]))
  238. // attri.append(.init(string: self.origialPrice_, attributes: [.font : NSFont.SFProTextRegularFont(24), .foregroundColor : NSColor(hex: "#7E7F85"), .strikethroughStyle : NSUnderlineStyle.single.rawValue]))
  239. // let style = NSMutableParagraphStyle()
  240. // style.alignment = .center
  241. // attri.addAttribute(.paragraphStyle, value: style, range: NSMakeRange(0, attri.length))
  242. // self.subTitleLabel.attributedStringValue = attri
  243. //
  244. // self.despBox.fillColor = NSColor.white.withAlphaComponent(0.15)
  245. // self.despView_.titleLabel.textColor = .white
  246. //
  247. // let despAttri = NSMutableAttributedString(string: NSLocalizedString("First 6 months", comment: "")+" ", attributes: [.font : NSFont.SFProTextRegularFont(14), .foregroundColor : NSColor.white])
  248. // despAttri.append(.init(string: self.displayPriceString_, attributes: [.font : NSFont.SFProTextRegularFont(14), .foregroundColor : NSColor(hex: "#227AFF")]))
  249. // let string = ", " + String(format: NSLocalizedString("then %@ for 6 months.", comment: ""), self.origialPrice_)
  250. // despAttri.append(.init(string: string, attributes: [.font : NSFont.SFProTextRegularFont(14), .foregroundColor : NSColor.white]))
  251. // self.despView_.subTitleLabel.attributedStringValue = despAttri
  252. //
  253. // self.despView_.hLine.layer?.backgroundColor = NSColor.white.withAlphaComponent(0.15).cgColor
  254. //
  255. // self.despView_.tipLabel.textColor = NSColor(hex: "#C8C9CC")
  256. // } else {
  257. // self.titleLabel.textColor = NSColor(hex: "#0E1114")
  258. //
  259. // let attri = NSMutableAttributedString(string: NSLocalizedString("Special Offer - ", comment: ""), attributes: [.font : NSFont.SFProTextRegularFont(32), .foregroundColor : NSColor(hex: "#000150")])
  260. // attri.append(.init(string: self.displayPriceString_, attributes: [.font : NSFont.SFProTextRegularFont(32), .foregroundColor : NSColor(hex: "#FD7272")]))
  261. // attri.append(.init(string: self.origialPrice_, attributes: [.font : NSFont.SFProTextRegularFont(24), .foregroundColor : NSColor(hex: "#757780"), .strikethroughStyle : NSUnderlineStyle.single.rawValue]))
  262. // let style = NSMutableParagraphStyle()
  263. // style.alignment = .center
  264. // attri.addAttribute(.paragraphStyle, value: style, range: NSMakeRange(0, attri.length))
  265. // self.subTitleLabel.attributedStringValue = attri
  266. //
  267. // self.despBox.fillColor = .white
  268. // self.despView_.titleLabel.textColor = NSColor(hex: "#0E1114")
  269. //
  270. // let despAttri = NSMutableAttributedString(string: NSLocalizedString("First 6 months", comment: "")+" ", attributes: [.font : NSFont.SFProTextRegularFont(14), .foregroundColor : NSColor(hex: "#000150")])
  271. // despAttri.append(.init(string: self.displayPriceString_, attributes: [.font : NSFont.SFProTextRegularFont(14), .foregroundColor : NSColor(hex: "#4982E6")]))
  272. // let string = ", " + String(format: NSLocalizedString("then %@ for 6 months.", comment: ""), self.origialPrice_)
  273. // despAttri.append(.init(string: string, attributes: [.font : NSFont.SFProTextRegularFont(14), .foregroundColor : NSColor(hex: "#000150")]))
  274. // self.despView_.subTitleLabel.attributedStringValue = despAttri
  275. //
  276. // self.despView_.hLine.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.15).cgColor
  277. //
  278. // self.despView_.tipLabel.textColor = NSColor(hex: "#757780")
  279. // }
  280. //
  281. // self.buttonView_.backgroundView.colors = [NSColor(hex: "#F8965A"), NSColor(hex: "#FD7171")]
  282. //
  283. // self.buttonView_.button.title = NSLocalizedString("Get Special Offer - Advanced 6 Mos", comment: "")
  284. // self.buttonView_.button.setTitleColor(.white)
  285. // }
  286. // }
  287. //
  288. // // MARK: - Private Methods
  289. //
  290. // private func _showCenter(animate: Bool){
  291. // guard let screenFrame = NSScreen.main?.frame else {
  292. // return
  293. // }
  294. // guard let win = self.window else {
  295. // return
  296. // }
  297. //
  298. // var frame = win.frame
  299. // frame.origin.y = (screenFrame.size.height-frame.size.height)*0.5
  300. // frame.origin.x = (screenFrame.size.width-frame.size.width)*0.5
  301. // win.setFrame(frame, display: true, animate: animate)
  302. // }
  303. //
  304. // // MARK: - Private Methods
  305. //
  306. // private func _saveRecord() {
  307. // let lastShowTime = KMDataManager.ud_double(forKey: lastShowTimeKey_)
  308. // if lastShowTime <= 0 {
  309. // let cnt = KMDataManager.ud_integer(forKey: showCountKey_)
  310. // KMDataManager.ud_set(cnt+1, forKey: showCountKey_)
  311. //
  312. // let date = Date().timeIntervalSince1970
  313. // KMDataManager.ud_set(date, forKey: lastShowTimeKey_)
  314. // return
  315. // }
  316. //
  317. // let date = Date(timeIntervalSince1970: lastShowTime)
  318. //
  319. // let calendar = Calendar.current
  320. // let unit: Set<Calendar.Component> = [.day,.month,.year]
  321. // let nowComps = calendar.dateComponents(unit, from: Date())
  322. // let selfCmps = calendar.dateComponents(unit, from: date)
  323. //
  324. // let theYear = selfCmps.year ?? 0
  325. // let theMonth = selfCmps.month ?? 0
  326. // let theDay = selfCmps.day ?? 0
  327. // let otherYear = nowComps.year ?? 0
  328. // let otherMonth = nowComps.month ?? 0
  329. // let otherDay = nowComps.day ?? 0
  330. //
  331. // if otherYear > theYear || otherMonth > theMonth {
  332. // let cnt = KMDataManager.ud_integer(forKey: showCountKey_)
  333. // KMDataManager.ud_set(cnt+1, forKey: showCountKey_)
  334. //
  335. // let date = Date().timeIntervalSince1970
  336. // KMDataManager.ud_set(date, forKey: lastShowTimeKey_)
  337. // return
  338. // }
  339. //
  340. // if otherDay - theDay >= 1 {
  341. // let cnt = KMDataManager.ud_integer(forKey: showCountKey_)
  342. // KMDataManager.ud_set(cnt+1, forKey: showCountKey_)
  343. //
  344. // let date = Date().timeIntervalSince1970
  345. // KMDataManager.ud_set(date, forKey: lastShowTimeKey_)
  346. // return
  347. // }
  348. // }
  349. //
  350. // private func _fetchOrigialPrice() -> String? {
  351. // return IAPProductsManager.default().fourDevicesAllAccessPackNew6Months_lite?.price()
  352. // }
  353. //
  354. // private func _selectOffer(offerId: String) {
  355. // offerId_ = offerId
  356. // if #available(macOS 12.0, *) {
  357. // winbackOffers(productId: "com.pdfreaderpro.mac_free.member.all_access_pack_advanced_6months.001") { offsers in
  358. // for offse in offsers {
  359. // let data = offse.id
  360. // if data == offerId {
  361. // self.displayPriceString_ = offse.displayPrice
  362. //
  363. // self.origialPrice_ = self._fetchOrigialPrice() ?? ""
  364. //
  365. // self.interfaceThemeDidChanged(self.window?.appearance?.name ?? .aqua)
  366. // }
  367. // }
  368. // }
  369. // } else {
  370. //
  371. // }
  372. // }
  373. //
  374. // private func _showAlert(message: String) {
  375. // KMMainThreadExecute {
  376. // let alert = NSAlert()
  377. // alert.alertStyle = .critical
  378. // alert.messageText = message
  379. // alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  380. // alert.runModal()
  381. // }
  382. // }
  383. //
  384. // private func _beginLoading() {
  385. // self.window?.contentView?.beginLoading()
  386. // }
  387. //
  388. // private func _endLoading() {
  389. // self.window?.contentView?.endLoading()
  390. // }
  391. //
  392. // // MARK: - Public Methods
  393. //
  394. // public func openWindow() {
  395. //// self.showWindow(nil)
  396. //
  397. // if #available(macOS 12.0, *) {
  398. // winbackOffers(productId: "com.pdfreaderpro.mac_free.member.all_access_pack_advanced_6months.001") { [weak self] offers in
  399. // if offers.isEmpty { // 商品没有配置 Win Back 优惠卷
  400. // self?.window?.setIsVisible(false)
  401. // self?.window?.close()
  402. // } else {
  403. // if let data = self?.offerId_, data.isEmpty == false {
  404. // // no things
  405. // } else {
  406. // self?.showWindow(nil)
  407. //
  408. // self?.window?.setIsVisible(false)
  409. // self?.window?.close()
  410. // }
  411. // }
  412. // }
  413. // } else {
  414. // window?.setIsVisible(false)
  415. // window?.close()
  416. // }
  417. // }
  418. //
  419. // public func needShow() -> Bool {
  420. // if #available(macOS 15.0, iOS 18.0, *) {
  421. // if KMDataManager.ud_integer(forKey: showCountKey_) >= 3 {
  422. //#if DEBUG
  423. // return true
  424. //#else
  425. // return false
  426. //#endif
  427. // }
  428. //
  429. // let lastShowTime = KMDataManager.ud_double(forKey: lastShowTimeKey_)
  430. // if lastShowTime > 0 {
  431. // let date = Date(timeIntervalSince1970: lastShowTime)
  432. // if date.isToday() {
  433. //#if DEBUG
  434. //#else
  435. // return false
  436. //#endif
  437. // }
  438. // }
  439. //
  440. // if KMNewUserGiftManager.default.loginProgressState == .none || KMNewUserGiftManager.default.fetchReceiptProgressState == .none {
  441. // return false
  442. // }
  443. //
  444. // let member = KMMemberInfo.shared
  445. //// if member.isLogin {
  446. //// if member.is_advanced() && member.is_subscribe() && (member.is_year() || member.is_half_year()) {
  447. //// return false
  448. //// }
  449. //// }
  450. // if member.isMemberAllFunction { // 有本地或账号权益
  451. // return false
  452. // }
  453. //
  454. // return true
  455. // }
  456. // return false
  457. // }
  458. //
  459. // public func clearRecord() {
  460. // KMDataManager.ud_set(0, forKey: showCountKey_)
  461. // KMDataManager.ud_set(0, forKey: lastShowTimeKey_)
  462. // }
  463. //
  464. // @available(macOS 12.0, *)
  465. // public func winbackOffers(productId: String?, callback: (([Product.SubscriptionOffer])->Void)?) {
  466. // if #available(macOS 15.0, iOS 18.0, *) {
  467. // guard let theProductId = productId else {
  468. // callback?([])
  469. // return
  470. // }
  471. //
  472. // Task {
  473. // let products = try await Product.products(for: [theProductId])
  474. // guard let product = products.first else {
  475. // callback?([])
  476. // return
  477. // }
  478. //
  479. // guard let subscriptionInfo = product.subscription else {
  480. // callback?([])
  481. // return
  482. // }
  483. //
  484. // callback?(subscriptionInfo.winBackOffers)
  485. // }
  486. // } else {
  487. // callback?([])
  488. // }
  489. // }
  490. //
  491. // public func purchase() {
  492. // Task { @MainActor in
  493. // // 加载产品
  494. // if #available(macOS 15.0, *) {
  495. // let products = try? await Product.products(for: ["com.pdfreaderpro.mac_free.member.all_access_pack_advanced_6months.001"])
  496. // guard let product = products?.first else {
  497. // _showAlert(message: "未找到指定的产品")
  498. // return
  499. // }
  500. //
  501. // // 确保产品为订阅类型
  502. // guard let subscriptionInfo = product.subscription else {
  503. // _showAlert(message: "该产品不是订阅类型")
  504. // return
  505. // }
  506. //
  507. // // 查找可用的 Win-Back Offer
  508. // KMPrint("product:\(product)")
  509. // KMPrint("subscriptionInfo.winBackOffers:\(subscriptionInfo.winBackOffers)")
  510. // let offers = subscriptionInfo.winBackOffers
  511. //
  512. // var off: Product.SubscriptionOffer?
  513. // for offer in offers {
  514. // if self.offerId_ == offer.id {
  515. // off = offer
  516. // break
  517. // }
  518. // }
  519. //
  520. // guard let winBackOffer = off else {
  521. // KMPrint("没有找到适合用户的 Win-Back Offer")
  522. // _showAlert(message: "No Offer")
  523. // return
  524. // }
  525. //
  526. // // 使用 Win-Back Offer 创建购买选项
  527. // let purchaseOption = Product.PurchaseOption.winBackOffer(winBackOffer)
  528. //
  529. // self._beginLoading()
  530. // // 发起购买
  531. // let purchaseResult = try await product.purchase(options: [purchaseOption])
  532. // switch purchaseResult {
  533. // case .success(let verificationResult):
  534. // self._endLoading()
  535. //
  536. // switch verificationResult {
  537. // case .verified(let transaction):
  538. // KMPrint("购买成功:\(transaction.id)")
  539. // await transaction.finish()
  540. //
  541. // DispatchQueue.main.asyncAfter(deadline: .now()+1) {
  542. // self.window?.close()
  543. //
  544. // let man = IAPProductsManager.default()
  545. // man?.winbackIAPPurchased(withProdcutId: transaction.productID, transactionId: "\(transaction.id)")
  546. // }
  547. //
  548. // case .unverified(_, let error):
  549. // KMPrint("验证失败:\(error)")
  550. // }
  551. // case .userCancelled:
  552. // KMPrint("用户取消了购买")
  553. // self._endLoading()
  554. // case .pending:
  555. // KMPrint("购买失败")
  556. // @unknown default:
  557. // KMPrint("购买失败")
  558. // }
  559. // }
  560. // }
  561. // }
  562. //}
  563. //
  564. //// MARK: - NSWindowDelegate
  565. //
  566. //extension KMWinBackWindowController: NSWindowDelegate {
  567. // func windowDidResize(_ notification: Notification) {
  568. // guard let data = window?.isEqual(to: notification.object), data == true else {
  569. // return
  570. // }
  571. // backgroundIv.image?.size = window?.frame.size ?? NSMakeSize(520, 540)
  572. // }
  573. //}