VerificationManager.m 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210
  1. //
  2. // VerificationManager.m
  3. // Filmage Screen
  4. //
  5. // Created by 朱东勇 on 2018/2/8.
  6. // Copyright © 2018年 kdan mobile. All rights reserved.
  7. //
  8. #import "VerificationManager.h"
  9. #import "NSNULL+Filtration.h"
  10. #import "NSObject+DeviceInfo.h"
  11. #import "JSONKit.h"
  12. #import "ASIFormDataRequest.h"
  13. const NSString *kDeviceVerifyFinishNotification = @"kDeviceVerifyFinishNotification";
  14. const NSString *kDeviceActivateStatusChangeNotification = @"kDeviceActivateNotification";
  15. static VerificationManager *__verificationManager = nil;
  16. @interface VerificationManager ()
  17. @property (nonatomic, strong) NSTimer *timer;
  18. @property (nonatomic) BOOL isVerifing;
  19. @end
  20. @implementation VerificationManager
  21. + (VerificationManager*)manager {
  22. #if VERSION_DMG
  23. if (!__verificationManager)
  24. __verificationManager = [[VerificationManager alloc] init];
  25. #else
  26. return nil;
  27. #endif
  28. return __verificationManager;
  29. }
  30. + (VerificationManager*)defaultManager {
  31. #if VERSION_DMG
  32. if (!__verificationManager)
  33. __verificationManager = [[VerificationManager alloc] init];
  34. #else
  35. return nil;
  36. #endif
  37. return __verificationManager;
  38. }
  39. - (instancetype)init {
  40. self = [super init];
  41. self.autoVerification = YES;
  42. #if !DEBUG // 非测试环境时
  43. #if kTestMode // 测试模式时 报错
  44. //#error 服务器未切换到正式服务器!
  45. #endif
  46. #endif
  47. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  48. [self verificationWithComplention:^(ActivityStatus status, NSDictionary *info, NSError *error) {
  49. }];
  50. });
  51. return self;
  52. }
  53. #pragma mark - Setter & Getter
  54. - (ActivityStatus)status {
  55. // if (self.detailInfo.status == ActivityStatusNone) {
  56. // return ActivityStatusTrialExpire;
  57. // }
  58. return self.detailInfo.status;
  59. }
  60. - (BOOL)needUpgradeLicense {
  61. if ([self.detailInfo[@"device"][@"product_code"] isEqualToString:@"com.brother.pdfreaderpro.mac.product_1"] ||
  62. [self.detailInfo[@"device"][@"product_code"] isEqualToString:@"com.brother.pdfreaderpro.cross.platform.product_1"]) {
  63. return YES;
  64. }
  65. // if ([self.detailInfo[@"subscription"][@"product"][@"code"] isEqualToString:@"com.brother.pdfreaderpro.mac.product_1"]) {
  66. // return YES;
  67. // }
  68. return NO;
  69. }
  70. - (BOOL)secondTrialEnabled {
  71. return self.detailInfo.repeatTrial;
  72. }
  73. - (NSInteger)trialTimes {
  74. return self.detailInfo.trialTimes;
  75. }
  76. - (NSString *)licenseCode {
  77. return self.detailInfo.licenseCode;
  78. }
  79. - (NSString *)originLicenseCode {
  80. return self.detailInfo.originLicenseCode;
  81. }
  82. - (NSString *)email {
  83. return self.detailInfo.email?:@"";
  84. }
  85. - (NSString *)subscriptionEmail {
  86. return self.detailInfo.subscriptionEmail?:@"";
  87. }
  88. - (NSString *)accountName {
  89. return self.detailInfo.accountName;
  90. }
  91. - (BOOL)allowUnbind {
  92. return self.detailInfo.allowUnbind;
  93. }
  94. - (NSInteger)unbindTimes {
  95. return self.detailInfo.unbindTimes;
  96. }
  97. - (NSString*)udid {
  98. //#if DEBUG
  99. // NSString *cachePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"uuid.plist"];
  100. // NSMutableDictionary *info = [[NSDictionary dictionaryWithContentsOfFile:cachePath] mutableCopy];
  101. //
  102. // if (!info) {
  103. // info = [NSMutableDictionary dictionary];
  104. //
  105. // [info setValue:[NSString stringWithFormat:@"TestInvate%.0f", [NSDate date].timeIntervalSince1970]
  106. // forKey:@"uuid"];
  107. //
  108. //
  109. // [[NSFileManager defaultManager] createDirectoryAtPath:NSTemporaryDirectory()
  110. // withIntermediateDirectories:YES
  111. // attributes:nil
  112. // error:nil];
  113. // [info writeToFile:cachePath atomically:YES];
  114. // }
  115. //
  116. // return info[@"uuid"]?:(GetHardwareUUID()?:@"");
  117. //#endif
  118. return GetHardwareUUID()?:@"";
  119. }
  120. - (NSString *)bundleIdentify {
  121. return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]?:@"";
  122. }
  123. - (void)setDetailInfo:(NSDictionary *)detailInfo {
  124. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  125. [defaults setValue:[detailInfo JSONData]
  126. forKey:@"detailInfo"];
  127. [defaults synchronize];
  128. }
  129. - (NSDictionary*)detailInfo {
  130. NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
  131. return [[[defaults valueForKey:@"detailInfo"] objectFromJSONData] filterNullObject];
  132. }
  133. //
  134. //- (void)setIsTest:(BOOL)isTest {
  135. // _isTest = isTest;
  136. //
  137. // [self verificationWithComplention:^(ActivityStatus status, NSDictionary *info, NSError *error) {
  138. //
  139. // }];
  140. //}
  141. - (void)setAutoVerification:(BOOL)autoVerification {
  142. _autoVerification = autoVerification;
  143. [self restartTimer];
  144. }
  145. - (BOOL)isVerificationCode {
  146. if (self.detailInfo.status == ActivityStatusVerification) {
  147. return YES;
  148. }
  149. return NO;
  150. }
  151. - (BOOL)showTrialGuide {
  152. if (self.detailInfo.status == ActivityStatusNone ||
  153. self.detailInfo.status == ActivityStatusTrial) {
  154. return YES;
  155. }
  156. return NO;
  157. }
  158. #pragma mark - Timer
  159. - (void)restartTimer {
  160. if (self.timer)
  161. [self.timer invalidate];
  162. self.timer = nil;
  163. if (self.autoVerification &&
  164. self.status != ActivityStatusNone) {
  165. self.timer = [NSTimer scheduledTimerWithTimeInterval:60 * 60//一个小时更新一次
  166. target:self
  167. selector:@selector(verificationFire)
  168. userInfo:nil
  169. repeats:NO];
  170. }
  171. }
  172. - (void)verificationFire {
  173. [self verificationWithComplention:^(ActivityStatus status, NSDictionary *info, NSError *error) {
  174. }];
  175. }
  176. #pragma mark - Interface
  177. - (void)activateDeviceWithInfo:(NSDictionary*)info
  178. complention:(ActivityComplention)complention {
  179. if (![info[@"cdkey"] length]) {
  180. //激活码为空
  181. NSError *error = [NSError errorWithDomain:@""
  182. code:ActivityErrorTypeCDKeyEmpty
  183. userInfo:nil];
  184. if (complention)
  185. complention(NO, nil, error);
  186. return;
  187. }
  188. if (![self isValidLicenseCode:info[@"cdkey"]]) {
  189. //激活码格式不正确
  190. NSError *error = [NSError errorWithDomain:@"激活失败"
  191. code:ActivityErrorTypeFormatError
  192. userInfo:nil];
  193. if (complention)
  194. complention(NO, @{@"errors":@"FormatError"}, error);
  195. return;
  196. }
  197. __block ActivityComplention tComplention = complention;
  198. __block VerificationManager *weak_self = self;
  199. //Process Params
  200. NSString *app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] description];
  201. if (!app_version.length)
  202. app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] description];
  203. NSDictionary *params =
  204. @{
  205. @"data":@{
  206. //激活信息
  207. @"subscription":@{
  208. // @"app_code":[self bundleIdentify]?:@"",
  209. @"app_code":@"com.brother.pdftecheditor",
  210. @"email":info[@"email"]?:@"",
  211. @"cdkey":info[@"cdkey"]?:@"",
  212. },
  213. //设备信息
  214. @"device":@{
  215. @"unique_sn":[self udid]?:@"",
  216. @"model":GetProductName()?:@"",
  217. @"os":GetSystemVersion()?:@"",
  218. @"time_zone":[[NSTimeZone localTimeZone] localizedName:NSTimeZoneNameStyleShortDaylightSaving locale:[NSLocale currentLocale]]?:@"",
  219. @"language":[[NSLocale currentLocale] localeIdentifier]?:@"",
  220. @"app_version":app_version?:@"",
  221. @"platform":@"DMG"
  222. }
  223. }
  224. };
  225. NSMutableData *postData = [VerificationManager mutableDataWithDic:params];
  226. //Send Request
  227. NSString *urlString = [kVerificationServer stringByAppendingString:@"api/auth_devices/activate"];
  228. NSURL *url = [NSURL URLWithString:urlString];
  229. ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
  230. request.requestMethod = @"POST";
  231. [request setPostBody:postData];
  232. NSString *postLength = [NSString stringWithFormat:@"%ld", (unsigned long)[postData length]];
  233. NSMutableDictionary *requestHeaders = [NSMutableDictionary dictionaryWithObjectsAndKeys:
  234. postLength, @"Content-Length", nil];
  235. request.defaultResponseEncoding = NSUTF8StringEncoding;
  236. // [request setAuthenticationScheme:@"https"];//设置验证方式
  237. // [request setValidatesSecureCertificate:NO];//设置验证证书
  238. [request setRequestHeaders:requestHeaders];
  239. [request addRequestHeader:@"Content-Type" value:@"application/json"];
  240. [request addRequestHeader:@"Accept" value:@"application/vnd.api+json;version=1"];
  241. __block void(^processRequest)(void) = ^{
  242. dispatch_async(dispatch_get_main_queue(), ^{
  243. NSDictionary *info = [[request.responseString objectFromJSONString] filterNullObject];
  244. NSError *error = request.error;
  245. if (info && [info isKindOfClass:[NSDictionary class]]) {
  246. if ([info valueForKey:@"errors"]) {
  247. NSString *detailKey = [[info[@"errors"] firstObject] valueForKey:@"detail_key"];
  248. if ([detailKey isEqualToString:@"exceed_max_device_num"]) {
  249. error = [NSError errorWithDomain:@"激活失败"
  250. code:ActivityErrorTypeOutNumber
  251. userInfo:info];
  252. }else if ([detailKey isEqualToString:@"invalid_activate_info"]) {
  253. error = [NSError errorWithDomain:@"激活失败"
  254. code:ActivityErrorTypeInvalidInfo
  255. userInfo:info];
  256. }else if ([detailKey isEqualToString:@"invalid_license_key"]) {
  257. error = [NSError errorWithDomain:@"激活失败"
  258. code:ActivityErrorTypeCDKeyNotExist
  259. userInfo:info];
  260. }else if ([detailKey isEqualToString:@"license_not_match_product"]) {
  261. error = [NSError errorWithDomain:@"激活失败"
  262. code:ActivityErrorTypeNotMatchProduct
  263. userInfo:info];
  264. }else if ([detailKey isEqualToString:@"license_expired"]) {
  265. error = [NSError errorWithDomain:@"激活失败"
  266. code:ActivityErrorTypeCDKeyExpire
  267. userInfo:info];
  268. }else {
  269. error = [NSError errorWithDomain:@"激活失败"
  270. code:ActivityErrorTypeUnknow
  271. userInfo:info];
  272. }
  273. }else if ([info valueForKey:@"error"]) {
  274. error = [NSError errorWithDomain:@"激活失败"
  275. code:ActivityErrorTypeUnknow
  276. userInfo:info];
  277. }
  278. }else {
  279. if(error) {
  280. error = [NSError errorWithDomain:error.domain code:ActivityErrorTypeNetworkDisable userInfo:error.userInfo];
  281. } else {
  282. error = [NSError errorWithDomain:@"激活失败"
  283. code:ActivityErrorTypeUnknow
  284. userInfo:@{}];
  285. }
  286. }
  287. if (!error) {
  288. NSMutableDictionary *dic = [weak_self.detailInfo?:@{} mutableCopy];
  289. for (NSString *key in info[@"data"]) {
  290. [dic setValue:info[@"data"][key] forKey:key];
  291. }
  292. weak_self.detailInfo = dic;
  293. NSString *notificationName = (NSString *)kDeviceActivateStatusChangeNotification;
  294. [[NSNotificationCenter defaultCenter] postNotificationName:notificationName
  295. object:self
  296. userInfo:info];
  297. [weak_self verificationWithComplention:^(ActivityStatus status, NSDictionary *info, NSError *error) {
  298. }];
  299. }
  300. [weak_self restartTimer];
  301. [weak_self verificationWithComplention:^(ActivityStatus status, NSDictionary *info, NSError *error) {
  302. }];
  303. if (tComplention)
  304. tComplention(weak_self.status, info, error);
  305. });
  306. };
  307. [request setFailedBlock:^{
  308. processRequest();
  309. }];
  310. [request setCompletionBlock:^{
  311. processRequest();
  312. }];
  313. [request startAsynchronous];
  314. }
  315. - (void)verificationWithComplention:(ActivityComplention)complention {
  316. __block ActivityComplention tComplention = complention;
  317. __block VerificationManager *weak_self = self;
  318. if (!self.isVerifing) {
  319. self.isVerifing = YES;
  320. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  321. //Process Params
  322. NSString *app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] description];
  323. if (!app_version.length)
  324. app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] description];
  325. NSString *platform = @"DMG";
  326. #if VERSION_FREE
  327. #if VERSION_DMG
  328. #else
  329. platform = @"AppleStore";
  330. #endif
  331. #else
  332. platform = @"AppleStorePro";
  333. #endif
  334. NSDictionary *params =
  335. @{
  336. @"data":@{
  337. //验证信息
  338. @"subscription":@{
  339. // @"app_code":[self bundleIdentify]?:@"",
  340. @"app_code":@"com.brother.pdftecheditor",
  341. // @"email":info[@"email"]?:@"",
  342. // @"cdkey":info[@"cdkey"]?:@"",
  343. },
  344. //设备信息
  345. @"device":@{
  346. @"unique_sn":[self udid]?:@"",
  347. @"model":GetProductName()?:@"",
  348. @"os":GetSystemVersion()?:@"",
  349. @"time_zone":[[NSTimeZone localTimeZone] localizedName:NSTimeZoneNameStyleShortDaylightSaving locale:[NSLocale currentLocale]]?:@"",
  350. @"language":[[NSLocale currentLocale] localeIdentifier]?:@"",
  351. @"app_version":app_version?:@"",
  352. @"platform":platform?:@"AppleStore"
  353. }
  354. }
  355. };
  356. NSMutableData *postData = [VerificationManager mutableDataWithDic:params];
  357. //Send Request
  358. NSString *urlString = [kVerificationServer stringByAppendingString:@"api/auth_devices/verify"];
  359. NSURL *url = [NSURL URLWithString:urlString];
  360. ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
  361. request.requestMethod = @"POST";
  362. [request setPostBody:postData];
  363. NSString *postLength = [NSString stringWithFormat:@"%ld", (unsigned long)[postData length]];
  364. NSMutableDictionary *requestHeaders = [NSMutableDictionary dictionaryWithObjectsAndKeys:
  365. postLength, @"Content-Length", nil];
  366. // [request setAuthenticationScheme:@"https"];//设置验证方式
  367. // [request setValidatesSecureCertificate:NO];//设置验证证书
  368. [request setRequestHeaders:requestHeaders];
  369. [request addRequestHeader:@"Content-Type" value:@"application/json"];
  370. [request addRequestHeader:@"Accept" value:@"application/vnd.api+json;version=1"];
  371. __block void(^processRequest)(void) = ^{
  372. dispatch_async(dispatch_get_main_queue(), ^{
  373. NSDictionary *info = [[request.responseString objectFromJSONString] filterNullObject];
  374. ActivityStatus status = weak_self.status;
  375. if ([info valueForKey:@"data"] &&
  376. [[info valueForKey:@"data"] valueForKey:@"device"]) {
  377. ActivityStatus tStatus = [(NSDictionary*)info[@"data"] status];
  378. //存储信息,并发送更新通知
  379. weak_self.detailInfo = info[@"data"];
  380. // if (status != tStatus ||
  381. // [[info valueForKey:@"data"] valueForKey:@"invite"]) {
  382. //发送通知
  383. NSString *notificationName = (NSString *)kDeviceActivateStatusChangeNotification;
  384. [[NSNotificationCenter defaultCenter] postNotificationName:notificationName
  385. object:weak_self
  386. userInfo:info];
  387. // }
  388. }
  389. [[NSNotificationCenter defaultCenter] postNotificationName:(NSString *)kDeviceVerifyFinishNotification
  390. object:nil
  391. userInfo:nil];
  392. weak_self.isVerifing = NO;
  393. //重置计时器
  394. [weak_self restartTimer];
  395. if (tComplention)
  396. tComplention(weak_self.status, info, request.error);
  397. });
  398. };
  399. [request setFailedBlock:^{
  400. processRequest();
  401. }];
  402. [request setCompletionBlock:^{
  403. processRequest();
  404. }];
  405. [request startAsynchronous];
  406. });
  407. }else {
  408. __block void(^waitBlock)(void) = ^{
  409. if (weak_self.isVerifing) {
  410. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  411. waitBlock();
  412. });
  413. }else {
  414. if (tComplention)
  415. tComplention(weak_self.status, @{@"data":weak_self.detailInfo?:@{}}, nil);
  416. waitBlock = NULL;
  417. }
  418. };
  419. waitBlock();
  420. }
  421. }
  422. - (void)trialForDays:(float)days
  423. complention:(ActivityComplention)complention {
  424. [self trialForDays:days email:nil name:nil complention:complention];
  425. }
  426. - (void)trialForDays:(float)days
  427. email:(NSString*)email
  428. name:(NSString*)name
  429. complention:(ActivityComplention)complention {
  430. __block ActivityComplention tComplention = complention;
  431. __block VerificationManager *weak_self = self;
  432. //Process Params
  433. NSString *app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] description];
  434. if (!app_version.length)
  435. app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] description];
  436. NSDictionary *params =
  437. @{
  438. @"data":@{
  439. //激活信息
  440. @"subscription":@{
  441. // @"app_code":[self bundleIdentify]?:@"",
  442. @"app_code":@"com.brother.pdftecheditor",
  443. @"trail_days":@(MAX(days, 1)),
  444. @"email":email?:@"",
  445. @"contact_name":name?:@""
  446. },
  447. //设备信息
  448. @"device":@{
  449. @"unique_sn":[self udid]?:@"",
  450. @"model":GetProductName()?:@"",
  451. @"os":GetSystemVersion()?:@"",
  452. @"time_zone":[[NSTimeZone localTimeZone] localizedName:NSTimeZoneNameStyleShortDaylightSaving locale:[NSLocale currentLocale]]?:@"",
  453. @"language":[[NSLocale currentLocale] localeIdentifier]?:@"",
  454. @"app_version":app_version?:@""
  455. }
  456. }
  457. };
  458. NSMutableData *postData = [VerificationManager mutableDataWithDic:params];
  459. //Send Request
  460. NSString *urlString = [kVerificationServer stringByAppendingString:@"api/auth_devices/trial"];
  461. NSURL *url = [NSURL URLWithString:urlString];
  462. ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
  463. request.requestMethod = @"POST";
  464. [request setPostBody:postData];
  465. NSString *postLength = [NSString stringWithFormat:@"%ld", (unsigned long)[postData length]];
  466. NSMutableDictionary *requestHeaders = [NSMutableDictionary dictionaryWithObjectsAndKeys:
  467. postLength, @"Content-Length", nil];
  468. request.defaultResponseEncoding = NSUTF8StringEncoding;
  469. // [request setAuthenticationScheme:@"https"];//设置验证方式
  470. // [request setValidatesSecureCertificate:NO];//设置验证证书
  471. [request setRequestHeaders:requestHeaders];
  472. [request addRequestHeader:@"Content-Type" value:@"application/json"];
  473. [request addRequestHeader:@"Accept" value:@"application/vnd.api+json;version=1"];
  474. __block void(^processRequest)(void) = ^{
  475. dispatch_async(dispatch_get_main_queue(), ^{
  476. NSDictionary *info = [[request.responseString objectFromJSONString] filterNullObject];
  477. ActivityStatus status = weak_self.status;
  478. if ([info valueForKey:@"data"] &&
  479. [[info valueForKey:@"data"] valueForKey:@"device"]) {
  480. ActivityStatus tStatus = [(NSDictionary*)info[@"data"] status];
  481. //存储信息,并发送更新通知
  482. NSMutableDictionary *dic = [weak_self.detailInfo?:@{} mutableCopy];
  483. for (NSString *key in info[@"data"]) {
  484. [dic setValue:info[@"data"][key] forKey:key];
  485. }
  486. weak_self.detailInfo = dic;
  487. if (status != tStatus) {
  488. //发送通知
  489. NSString *notificationName = (NSString *)kDeviceActivateStatusChangeNotification;
  490. [[NSNotificationCenter defaultCenter] postNotificationName:notificationName
  491. object:self
  492. userInfo:info];
  493. }
  494. }
  495. //重置计时器
  496. [weak_self restartTimer];
  497. if (tComplention)
  498. tComplention(weak_self.status, info, request.error);
  499. });
  500. };
  501. [request setFailedBlock:^{
  502. processRequest();
  503. }];
  504. [request setCompletionBlock:^{
  505. processRequest();
  506. }];
  507. [request startAsynchronous];
  508. }
  509. - (void)getCodeWithEmail:(NSString*)email
  510. complention:(ActivityComplention)complention {
  511. __block ActivityComplention tComplention = complention;
  512. __block VerificationManager *weak_self = self;
  513. //Process Params
  514. NSString *app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] description];
  515. if (!app_version.length)
  516. app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] description];
  517. NSString *platform = @"DMG";
  518. #ifdef AppStore_Version
  519. #if Lite_Version
  520. platform = @"AppleStore";
  521. #else
  522. platform = @"AppleStorePro";
  523. #endif
  524. #endif
  525. NSDictionary *params =
  526. @{
  527. @"data":@{
  528. // @"app_code":[self bundleIdentify]?:@"",
  529. @"app_code":@"com.brother.pdftecheditor",
  530. @"email":email?:@"",
  531. @"unique_sn":[self udid]?:@"",
  532. @"platform":platform?:@"AppleStore"
  533. }
  534. };
  535. NSMutableData *postData = [VerificationManager mutableDataWithDic:params];
  536. //Send Request
  537. NSString *urlString = [kVerificationServer stringByAppendingString:@"api/invites/getCode"];
  538. NSURL *url = [NSURL URLWithString:urlString];
  539. ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
  540. request.requestMethod = @"POST";
  541. [request setPostBody:postData];
  542. NSString *postLength = [NSString stringWithFormat:@"%ld", (unsigned long)[postData length]];
  543. NSMutableDictionary *requestHeaders = [NSMutableDictionary dictionaryWithObjectsAndKeys:
  544. postLength, @"Content-Length", nil];
  545. request.defaultResponseEncoding = NSUTF8StringEncoding;
  546. // [request setAuthenticationScheme:@"https"];//设置验证方式
  547. // [request setValidatesSecureCertificate:NO];//设置验证证书
  548. [request setRequestHeaders:requestHeaders];
  549. [request addRequestHeader:@"Content-Type" value:@"application/json"];
  550. [request addRequestHeader:@"Accept" value:@"application/vnd.api+json;version=1"];
  551. __block void(^processRequest)(void) = ^{
  552. dispatch_async(dispatch_get_main_queue(), ^{
  553. NSDictionary *info = [[request.responseString objectFromJSONString] filterNullObject];
  554. if ([info valueForKey:@"data"] &&
  555. [[info valueForKey:@"data"] valueForKey:@"email"] &&
  556. [[info valueForKey:@"data"] valueForKey:@"share_code"]) {
  557. //存储信息,并发送更新通知
  558. NSMutableDictionary *dic = [weak_self.detailInfo?:@{} mutableCopy];
  559. [dic setValue:info[@"data"] forKey:@"invite"];
  560. weak_self.detailInfo = dic;
  561. [weak_self verificationWithComplention:^(ActivityStatus status, NSDictionary *info, NSError *error) {
  562. }];
  563. }
  564. //重置计时器
  565. [weak_self restartTimer];
  566. if (tComplention)
  567. tComplention(weak_self.status, info, request.error);
  568. });
  569. };
  570. [request setFailedBlock:^{
  571. processRequest();
  572. }];
  573. [request setCompletionBlock:^{
  574. processRequest();
  575. }];
  576. [request startAsynchronous];
  577. }
  578. //使用邀请码
  579. - (void)userCode:(NSString*)code
  580. complention:(ActivityComplention)complention {
  581. __block ActivityComplention tComplention = complention;
  582. __block VerificationManager *weak_self = self;
  583. //Process Params
  584. NSString *app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] description];
  585. if (!app_version.length)
  586. app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] description];
  587. BOOL iszhcn = !([NSLocalizedString(@"Language", nil) isEqualToString:@"English"] &&
  588. [NSLocalizedString(@"Language", nil) isEqualToString:@"Français"]);
  589. NSString *platform = @"DMG";
  590. #ifdef AppStore_Version
  591. #if Lite_Version
  592. platform = @"AppleStore";
  593. #else
  594. platform = @"AppleStorePro";
  595. #endif
  596. #endif
  597. NSDictionary *params =
  598. @{
  599. @"data":@{
  600. // @"app_code":[self bundleIdentify]?:@"",
  601. @"app_code":@"com.brother.pdftecheditor",
  602. @"code":code?:@"",
  603. @"unique_sn":[self udid]?:@"",
  604. @"lang":@(iszhcn),
  605. @"platform":platform?:@"AppleStore"
  606. }
  607. };
  608. NSMutableData *postData = [VerificationManager mutableDataWithDic:params];
  609. //Send Request
  610. NSString *urlString = [kVerificationServer stringByAppendingString:@"api/invites/activeInvite"];
  611. NSURL *url = [NSURL URLWithString:urlString];
  612. ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
  613. request.requestMethod = @"POST";
  614. [request setPostBody:postData];
  615. NSString *postLength = [NSString stringWithFormat:@"%ld", (unsigned long)[postData length]];
  616. NSMutableDictionary *requestHeaders = [NSMutableDictionary dictionaryWithObjectsAndKeys:
  617. postLength, @"Content-Length", nil];
  618. request.defaultResponseEncoding = NSUTF8StringEncoding;
  619. // [request setAuthenticationScheme:@"https"];//设置验证方式
  620. // [request setValidatesSecureCertificate:NO];//设置验证证书
  621. [request setRequestHeaders:requestHeaders];
  622. [request addRequestHeader:@"Content-Type" value:@"application/json"];
  623. [request addRequestHeader:@"Accept" value:@"application/vnd.api+json;version=1"];
  624. __block void(^processRequest)(void) = ^{
  625. dispatch_async(dispatch_get_main_queue(), ^{
  626. NSDictionary *info = [[request.responseString objectFromJSONString] filterNullObject];
  627. ActivityStatus status = weak_self.status;
  628. if ([info valueForKey:@"data"] &&
  629. [[info valueForKey:@"data"] valueForKey:@"device"]) {
  630. ActivityStatus tStatus = [(NSDictionary*)info[@"data"] status];
  631. weak_self.detailInfo = info[@"data"];
  632. if (status != tStatus) {
  633. //发送通知
  634. NSString *notificationName = (NSString *)kDeviceActivateStatusChangeNotification;
  635. [[NSNotificationCenter defaultCenter] postNotificationName:notificationName
  636. object:self
  637. userInfo:info];
  638. }
  639. [weak_self verificationWithComplention:^(ActivityStatus status, NSDictionary *info, NSError *error) {
  640. }];
  641. }
  642. //重置计时器
  643. [weak_self restartTimer];
  644. if (tComplention)
  645. tComplention(weak_self.status, info, request.error);
  646. });
  647. };
  648. [request setFailedBlock:^{
  649. processRequest();
  650. }];
  651. [request setCompletionBlock:^{
  652. processRequest();
  653. }];
  654. [request startAsynchronous];
  655. }
  656. - (void)modifyEmail:(NSString*)email
  657. complention:(ActivityComplention)complention {
  658. __block ActivityComplention tComplention = complention;
  659. __block VerificationManager *weak_self = self;
  660. //Process Params
  661. NSString *app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] description];
  662. if (!app_version.length)
  663. app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] description];
  664. BOOL iszhcn = !([NSLocalizedString(@"Language", nil) isEqualToString:@"English"] &&
  665. [NSLocalizedString(@"Language", nil) isEqualToString:@"Français"]);
  666. NSDictionary *params =
  667. @{
  668. @"data":@{
  669. // @"app_code":[self bundleIdentify]?:@"",
  670. @"app_code":@"com.brother.pdftecheditor",
  671. @"email":email?:@"",
  672. @"unique_sn":[self udid]?:@"",
  673. @"lang":@(iszhcn),
  674. }
  675. };
  676. NSMutableData *postData = [VerificationManager mutableDataWithDic:params];
  677. //Send Request
  678. NSString *urlString = [kVerificationServer stringByAppendingString:@"api/invites/updateEmail"];
  679. NSURL *url = [NSURL URLWithString:urlString];
  680. ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
  681. request.requestMethod = @"POST";
  682. [request setPostBody:postData];
  683. NSString *postLength = [NSString stringWithFormat:@"%ld", (unsigned long)[postData length]];
  684. NSMutableDictionary *requestHeaders = [NSMutableDictionary dictionaryWithObjectsAndKeys:
  685. postLength, @"Content-Length", nil];
  686. request.defaultResponseEncoding = NSUTF8StringEncoding;
  687. // [request setAuthenticationScheme:@"https"];//设置验证方式
  688. // [request setValidatesSecureCertificate:NO];//设置验证证书
  689. [request setRequestHeaders:requestHeaders];
  690. [request addRequestHeader:@"Content-Type" value:@"application/json"];
  691. [request addRequestHeader:@"Accept" value:@"application/vnd.api+json;version=1"];
  692. __block void(^processRequest)(void) = ^{
  693. dispatch_async(dispatch_get_main_queue(), ^{
  694. NSDictionary *info = [[request.responseString objectFromJSONString] filterNullObject];
  695. if ([info valueForKey:@"data"] &&
  696. [[info valueForKey:@"data"] valueForKey:@"email"] &&
  697. [[info valueForKey:@"data"] valueForKey:@"share_code"]) {
  698. //存储信息,并发送更新通知
  699. NSMutableDictionary *dic = [weak_self.detailInfo?:@{} mutableCopy];
  700. [dic setValue:info[@"data"] forKey:@"invite"];
  701. weak_self.detailInfo = dic;
  702. [weak_self verificationWithComplention:^(ActivityStatus status, NSDictionary *info, NSError *error) {
  703. }];
  704. }
  705. //重置计时器
  706. [weak_self restartTimer];
  707. if (tComplention)
  708. tComplention(weak_self.status, info, request.error);
  709. });
  710. };
  711. [request setFailedBlock:^{
  712. processRequest();
  713. }];
  714. [request setCompletionBlock:^{
  715. processRequest();
  716. }];
  717. [request startAsynchronous];
  718. }
  719. //给好友发送邀请码
  720. - (void)sendInvateEmails:(NSString*)emails
  721. code:(NSString*)code
  722. complention:(ActivityComplention)complention {
  723. __block ActivityComplention tComplention = complention;
  724. __block VerificationManager *weak_self = self;
  725. //Process Params
  726. NSString *app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] description];
  727. if (!app_version.length)
  728. app_version = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"] description];
  729. BOOL iszhcn = !([NSLocalizedString(@"Language", nil) isEqualToString:@"English"] &&
  730. [NSLocalizedString(@"Language", nil) isEqualToString:@"Français"]);
  731. NSDictionary *params =
  732. @{
  733. @"data":@{
  734. // @"app_code":[self bundleIdentify]?:@"",
  735. @"app_code":@"com.brother.pdftecheditor",
  736. @"email":emails?:@"",
  737. @"code":[code stringByReplacingOccurrencesOfString:@" " withString:@""]?:@"",
  738. @"unique_sn":[self udid]?:@"",
  739. @"lang":@(iszhcn),
  740. }
  741. };
  742. NSMutableData *postData = [VerificationManager mutableDataWithDic:params];
  743. //Send Request
  744. NSString *urlString = [kVerificationServer stringByAppendingString:@"api/invites/shareEmail"];
  745. NSURL *url = [NSURL URLWithString:urlString];
  746. ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
  747. request.requestMethod = @"POST";
  748. [request setPostBody:postData];
  749. NSString *postLength = [NSString stringWithFormat:@"%ld", (unsigned long)[postData length]];
  750. NSMutableDictionary *requestHeaders = [NSMutableDictionary dictionaryWithObjectsAndKeys:
  751. postLength, @"Content-Length", nil];
  752. request.defaultResponseEncoding = NSUTF8StringEncoding;
  753. // [request setAuthenticationScheme:@"https"];//设置验证方式
  754. // [request setValidatesSecureCertificate:NO];//设置验证证书
  755. [request setRequestHeaders:requestHeaders];
  756. [request addRequestHeader:@"Content-Type" value:@"application/json"];
  757. [request addRequestHeader:@"Accept" value:@"application/vnd.api+json;version=1"];
  758. __block void(^processRequest)(void) = ^{
  759. dispatch_async(dispatch_get_main_queue(), ^{
  760. NSDictionary *info = [[request.responseString objectFromJSONString] filterNullObject];
  761. //重置计时器
  762. [weak_self restartTimer];
  763. if (tComplention)
  764. tComplention(weak_self.status, info, request.error);
  765. [weak_self verificationWithComplention:^(ActivityStatus status, NSDictionary *info, NSError *error) {
  766. }];
  767. });
  768. };
  769. [request setFailedBlock:^{
  770. processRequest();
  771. }];
  772. [request setCompletionBlock:^{
  773. processRequest();
  774. }];
  775. [request startAsynchronous];
  776. }
  777. #pragma mark - Data Formatter
  778. - (BOOL)isValidLicenseCode:(NSString *)cdKey {
  779. NSString *validKey = [cdKey stringByReplacingOccurrencesOfString:@" " withString:@""];
  780. if (validKey.length != 19) {
  781. return NO;
  782. }
  783. //计算字符串长度
  784. NSInteger str_length = [validKey length];
  785. NSString *regex = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-";
  786. for (int i = 0; i<str_length; i++) {
  787. NSString *subStr = [validKey substringWithRange:NSMakeRange(i, 1)];
  788. if([regex rangeOfString:subStr].location == NSNotFound) {
  789. return NO;
  790. }
  791. }
  792. return YES;
  793. }
  794. + (NSString*)postStringWithObject:(id)value {
  795. NSString *string;
  796. if ([value isKindOfClass:[NSArray class]]) {
  797. string = @"[";
  798. BOOL isFirst = YES;
  799. for (id object in value) {
  800. if (isFirst) {
  801. isFirst = NO;
  802. }else {
  803. string = [string stringByAppendingString:@","];
  804. }
  805. string = [string stringByAppendingString:[VerificationManager postStringWithObject:object]];
  806. }
  807. string = [string stringByAppendingString:@"]"];
  808. }else if ([value isKindOfClass:[NSDictionary class]]) {
  809. string = @"{";
  810. BOOL isFirst = YES;
  811. for (NSString *key in [value allKeys]) {
  812. if (isFirst) {
  813. isFirst = NO;
  814. }else {
  815. string = [string stringByAppendingString:@","];
  816. }
  817. string = [string stringByAppendingFormat:@"\"%@\"", key];
  818. string = [string stringByAppendingString:@":"];
  819. string = [string stringByAppendingString:[VerificationManager postStringWithObject:[value valueForKey:key]]];
  820. }
  821. string = [string stringByAppendingString:@"}"];
  822. }else {
  823. string = [NSString stringWithFormat:@"\"%@\"", value];
  824. }
  825. return string;
  826. }
  827. + (NSString*)postStringWithDic:(NSDictionary*)dic {
  828. return [VerificationManager postStringWithObject:dic];
  829. }
  830. + (NSMutableData*)mutableDataWithDic:(NSDictionary*)dic {
  831. NSString *json = [VerificationManager postStringWithDic:dic];
  832. json = [json stringByReplacingOccurrencesOfString:@"\n" withString:@""];
  833. json = [json stringByReplacingOccurrencesOfString:@"\r\0" withString:@""];
  834. json = [json stringByReplacingOccurrencesOfString:@"\0" withString:@""];
  835. NSData *postData = [json dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
  836. return [postData mutableCopy];
  837. }
  838. @end
  839. #pragma mark - Test
  840. #if DEBUG
  841. @implementation VerificationManager (Test)
  842. //- (ActivityStatus)status {
  843. // return ActivityStatusVerification;
  844. //}
  845. - (void)updateVerificationStatus {
  846. [self updateStatus:ActivityStatusVerification postNo:true];
  847. }
  848. - (void)updateStatus:(ActivityStatus)status postNo:(bool)postNo {
  849. NSString *subValue = @"";
  850. NSString *deviceValue = @"";
  851. NSTimeInterval endTime = 0;
  852. if (status == ActivityStatusNone) {
  853. deviceValue = @"";
  854. } else if (status == ActivityStatusTrial) {
  855. deviceValue = @"on_trial";
  856. } else if (status == ActivityStatusTrialExpire) {
  857. deviceValue = @"expired_trial";
  858. } else if (status == ActivityStatusVerification) {
  859. deviceValue = @"activated";
  860. endTime = [NSDate date].timeIntervalSince1970 + 60 * 60;
  861. } else if (status == ActivityStatusVerifExpire) {
  862. deviceValue = @"expired_license";
  863. } else if (status == ActivityStatusLicenseExpire) {
  864. deviceValue = @"";
  865. subValue = @"expired";
  866. }
  867. NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:self.detailInfo];
  868. dict[@"subscription"][@"status"] = subValue;
  869. dict[@"device"][@"status"] = deviceValue;
  870. if (endTime != 0) {
  871. dict[@"device"][@"end_date"] = @(endTime);
  872. dict[@"subscription"][@"end_date"] = @(endTime);
  873. }
  874. self.detailInfo = dict;
  875. if (postNo) {
  876. //发送通知
  877. NSString *notificationName = (NSString *)kDeviceActivateStatusChangeNotification;
  878. [[NSNotificationCenter defaultCenter] postNotificationName:notificationName
  879. object:self
  880. userInfo:nil];
  881. }
  882. }
  883. @end
  884. #endif
  885. #pragma mark - NSDictionary + ActivityInfo
  886. @implementation NSDictionary (ActivityInfo)
  887. - (NSDate*)expireDate {
  888. if (self[@"device"][@"end_date"]) {
  889. return [self dateForValue:self[@"device"][@"end_date"]];
  890. } else if (self[@"subscription"][@"end_date"]) {
  891. return [self dateForValue:self[@"subscription"][@"end_date"]];
  892. }
  893. return nil;
  894. }
  895. - (NSDate*)createDate {
  896. if (self[@"device"][@"created_at"]) {
  897. return [self dateForValue:self[@"device"][@"created_at"]];
  898. }
  899. return nil;
  900. }
  901. - (NSDate *)deviceActiveDate {
  902. if (self[@"device"][@"activated_date"]) {
  903. return [self dateForValue:self[@"device"][@"activated_date"]];
  904. }
  905. return nil;
  906. }
  907. - (NSDate *)deviceEndDate {
  908. if (self[@"device"][@"end_up_at"]) {
  909. return [self dateForValue:self[@"device"][@"end_up_at"]];
  910. }
  911. return nil;
  912. }
  913. - (ActivityStatus)status {
  914. ActivityStatus tStatus = ActivityStatusNone;
  915. if ([self[@"subscription"][@"status"] isEqualToString:@"expired"]) {
  916. tStatus = ActivityStatusLicenseExpire;
  917. }else{
  918. if ([self[@"device"][@"status"] isEqualToString:@"activated"]) {
  919. tStatus = ActivityStatusVerification;
  920. }else if ([self[@"device"][@"status"] isEqualToString:@"on_trial"]) {
  921. tStatus = ActivityStatusTrial;
  922. }else if ([self[@"device"][@"status"] isEqualToString:@"expired_trial"]) {
  923. tStatus = ActivityStatusTrialExpire;
  924. }else if ([self[@"device"][@"status"] isEqualToString:@"expired_license"]) {
  925. tStatus = ActivityStatusVerifExpire;
  926. }
  927. }
  928. if (ActivityStatusTrial == tStatus) {
  929. if (self.expireDate &&
  930. [NSDate date].timeIntervalSince1970 - [self expireDate].timeIntervalSince1970 > 0) {
  931. tStatus = ActivityStatusTrialExpire;
  932. }
  933. } else if (ActivityStatusVerification == tStatus) {
  934. if (self.expireDate &&
  935. [NSDate date].timeIntervalSince1970 - [self expireDate].timeIntervalSince1970 > 0) {
  936. tStatus = ActivityStatusVerifExpire;
  937. }
  938. if (self[@"dejvice"][@"status"] &&
  939. [self[@"device"][@"status"] isEqualToString:@"expired_license"]) {
  940. //激活码过期
  941. tStatus = ActivityStatusVerifExpire;
  942. }
  943. if ([self deviceActiveDate] && [self deviceEndDate]) {
  944. NSDate *activeDate = [self deviceActiveDate];
  945. NSDate *deviceEndDate = [self deviceEndDate];
  946. if (deviceEndDate.timeIntervalSince1970 - activeDate.timeIntervalSince1970 < 30*3600*24) {
  947. tStatus = ActivityStatusTrial;
  948. if (self.expireDate &&
  949. [NSDate date].timeIntervalSince1970 - [self expireDate].timeIntervalSince1970 > 0) {
  950. tStatus = ActivityStatusTrialExpire;
  951. }
  952. }
  953. }
  954. }
  955. return tStatus;
  956. }
  957. - (NSString*)licenseCode {
  958. return self[@"device"][@"cdkey"];
  959. }
  960. - (NSString*)originLicenseCode {
  961. return self[@"device"][@"origin_cdkey"];
  962. }
  963. - (NSString*)shareCode {
  964. return self[@"invite"][@"share_code"]?:@"";
  965. }
  966. - (NSUInteger)invateUsersCount {
  967. return [self[@"invite"][@"new_users_num"] integerValue];
  968. }
  969. - (NSString*)fromCode {
  970. return self[@"invite"][@"from_code"]?:@"";
  971. }
  972. - (NSDate*)fetchInvateDate {
  973. if (self[@"invite"][@"created_at"]) {
  974. return [self dateForValue:self[@"invite"][@"created_at"]];
  975. }
  976. return nil;
  977. }
  978. - (NSDate *)dateForValue:(id)value {
  979. if ([value isKindOfClass:[NSString class]]) {
  980. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  981. [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  982. formatter.locale = [NSLocale systemLocale];
  983. return [formatter dateFromString:value];
  984. }else if ([value isKindOfClass:[NSNumber class]]) {
  985. return [NSDate dateWithTimeIntervalSince1970:[value doubleValue]];
  986. }
  987. return nil;
  988. }
  989. - (BOOL)repeatTrial {
  990. return [self[@"device"][@"trial_again"] boolValue];
  991. }
  992. - (NSUInteger)trialTimes {
  993. return [self[@"device"][@"trial_times"]?:@"1" intValue];
  994. }
  995. - (NSString *)email {
  996. return self[@"device"][@"email"]?:@"";
  997. }
  998. - (NSString *)subscriptionEmail {
  999. return self[@"subscription"][@"email"]?:@"";
  1000. }
  1001. - (NSString *)accountName {
  1002. return self[@"device"][@"contact_name"]?:@"";
  1003. }
  1004. - (NSUInteger)maxFreeDays {
  1005. return [self[@"invite"][@"max_free_days"]?:@"365" intValue];
  1006. }
  1007. - (BOOL)allowUnbind {
  1008. return [self[@"device"][@"allow_unbind"] boolValue];
  1009. }
  1010. - (NSInteger)unbindTimes {
  1011. return [self[@"device"][@"unbind_time"]?:@"0" integerValue];
  1012. }
  1013. @end