KMCheckInManager.swift 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. //
  2. // KMCheckInManager.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by User-Tangchao on 2025/1/2.
  6. //
  7. import Cocoa
  8. let kKMTrailCancelStateDidChange = Notification.Name("KMTrailCancelStateDidChangeNotificationName")
  9. @objcMembers class KMCheckInManager: NSObject {
  10. static let `default` = KMCheckInManager()
  11. // 试用退订
  12. var trailCancel = false {
  13. didSet {
  14. NotificationCenter.default.post(name: kKMTrailCancelStateDidChange, object: nil)
  15. }
  16. }
  17. private var timer_: Timer?
  18. func initLaunchData() {
  19. // 启动定时器 轮询签到
  20. var timeInterval: CGFloat = 60 * 60
  21. #if DEBUG
  22. timeInterval = 1 * 60
  23. #endif
  24. timer_ = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: true, block: { [weak self] timer in
  25. self?.checkIn(refreshData: true, callback: nil)
  26. self?.fetchCancelSubscribe(callback: nil)
  27. })
  28. }
  29. func checkIn(refreshData: Bool, callback: ((Any ...)->Void)?) {
  30. let member = KMMemberInfo.shared
  31. if member.isLogin == false {
  32. return
  33. }
  34. if member.is_advanced_year_subscribe() == false {
  35. return
  36. }
  37. if member.isCancelSubscribe() { // 已退订
  38. return
  39. }
  40. // 高级版年订阅
  41. if member.is_trailing() == false {
  42. return
  43. }
  44. let userEmail = member.userEmail
  45. if userEmail.isEmpty {
  46. return
  47. }
  48. if hasCheckInForToday(for: userEmail) { // 今天已经签到
  49. return
  50. }
  51. // 试用中 去签到
  52. KMMemberCenterManager.checkIn { success, resultModel, error in
  53. if success {
  54. if refreshData {
  55. // 刷新用户数据 [刷新试用天数]
  56. KMUserInfoVCModel().refreshUserInfo { success, msg,dic in
  57. if(success) {
  58. self.openCheckInWindow()
  59. callback?()
  60. } else {
  61. callback?()
  62. }
  63. }
  64. } else {
  65. self.openCheckInWindow()
  66. callback?()
  67. }
  68. } else {
  69. callback?()
  70. self.openCheckInWindow()
  71. }
  72. }
  73. }
  74. // 弹签到窗口
  75. func openCheckInWindow() {
  76. let member = KMMemberInfo.shared
  77. if member.isLogin == false {
  78. return
  79. }
  80. let userEmail = member.userEmail
  81. if userEmail.isEmpty {
  82. return
  83. }
  84. if hasCheckInForToday(for: userEmail) { // 今天已经签到
  85. return
  86. }
  87. // 弹签到窗口
  88. if KMCheckInWindowController.shared.needShow() {
  89. var dayNum: Int = 0
  90. for vip in KMMemberInfo.shared.activeVips {
  91. if vip.levels == "3" && vip.paymentModel == "1" && vip.cycle == 4 {
  92. dayNum = vip.trailDays
  93. break
  94. }
  95. }
  96. if dayNum == 1 || dayNum == 3 || dayNum == 7 {
  97. if fetchDayNumRecord(for: userEmail) != dayNum { // 最后记录的累积天数没有弹
  98. KMCheckInWindowController.shared.openWindow(num: dayNum)
  99. }
  100. saveRecord(dayNum: dayNum)
  101. }
  102. }
  103. }
  104. func advancedYearSubscribeTrailCancelForLocal() -> Bool {
  105. #if VERSION_FREE
  106. #if VERSION_DMG
  107. #else
  108. if KMMemberInfo.shared.isLogin {
  109. return false
  110. }
  111. let man = IAPProductsManager.default()
  112. if let model = IAPReceiptTool.fetchProductLastestReceipts(with: man?.receiptModel, withProductId: man?.fourDevicesAllAccessPackNew12months_lite?.product?.productIdentifier) {
  113. if model.is_trial_period { // 有试用过
  114. var cancelTrail = false
  115. for infoM in man?.receiptModel?.pendingRenewalInfoModels ?? [] {
  116. if model.product_id == infoM.product_id {
  117. cancelTrail = infoM.auto_renew_status == 0
  118. }
  119. }
  120. if cancelTrail { // 试用退订
  121. return true
  122. }
  123. }
  124. }
  125. #endif
  126. #endif
  127. return false
  128. }
  129. func fetchCancelSubscribe(callback: ((Any ...)->Void)?) {
  130. #if VERSION_FREE
  131. // 判断用户是否处于试用后退订
  132. KMMemberCenterManager.judgeTrailCancel { success, resultModel, error in
  133. callback?()
  134. if success == true {
  135. self.trailCancel = resultModel?.result ?? false
  136. if self.trailCancel {
  137. self.openCancelSubscribeWindow()
  138. }
  139. }
  140. }
  141. #endif
  142. }
  143. // 退订窗口
  144. func openCancelSubscribeWindow() {
  145. #if VERSION_DMG
  146. if KMDataManager.ud_bool(forKey: kKMAdvancedYearSubscribedOfTrial) == false { // 没有试用过
  147. return
  148. }
  149. // 高级版年订阅有试用过
  150. let member = KMMemberInfo.shared
  151. if member.isLogin == false {
  152. return
  153. }
  154. if member.is_advanced_year_subscribe() && member.vip_payType == 1 {
  155. // 高级版年订阅有试用 续订
  156. return
  157. }
  158. if KMCancelSubscribeSuccessWindowController.shared.needShow() {
  159. KMCancelSubscribeSuccessWindowController.shared.openWindow()
  160. }
  161. #else
  162. if KMMemberInfo.shared.isLogin == false && advancedYearSubscribeTrailCancelForLocal() { // 本地权益 高级版年订阅试用退订
  163. if KMMemberInfo.shared.isMemberAllFunction { // 有本地 或 账号权益
  164. return
  165. }
  166. let winC = KMCancelSubscribeSuccessWindowController.shared
  167. if winC.needShow() {
  168. if winC.window?.isVisible == true {
  169. } else {
  170. winC.openWindow()
  171. }
  172. }
  173. return
  174. }
  175. if KMDataManager.ud_bool(forKey: kKMAdvancedYearSubscribedOfTrial) == false { // 没有试用过
  176. return
  177. }
  178. // 高级版年订阅有试用过
  179. let member = KMMemberInfo.shared
  180. if member.isLogin == false {
  181. return
  182. }
  183. if member.is_advanced_year_subscribe() && member.isCancelSubscribe() == false {
  184. // 高级版年订阅有试用 续订
  185. return
  186. }
  187. let winC = KMCancelSubscribeSuccessWindowController.shared
  188. if winC.needShow() {
  189. if winC.window?.isVisible == true {
  190. } else {
  191. winC.openWindow()
  192. }
  193. }
  194. #endif
  195. }
  196. func hasCheckInForToday(for email: String) -> Bool {
  197. let record = fetchRecord(for: email)
  198. if record.isEmpty {
  199. return false
  200. }
  201. guard let recordTime = record["time"] as? TimeInterval, recordTime > 0 else {
  202. return false
  203. }
  204. let recordDate = Date(timeIntervalSince1970: recordTime)
  205. if recordDate.isToday() { // 今天已经签到
  206. return true
  207. }
  208. return false
  209. }
  210. func fetchDayNumRecord(for email: String) -> Int {
  211. let record = fetchRecord(for: email)
  212. if record.isEmpty {
  213. return 0
  214. }
  215. let dayNum = record["dayNum"] as? Int
  216. return dayNum ?? 0
  217. }
  218. // MARK: - Record
  219. func saveRecord(dayNum: Int) {
  220. let member = KMMemberInfo.shared
  221. if member.isLogin == false {
  222. return
  223. }
  224. let userEmail = member.userEmail
  225. if userEmail.isEmpty {
  226. return
  227. }
  228. if hasCheckInForToday(for: userEmail) { // 今天已经签到
  229. return
  230. }
  231. // 暂时没有做数量限制
  232. var dict = KMDataManager.udExtension_object(forKey: "CheckInRecords") as? [String : Any] ?? [:]
  233. let time = Date().timeIntervalSince1970
  234. let data = ["email" : userEmail, "time" : time, "dayNum" : dayNum] as [String : Any]
  235. dict[userEmail] = data
  236. KMDataManager.udExtension_set(dict , forKey: "CheckInRecords")
  237. }
  238. func fetchRecords() -> [String : Any] {
  239. let datas = KMDataManager.udExtension_object(forKey: "CheckInRecords") as? [String : Any]
  240. return datas ?? [:]
  241. }
  242. func fetchRecord(for key: String) -> [String : Any] {
  243. let data = fetchRecords()[key] as? [String : Any]
  244. return data ?? [:]
  245. }
  246. }