IAPReceiptModel.m 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. //
  2. // IAPReceiptModel.m
  3. // PDF Reader Pro
  4. //
  5. // Created by User-Tangchao on 2025/1/1.
  6. //
  7. #import "IAPReceiptModel.h"
  8. @implementation IAPReceiptInfoModel
  9. + (instancetype)modelWithDict:(NSDictionary *)dict {
  10. return [[[self class] alloc] initWithDict:dict];
  11. }
  12. - (instancetype)initWithDict:(NSDictionary *)dict {
  13. if (self = [super init]) {
  14. // [self setValuesForKeysWithDictionary:dict ? dict : [NSDictionary new]];
  15. if ([dict[@"product_id"] isKindOfClass:[NSString class]]) {
  16. self.product_id = dict[@"product_id"];
  17. }
  18. if ([dict[@"purchase_date"] isKindOfClass:[NSString class]]) {
  19. self.purchase_date = dict[@"purchase_date"];
  20. }
  21. if ([dict[@"purchase_date_ms"] isKindOfClass:[NSString class]]) {
  22. self.purchase_date_ms = dict[@"purchase_date_ms"];
  23. }
  24. if ([dict[@"purchase_date_pst"] isKindOfClass:[NSString class]]) {
  25. self.purchase_date_pst = dict[@"purchase_date_pst"];
  26. }
  27. if ([dict[@"expires_date"] isKindOfClass:[NSString class]]) {
  28. self.expires_date = dict[@"expires_date"];
  29. }
  30. if ([dict[@"expires_date_ms"] isKindOfClass:[NSString class]]) {
  31. self.expires_date_ms = dict[@"expires_date_ms"];
  32. }
  33. if ([dict[@"expires_date_pst"] isKindOfClass:[NSString class]]) {
  34. self.expires_date_pst = dict[@"expires_date_pst"];
  35. }
  36. if ([dict[@"original_purchase_date"] isKindOfClass:[NSString class]]) {
  37. self.original_purchase_date = dict[@"original_purchase_date"];
  38. }
  39. if ([dict[@"original_purchase_date_ms"] isKindOfClass:[NSString class]]) {
  40. self.original_purchase_date_ms = dict[@"original_purchase_date_ms"];
  41. }
  42. if ([dict[@"original_purchase_date_pst"] isKindOfClass:[NSString class]]) {
  43. self.original_purchase_date_pst = dict[@"original_purchase_date_pst"];
  44. }
  45. if ([dict[@"original_transaction_id"] isKindOfClass:[NSString class]]) {
  46. self.original_transaction_id = dict[@"original_transaction_id"];
  47. }
  48. if ([dict[@"transaction_id"] isKindOfClass:[NSString class]]) {
  49. self.transaction_id = dict[@"transaction_id"];
  50. }
  51. if ([dict[@"subscription_group_identifier"] isKindOfClass:[NSString class]]) {
  52. self.subscription_group_identifier = dict[@"subscription_group_identifier"];
  53. }
  54. if ([dict[@"in_app_ownership_type"] isKindOfClass:[NSString class]]) {
  55. self.in_app_ownership_type = dict[@"in_app_ownership_type"];
  56. }
  57. if ([dict[@"is_in_intro_offer_period"] isKindOfClass:[NSNumber class]]) {
  58. self.is_in_intro_offer_period = [dict[@"is_in_intro_offer_period"] boolValue];
  59. } else if ([dict[@"is_in_intro_offer_period"] isKindOfClass:[NSString class]]) {
  60. self.is_in_intro_offer_period = [dict[@"is_in_intro_offer_period"] boolValue];
  61. }
  62. if ([dict[@"is_trial_period"] isKindOfClass:[NSNumber class]]) {
  63. self.is_trial_period = [dict[@"is_trial_period"] boolValue];
  64. } else if ([dict[@"is_trial_period"] isKindOfClass:[NSString class]]) {
  65. self.is_trial_period = [dict[@"is_trial_period"] boolValue];
  66. }
  67. if ([dict[@"quantity"] isKindOfClass:[NSNumber class]]) {
  68. self.quantity = [dict[@"quantity"] intValue];
  69. } else if ([dict[@"quantity"] isKindOfClass:[NSString class]]) {
  70. self.quantity = [dict[@"quantity"] intValue];
  71. }
  72. if ([dict[@"promotional_offer_id"] isKindOfClass:[NSString class]]) {
  73. self.promotional_offer_id = dict[@"promotional_offer_id"];
  74. }
  75. if ([dict[@"web_order_line_item_id"] isKindOfClass:[NSString class]]) {
  76. self.web_order_line_item_id = dict[@"web_order_line_item_id"];
  77. }
  78. }
  79. return self;
  80. }
  81. - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
  82. NSLog(@"forUndefinedKey: %@", key);
  83. }
  84. @end
  85. @implementation IAPPendingRenewalInfoModel
  86. + (instancetype)modelWithDict:(NSDictionary *)dict {
  87. return [[[self class] alloc] initWithDict:dict];
  88. }
  89. - (instancetype)initWithDict:(NSDictionary *)dict {
  90. if (self = [super init]) {
  91. // [self setValuesForKeysWithDictionary:dict ? dict : [NSDictionary new]];
  92. if ([dict[@"auto_renew_product_id"] isKindOfClass:[NSString class]]) {
  93. self.auto_renew_product_id = dict[@"auto_renew_product_id"];
  94. }
  95. if ([dict[@"auto_renew_status"] isKindOfClass:[NSNumber class]]) {
  96. self.auto_renew_status = [dict[@"auto_renew_status"] intValue];
  97. } else if ([dict[@"auto_renew_status"] isKindOfClass:[NSString class]]) {
  98. self.auto_renew_status = [dict[@"auto_renew_status"] intValue];
  99. }
  100. if ([dict[@"expiration_intent"] isKindOfClass:[NSNumber class]]) {
  101. self.expiration_intent = [dict[@"expiration_intent"] intValue];
  102. } else if ([dict[@"expiration_intent"] isKindOfClass:[NSString class]]) {
  103. self.expiration_intent = [dict[@"expiration_intent"] intValue];
  104. }
  105. if ([dict[@"is_in_billing_retry_period"] isKindOfClass:[NSNumber class]]) {
  106. self.is_in_billing_retry_period = [dict[@"is_in_billing_retry_period"] intValue];
  107. } else if ([dict[@"is_in_billing_retry_period"] isKindOfClass:[NSString class]]) {
  108. self.is_in_billing_retry_period = [dict[@"is_in_billing_retry_period"] intValue];
  109. }
  110. if ([dict[@"product_id"] isKindOfClass:[NSString class]]) {
  111. self.product_id = dict[@"product_id"];
  112. }
  113. }
  114. return self;
  115. }
  116. - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
  117. NSLog(@"forUndefinedKey: %@", key);
  118. }
  119. @end
  120. @implementation IAPInAppReceiptModel
  121. + (instancetype)modelWithDict:(NSDictionary *)dict {
  122. return [[[self class] alloc] initWithDict:dict];
  123. }
  124. - (instancetype)initWithDict:(NSDictionary *)dict {
  125. if (self = [super init]) {
  126. // [self setValuesForKeysWithDictionary:dict ? dict : [NSDictionary new]];
  127. if ([dict[@"adam_id"] isKindOfClass:[NSNumber class]]) {
  128. self.adam_id = [dict[@"adam_id"] intValue];
  129. } else if ([dict[@"adam_id"] isKindOfClass:[NSString class]]) {
  130. self.adam_id = [dict[@"adam_id"] intValue];
  131. }
  132. if ([dict[@"app_item_id"] isKindOfClass:[NSNumber class]]) {
  133. self.app_item_id = [dict[@"app_item_id"] intValue];
  134. } else if ([dict[@"app_item_id"] isKindOfClass:[NSString class]]) {
  135. self.app_item_id = [dict[@"app_item_id"] intValue];
  136. }
  137. if ([dict[@"application_version"] isKindOfClass:[NSString class]]) {
  138. self.application_version = dict[@"application_version"];
  139. }
  140. if ([dict[@"bundle_id"] isKindOfClass:[NSString class]]) {
  141. self.bundle_id = dict[@"bundle_id"];
  142. }
  143. if ([dict[@"download_id"] isKindOfClass:[NSNumber class]]) {
  144. self.download_id = [dict[@"download_id"] intValue];
  145. } else if ([dict[@"download_id"] isKindOfClass:[NSString class]]) {
  146. self.download_id = [dict[@"download_id"] intValue];
  147. }
  148. if ([dict[@"version_external_identifier"] isKindOfClass:[NSNumber class]]) {
  149. self.version_external_identifier = [dict[@"version_external_identifier"] intValue];
  150. } else if ([dict[@"version_external_identifier"] isKindOfClass:[NSString class]]) {
  151. self.version_external_identifier = [dict[@"version_external_identifier"] intValue];
  152. }
  153. if ([dict[@"original_application_version"] isKindOfClass:[NSString class]]) {
  154. self.original_application_version = dict[@"original_application_version"];
  155. }
  156. if ([dict[@"original_purchase_date"] isKindOfClass:[NSString class]]) {
  157. self.original_purchase_date = dict[@"original_purchase_date"];
  158. }
  159. if ([dict[@"original_purchase_date_ms"] isKindOfClass:[NSString class]]) {
  160. self.original_purchase_date_ms = dict[@"original_purchase_date_ms"];
  161. }
  162. if ([dict[@"original_purchase_date_pst"] isKindOfClass:[NSString class]]) {
  163. self.original_purchase_date_pst = dict[@"original_purchase_date_pst"];
  164. }
  165. if ([dict[@"receipt_creation_date"] isKindOfClass:[NSString class]]) {
  166. self.receipt_creation_date = dict[@"receipt_creation_date"];
  167. }
  168. if ([dict[@"receipt_creation_date_ms"] isKindOfClass:[NSString class]]) {
  169. self.receipt_creation_date_ms = dict[@"receipt_creation_date_ms"];
  170. }
  171. if ([dict[@"receipt_creation_date_pst"] isKindOfClass:[NSString class]]) {
  172. self.receipt_creation_date_pst = dict[@"receipt_creation_date_pst"];
  173. }
  174. if ([dict[@"receipt_type"] isKindOfClass:[NSString class]]) {
  175. self.receipt_type = dict[@"receipt_type"];
  176. }
  177. if ([dict[@"request_date"] isKindOfClass:[NSString class]]) {
  178. self.request_date = dict[@"request_date"];
  179. }
  180. if ([dict[@"request_date_ms"] isKindOfClass:[NSString class]]) {
  181. self.request_date_ms = dict[@"request_date_ms"];
  182. }
  183. if ([dict[@"request_date_pst"] isKindOfClass:[NSString class]]) {
  184. self.request_date_pst = dict[@"request_date_pst"];
  185. }
  186. if ([dict[@"in_app"] isKindOfClass:[NSArray class]]) {
  187. self.in_app = dict[@"in_app"];
  188. }
  189. NSMutableArray *inAppModelArray = [NSMutableArray arrayWithCapacity:4];
  190. for (NSDictionary *dict in self.in_app) {
  191. IAPReceiptInfoModel *model = [IAPReceiptInfoModel modelWithDict:dict];
  192. [inAppModelArray addObject:model];
  193. }
  194. self.inAppModels = [inAppModelArray copy];
  195. }
  196. return self;
  197. }
  198. - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
  199. NSLog(@"forUndefinedKey: %@", key);
  200. }
  201. @end
  202. @implementation IAPReceiptModel
  203. + (instancetype)modelWithDict:(NSDictionary *)dict {
  204. return [[[self class] alloc] initWithDict:dict];
  205. }
  206. - (instancetype)initWithDict:(NSDictionary *)dict {
  207. if (self = [super init]) {
  208. // [self setValuesForKeysWithDictionary:dict ? dict : [NSDictionary new]];
  209. if ([dict[@"environment"] isKindOfClass:[NSString class]]) {
  210. self.environment = dict[@"environment"];
  211. }
  212. if ([dict[@"is_sandbox"] isKindOfClass:[NSNumber class]]) {
  213. self.is_sandbox = [dict[@"is_sandbox"] boolValue];
  214. } else if ([dict[@"is_sandbox"] isKindOfClass:[NSString class]]) {
  215. self.is_sandbox = [dict[@"is_sandbox"] boolValue];
  216. }
  217. if ([dict[@"latest_receipt"] isKindOfClass:[NSString class]]) {
  218. self.latest_receipt = dict[@"latest_receipt"];
  219. }
  220. if ([dict[@"status"] isKindOfClass:[NSNumber class]]) {
  221. self.status = [dict[@"status"] intValue];
  222. } else if ([dict[@"status"] isKindOfClass:[NSString class]]) {
  223. self.status = [dict[@"status"] intValue];
  224. }
  225. if ([dict[@"latest_receipt_info"] isKindOfClass:[NSArray class]]) {
  226. self.latest_receipt_info = dict[@"latest_receipt_info"];
  227. }
  228. if ([dict[@"pending_renewal_info"] isKindOfClass:[NSArray class]]) {
  229. self.pending_renewal_info = dict[@"pending_renewal_info"];
  230. }
  231. if ([dict[@"receipt"] isKindOfClass:[NSDictionary class]]) {
  232. self.receipt = dict[@"receipt"];
  233. }
  234. IAPInAppReceiptModel *receiptM = [IAPInAppReceiptModel modelWithDict:self.receipt ? self.receipt : [NSDictionary new]];
  235. self.receiptModel = receiptM;
  236. NSMutableArray *latestReceiptInfoModelArray = [NSMutableArray arrayWithCapacity:4];
  237. for (NSDictionary *dict in self.latest_receipt_info) {
  238. IAPReceiptInfoModel *model = [IAPReceiptInfoModel modelWithDict:dict];
  239. [latestReceiptInfoModelArray addObject:model];
  240. }
  241. self.latestReceiptInfoModels = [latestReceiptInfoModelArray copy];
  242. NSMutableArray *pendingRenewalInfoModelArray = [NSMutableArray arrayWithCapacity:4];
  243. for (NSDictionary *dict in self.pending_renewal_info) {
  244. IAPPendingRenewalInfoModel *model = [IAPPendingRenewalInfoModel modelWithDict:dict];
  245. [pendingRenewalInfoModelArray addObject:model];
  246. }
  247. self.pendingRenewalInfoModels = [pendingRenewalInfoModelArray copy];
  248. }
  249. return self;
  250. }
  251. - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
  252. NSLog(@"forUndefinedKey: %@", key);
  253. }
  254. @end
  255. @implementation IAPReceiptTool
  256. + (BOOL)isFreeTrailingWithModel:(IAPReceiptModel *)model withProductId:(NSString *)productId {
  257. IAPReceiptInfoModel *lastestM = [self fetchProductLastestReceiptsWithModel:model withProductId:productId];
  258. if (lastestM == nil) {
  259. return false;
  260. }
  261. if (lastestM.is_trial_period == false) {
  262. return false;
  263. }
  264. long long expiresDate = [lastestM.expires_date_ms longLongValue]/1000;
  265. long long currentDate = [[NSDate date] timeIntervalSince1970];
  266. BOOL isActive = (expiresDate > currentDate) ? YES : NO;
  267. return isActive;
  268. }
  269. + (BOOL)isNewUserWithModel:(IAPReceiptModel *)model withGroupIdentifier:(NSString *)groupIdentifier {
  270. if ([self hasFreeTrialWithModel:model withGroupIdentifier:groupIdentifier]) {
  271. return false;
  272. }
  273. if ([self hasIntroOfferWithModel:model withGroupIdentifier:groupIdentifier]) {
  274. return false;
  275. }
  276. return true;
  277. }
  278. + (BOOL)hasFreeTrialWithModel:(IAPReceiptModel *)model withGroupIdentifier:(NSString *)groupIdentifier {
  279. for (IAPReceiptInfoModel *m in [self fetchReceiptsWithModel:model withGroupIdentifier:groupIdentifier]) {
  280. if (m.is_trial_period) {
  281. return true;
  282. }
  283. }
  284. return false;
  285. }
  286. + (BOOL)hasIntroOfferWithModel:(IAPReceiptModel *)model withGroupIdentifier:(NSString *)groupIdentifier {
  287. for (IAPReceiptInfoModel *m in [self fetchReceiptsWithModel:model withGroupIdentifier:groupIdentifier]) {
  288. if (m.is_in_intro_offer_period) {
  289. return true;
  290. }
  291. }
  292. return false;
  293. }
  294. + (NSArray<IAPReceiptInfoModel *> *)fetchReceiptsWithModel:(IAPReceiptModel *)model withGroupIdentifier:(NSString *)groupIdentifier {
  295. NSMutableArray *results = [NSMutableArray arrayWithCapacity:4];
  296. for (IAPReceiptInfoModel *m in [self fetchReceiptsWithModel:model]) {
  297. if ([m.subscription_group_identifier isEqualToString:groupIdentifier] == false) {
  298. continue;
  299. }
  300. [results addObject:m];
  301. }
  302. return [results copy];
  303. }
  304. + (IAPReceiptInfoModel *)fetchProductLastestReceiptsWithModel:(IAPReceiptModel *)model withProductId:(NSString *)productId {
  305. IAPReceiptInfoModel *flagM= nil;
  306. long long lastestExpiresDate = 0;
  307. for (IAPReceiptInfoModel *m in [self fetchProductReceiptsWithModel:model withProductId:productId]) {
  308. long long theExpiresDate = [m.expires_date_ms longLongValue]/1000;
  309. if (theExpiresDate > lastestExpiresDate) {
  310. lastestExpiresDate = theExpiresDate;
  311. flagM = m;
  312. }
  313. }
  314. return flagM;
  315. }
  316. + (NSArray<IAPReceiptInfoModel *> *)fetchProductReceiptsWithModel:(IAPReceiptModel *)model withProductId:(NSString *)productId {
  317. NSMutableArray *results = [NSMutableArray arrayWithCapacity:4];
  318. for (IAPReceiptInfoModel *m in [self fetchReceiptsWithModel:model]) {
  319. if ([m.product_id isEqualToString:productId] == false) {
  320. continue;
  321. }
  322. [results addObject:m];
  323. }
  324. return [results copy];
  325. }
  326. + (NSArray<IAPReceiptInfoModel *> *)fetchReceiptsWithModel:(IAPReceiptModel *)model {
  327. NSMutableArray *results = [NSMutableArray arrayWithCapacity:4];
  328. for (IAPReceiptInfoModel *m in model.latestReceiptInfoModels) {
  329. [results addObject:m];
  330. }
  331. for (IAPReceiptInfoModel *m in model.receiptModel.inAppModels) {
  332. [results addObject:m];
  333. }
  334. return [results copy];
  335. }
  336. @end