XenonSDK.m 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. //
  2. // XenonSDK.m
  3. // XenonSDK
  4. //
  5. // Created by SAGESSE on 2019/3/11.
  6. // Copyright © 2019 SAGESSE. All rights reserved.
  7. //
  8. #import "XenonSDK.h"
  9. #import <Security/Security.h>
  10. #import <sys/utsname.h>
  11. #if SDK_HAS_IDFA
  12. #import <AdSupport/AdSupport.h>
  13. #endif
  14. #import "BubbleView.h"
  15. #import "RootViewController.h"
  16. #import "NoticeViewController.h"
  17. #import "UserBindPhoneViewController.h"
  18. #import "UserLoginFastViewController.h"
  19. #import "UserLoginPhoneViewController.h"
  20. #import "UserCenterViewController1.h"
  21. #import "UserCenterViewController2.h"
  22. #import "XSUtils.h"
  23. #import "KDIAPManager.h"
  24. #import "XSCollector.h"
  25. #import <objc/message.h>
  26. @interface XenonSDK ()
  27. @end
  28. ///
  29. /// Game SDK
  30. ///
  31. @implementation XenonSDK
  32. @synthesize user = _user;
  33. @synthesize token = _token;
  34. ///
  35. /// A sington instance of SDK.
  36. ///
  37. + (instancetype)sharedSDK {
  38. static id sharedSDK = nil;
  39. static dispatch_once_t onceToken;
  40. dispatch_once(&onceToken, ^{
  41. sharedSDK = XenonSDK.new;
  42. if (XSNetwork.baseURL == nil) {
  43. XSNetwork.baseURL = @"https://app.funcheergame.com";
  44. //测试地址 @"http://47.56.223.128:9099";
  45. //国内正式地址 @"https://app.funcheergame.com";
  46. //国外正式地址 @"https://fapp.funcheergame.com"
  47. }
  48. });
  49. return sharedSDK;
  50. }
  51. ///
  52. /// Init the sdk with application code.
  53. /// \param parameter The parameter provided by the platform.
  54. ///
  55. /// \param complete This closure called when init complete.
  56. ///
  57. - (void)initWithParameter:(NSString*)parameter complete:(void (^)(NSError* error))complete {
  58. // If init is complete, ignore it this call.
  59. if (self.configuration != nil) {
  60. if (complete != nil) {
  61. complete(nil); // sdk is ready.
  62. }
  63. return;
  64. }
  65. // Parse pre-configuration for parameter.
  66. NSArray* configs = [parameter componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"|&"]];
  67. if (configs.count != 4) {
  68. if (complete != nil) {
  69. complete([XSNetwork errorWithCode:-1 message:@"参数错误"]); // error -1
  70. }
  71. return ;
  72. }
  73. // Update pre-configuration for parameter.
  74. self.appId = configs[0];
  75. self.channelId = configs[1];
  76. self.adId = configs[2];
  77. self.adFlag = configs[3];
  78. // Update system configration for server.
  79. [XSNetwork configureWithIdentifier:self.adId flags:self.adFlag complete:^(XSConfiguration* object, NSError *error) {
  80. // If an error occurs, directly callback cp.
  81. if (error != nil) {
  82. if (complete != nil) {
  83. complete(error);
  84. }
  85. return;
  86. }
  87. // An unknown error.
  88. if (object.closeState != 0) {
  89. // Display an system notice.
  90. id qq = self.configuration.fixLinkQQ ?: @"";
  91. id tel = self.configuration.fixLinkTel ?: @"";
  92. // Set the update title & contents.
  93. id contents = [NSString stringWithFormat:@"\n亲爱的玩家您好, 由于服务器紧急维护, 目前游戏暂时无法进入, 给您带来的不便我们深表歉意!\n如果您还有其他问题请与我们联系!\n\n客服QQ: %@\n客服电话: %@", qq, tel];
  94. UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"系统公告" message:contents preferredStyle:UIAlertControllerStyleAlert];
  95. [alert addAction:[UIAlertAction actionWithTitle:@"我知道了" style:UIAlertActionStyleDefault handler:nil]];
  96. self.rootViewController = alert;
  97. complete([XSNetwork errorWithCode:-8 message:nil]);
  98. return;
  99. }
  100. // Setup sdk with server configuration.
  101. self.configuration = object;
  102. // Get third-party platform parameters.
  103. if (self.configuration.thirdPartyPrams.length != 0) {
  104. NSDictionary* thirdPartyPrams = [NSJSONSerialization JSONObjectWithData:[self.configuration.thirdPartyPrams dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
  105. // If the tracker is turned on, create the object.
  106. int mask = 0;
  107. NSString* dps = thirdPartyPrams[@"dp"];
  108. if (dps.length != 0) {
  109. sscanf(dps.UTF8String, "%x", &mask);
  110. if (mask != 0) {
  111. XSTracker.shared = [XSTracker new];
  112. XSTracker.shared.mask = mask;
  113. [XSNetwork trigger:20];
  114. }
  115. }
  116. // In the initialization.
  117. [XSTracker.shared trace:0x010000 parameters:[NSString stringWithFormat:@"%@", NSProcessInfo.processInfo.environment]];
  118. // If an advertisement parameter is specified, try to parse advertising parameter.
  119. NSString* adPrams = self.configuration.adPrams;
  120. if (adPrams.length != 0) {
  121. // Parse advertising parameter.
  122. [[adPrams componentsSeparatedByString:@"&"] enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  123. // Value must be `key=value`
  124. NSArray* tmp = [obj componentsSeparatedByString:@"="];
  125. if (tmp.count != 2) {
  126. return;
  127. }
  128. if ([tmp[0] isEqualToString:@"td_app_id"]) {
  129. self.configuration.tdAppId = tmp[1];
  130. }
  131. if ([tmp[0] isEqualToString:@"td_game_id"]) {
  132. self.configuration.tdGameId = tmp[1];
  133. }
  134. }];
  135. // If td game id is not provided, the TD sdk is not initialized.
  136. if (self.configuration.tdAppId.length != 0 && self.configuration.tdGameId.length != 0) {
  137. // Init for data analzer server.
  138. XSCollector.shared = [[XSCollector alloc] initWithAppId:self.configuration.tdAppId gameId:self.configuration.tdGameId];
  139. }
  140. }
  141. }
  142. [self sdk_checkVersion:^{
  143. [self sdk_checkNote:^{
  144. // Check workflow ended.
  145. [XSTracker.shared trace:0x010001];
  146. // Init sdk complete.
  147. if (complete != nil)
  148. complete(nil);
  149. // init workflow ended.
  150. [XSTracker.shared trace:0x010002];
  151. }];
  152. }];
  153. }];
  154. }
  155. ///
  156. /// Login the sdk.
  157. /// \param complete This closure called when login complete.
  158. ///
  159. - (void)loginWithComplete:(void (^)(id user, NSError* error))complete {
  160. // If init is complete, ignore it this call.
  161. if (self.configuration == nil) {
  162. if (complete != nil)
  163. complete(nil, [XSNetwork errorWithCode:-1 message:@"请先初始化"]); // error -1
  164. //发出登录失败通知. flag=NO
  165. NSNotification *notification = [NSNotification notificationWithName:@"LoginSuccessNotificaion" object:nil userInfo:@{@"userInfo":@"",@"flag":@"NO"}];
  166. [[NSNotificationCenter defaultCenter] postNotification:notification];
  167. return;
  168. }
  169. [XSTracker.shared trace:0x010010];
  170. // Unified operation after successful login.
  171. void (^loginedCallback)(void) = ^{
  172. // Build return data.
  173. id user = nil;
  174. if (self.user != nil) {
  175. user = @{
  176. @"uid": self.user.uid,
  177. @"token": self.user.token,
  178. @"userName": self.user.userName ?: @"",
  179. @"phone": self.user.phone ?: @""
  180. };
  181. // According to air bubbles.
  182. if (!self.configuration.isFloatDisable) {
  183. UIWindow* window = UIApplication.sharedApplication.delegate.window ?: UIApplication.sharedApplication.keyWindow;
  184. BubbleView* view = [[BubbleView alloc] initWithFrame:CGRectMake(0, 0, 60, 60)];
  185. [view.contentView addTarget:self action:@selector(center) forControlEvents:UIControlEventTouchUpInside];
  186. UITapGestureRecognizer *tapRecognize = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTap:)];
  187. [view addGestureRecognizer:tapRecognize];
  188. [window addSubview:view];
  189. // It's shown in the first one.
  190. UIView* xmp = [window viewWithTag:-1];
  191. if (xmp != nil) {
  192. [window bringSubviewToFront:xmp];
  193. }
  194. [self.bubbleView removeFromSuperview];
  195. self.bubbleView = view;
  196. }
  197. [XSTracker.shared trace:0x010013];
  198. }
  199. [XSTracker.shared trace:0x010011];
  200. if (complete) {
  201. complete(user, nil);
  202. }
  203. [XSTracker.shared trace:0x010012];
  204. };
  205. // Try automatically login if needed.
  206. if (self.user != nil) {
  207. [XSNetwork showHudLoading];
  208. [XSNetwork authWithUser:self.user.uid complete:^(XSUser* user, NSError *error) {
  209. // If the login fails, clear the user information and login again.
  210. if (user.token.length == 0 || error != nil) {
  211. [XSNetwork showHudFailure:@"登录时效期已过,请重新登录"];
  212. self.user = nil;
  213. [self loginWithComplete:complete];
  214. return;
  215. }
  216. // Update user info.
  217. XSUser* duser = self.user;
  218. duser.token = user.token;
  219. duser.isRegister = false;
  220. self.user = duser;
  221. // Login successful, display HUD.
  222. [XSNetwork showPrompt:duser.name];
  223. //发出登成功通知.flag=YES
  224. NSDictionary *dict = @{@"userInfo":self.user,@"flag":@"YES"};
  225. NSNotification *notification = [NSNotification notificationWithName:@"LoginSuccessNotificaion" object:nil userInfo:dict];
  226. [[NSNotificationCenter defaultCenter] postNotification:notification];
  227. // Check if the user is already connected to the phone.
  228. // [self sdk_checkPhone:^{
  229. // loginedCallback();
  230. // }];
  231. //绑定手机
  232. loginedCallback();
  233. }];
  234. [XSTracker.shared trace:0x010014];
  235. return;
  236. }
  237. // Setup login callback.
  238. __weak __typeof(self) ws = self;
  239. self.sdk_loginCallback = ^(XSUser* user) {
  240. [ws setUser:user];
  241. [ws.rootViewController dismissViewControllerAnimated:YES completion:nil];
  242. // Login successful, display HUD.
  243. //发出登录成功通知.
  244. NSDictionary *dict = @{@"userInfo":user,@"flag":@"YES"};
  245. NSNotification *notification = [NSNotification notificationWithName:@"LoginSuccessNotificaion" object:nil userInfo:dict];
  246. [[NSNotificationCenter defaultCenter] postNotification:notification];
  247. [XSNetwork showPrompt:user.name];
  248. loginedCallback();
  249. };
  250. // The last time was to log out, so the quick login list is displayed.
  251. if (XSUser.history.count != 0) {
  252. //self.rootViewController = [[RootViewController alloc] initWithRootViewController:UserLoginFastViewController.new];
  253. self.rootViewController = [[RootViewController alloc] initWithRootViewController:UserLoginPhoneViewController.new];
  254. return;
  255. }
  256. // To account login
  257. self.rootViewController = [[RootViewController alloc] initWithRootViewController:UserLoginPhoneViewController.new];
  258. }
  259. ///
  260. /// Logout the sdk.
  261. /// \param complete This closure called when logout complete.
  262. ///
  263. - (void)logoutWithComplete:(void (^)(void))complete {
  264. // If init is complete, ignore it this call.
  265. if (self.configuration == nil) {
  266. if (complete != nil)
  267. complete();
  268. return;
  269. }
  270. self.user = nil;
  271. [self.bubbleView removeFromSuperview];
  272. self.bubbleView = nil;
  273. //发出退出通知.
  274. NSNotification *notification = [NSNotification notificationWithName:@"LogoutNotificaion" object:nil userInfo:nil];
  275. [[NSNotificationCenter defaultCenter] postNotification:notification];
  276. if (complete != nil)
  277. complete();
  278. [XSTracker.shared trace:0x010020];
  279. }
  280. ///
  281. /// Logout the game and sdk.
  282. /// \param handler This closure called when user logout in web view.
  283. /// \note Warning this handler will retain in until next call this method.
  284. ///
  285. - (void)logoutWhenNotification:(void (^)(void))handler {
  286. self.sdk_logoutCallback = ^(id user) {
  287. if (handler != nil)
  288. handler();
  289. [XSTracker.shared trace:0x010020];
  290. };
  291. }
  292. ///
  293. /// Buy a product.
  294. /// \param parameters Payment request parameters.
  295. /// \param complete Payment result of the callback, if the apple payment is completed before the callback, other payments will be the official launch of the callback
  296. ///
  297. - (void)buy:(NSDictionary*)parameters complete:(void (^)(id order, NSError* error))complete {
  298. // Check paramrters.
  299. if (self.configuration == nil || self.user == nil) {
  300. if (complete != nil) {
  301. complete(nil, [XSNetwork errorWithCode:-1 message:@"请先登录"]); // error -1
  302. return ;
  303. }
  304. }
  305. [XSTracker.shared trace:0x010030];
  306. [XSNetwork showHudLoading];
  307. //
  308. // [XSNetwork routeWithComplete:^(id object, NSError *error) {
  309. //
  310. // if (error != nil) {
  311. // [XSNetwork showHudFailure:error];
  312. // if (complete != nil) {
  313. // complete(nil, error);
  314. // }
  315. // return;
  316. // }
  317. // Get parmeters.
  318. XSUser* user = self.user;
  319. //NSString* path = object[fqsd(@"PREAACs/NCYsJjQuLRkA")];
  320. //#if SDK_HAS_H5_PAYMENT
  321. //Generate h5 payment parameters.
  322. // if (path.length != 0) {
  323. //
  324. // [XSNetwork hideHud];
  325. // [XSTracker.shared trace:0x010031];
  326. //
  327. // id payments = @{
  328. // @"cpBillNo": parameters[@"orderId"] ?: @"",
  329. // @"orderAmount": parameters[@"amount"] ?: @"",
  330. // @"subject": parameters[@"productName"] ?: @"",
  331. //
  332. // @"roleName": parameters[@"roleName"] ?: @"",
  333. // @"serverId": parameters[@"serverId"] ?: @"",
  334. // @"extraInfo": parameters[@"extraInfo"] ?: @"",
  335. //
  336. // @"phone": @"",
  337. // @"isTest": @"1",
  338. // @"orderPlatform": @"0",
  339. // @"orderType": @"1",
  340. // @"remark": @"0",
  341. // @"isApp": @"0",
  342. //
  343. // @"uid": user.uid,
  344. // @"userName": user.userName ?: @""
  345. // };
  346. //
  347. // NSURLComponents* components = [NSURLComponents componentsWithString:path];
  348. // NSDictionary* json = [XSNetwork bodyWithParameters:payments];
  349. // NSString* str = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:json options:0 error:nil] encoding:NSUTF8StringEncoding];
  350. //
  351. // components.queryItems = @[[NSURLQueryItem queryItemWithName:@"jsonData" value:str],
  352. // [NSURLQueryItem queryItemWithName:@"v" value:@"1"]];
  353. //
  354. // if (components.URL == nil) {
  355. // if (complete != nil) {
  356. // complete(nil, [XSNetwork errorWithCode:-1 message:@"后台参数错误"]);
  357. // }
  358. // return;
  359. // }
  360. //
  361. // UserCenterViewController* rootViewController = UserCenterViewController.new;
  362. // rootViewController.custom = components.URL.absoluteString;
  363. // rootViewController.otherView = self.bubbleView;
  364. // rootViewController.modalPresentationStyle = UIModalPresentationOverFullScreen;
  365. // self.rootViewController = rootViewController;
  366. //
  367. // // Cannot get the callback state.
  368. // rootViewController.callback = ^{
  369. // if (complete != nil) {
  370. // complete(nil, nil);
  371. // }
  372. // };
  373. // return;
  374. // }
  375. //#endif
  376. //#if SDK_HAS_IAP_PAYMENT
  377. // Generate iap payment parameters.
  378. id payments = @{
  379. @"productCode": parameters[@"productCode"] ?: @"",
  380. @"isCoin": @"0",
  381. @"orderPlatform": @"0",
  382. @"orderType": @"1",
  383. @"orderAmount": parameters[@"amount"] ?: @"",
  384. @"isTest": @"0",
  385. @"subject": parameters[@"productName"] ?: @"",
  386. @"roleName": parameters[@"roleName"] ?: @"",
  387. @"cpBillNo": parameters[@"orderId"] ?: @"",
  388. @"remark": @"0",
  389. @"serverId": parameters[@"serverId"] ?: @"",
  390. @"extraInfo": parameters[@"extraInfo"] ?: @"",
  391. @"uid": user.uid,
  392. @"userName": user.userName ?: @""
  393. };
  394. [XSTracker.shared trace:0x010032];
  395. [XSNetwork payWithParameters:payments complete:^(id object, NSError *error) {
  396. if (error != nil) {
  397. [XSNetwork showHudFailure:error];
  398. if (complete != nil) {
  399. complete(nil, error);
  400. }
  401. return;
  402. }
  403. [XSTracker.shared trace:0x010034];
  404. [XSNetwork showHudSuccess:@"支付成功"];
  405. if (complete != nil)
  406. complete(payments, nil);
  407. }];
  408. //#endif
  409. //}];
  410. }
  411. ///点击悬浮按钮,
  412. -(void)handleTap:(UITapGestureRecognizer *)recognizer {
  413. if (self.configuration == nil || self.user == nil) {
  414. return;
  415. }
  416. [XSTracker.shared trace:0x010040];
  417. //0:横屏 1:竖屏
  418. #define SCREEN_Direction 0
  419. ///横屏
  420. #if SCREEN_Direction == 0
  421. UserCenterViewController1* rootViewController1 = UserCenterViewController1.new;
  422. rootViewController1.otherView = self.bubbleView;
  423. rootViewController1.modalPresentationStyle = UIModalPresentationOverFullScreen;
  424. self.rootViewController = rootViewController1;
  425. #endif
  426. ///竖屏
  427. #if SCREEN_Direction == 1
  428. UserCenterViewController2* rootViewController2 = UserCenterViewController2.new;
  429. rootViewController2.otherView = self.bubbleView;
  430. rootViewController2.modalPresentationStyle = UIModalPresentationOverFullScreen;
  431. self.rootViewController = rootViewController2;
  432. #endif
  433. }
  434. ///
  435. /// User Center.
  436. ///
  437. - (void)center {
  438. if (self.configuration == nil || self.user == nil) {
  439. return;
  440. }
  441. [XSTracker.shared trace:0x010040];
  442. //0:横屏 1:竖屏
  443. #define SCREEN_Direction 0
  444. ///横屏
  445. #if SCREEN_Direction == 0
  446. UserCenterViewController1* rootViewController1 = UserCenterViewController1.new;
  447. rootViewController1.otherView = self.bubbleView;
  448. rootViewController1.modalPresentationStyle = UIModalPresentationOverFullScreen;
  449. self.rootViewController = rootViewController1;
  450. #endif
  451. ///竖屏
  452. #if SCREEN_Direction == 1
  453. UserCenterViewController2* rootViewController2 = UserCenterViewController2.new;
  454. rootViewController2.otherView = self.bubbleView;
  455. rootViewController2.modalPresentationStyle = UIModalPresentationOverFullScreen;
  456. self.rootViewController = rootViewController2;
  457. #endif
  458. }
  459. /// Report role info.
  460. /// \param roleName This role name.
  461. ///
  462. /// \param level This role current level.
  463. ///
  464. /// \param serverId This role current server.
  465. ///
  466. - (void)reportWithRoleName:(NSString*)roleName level:(NSInteger)level serverId:(NSString*)serverId {
  467. if (self.configuration == nil || self.user == nil) {
  468. return;
  469. }
  470. [XSNetwork reportWithUser:self.user.userName Name:roleName level:level server:serverId];
  471. [XSCollector.shared reportWithAccount:self.user.uid name:roleName level:level server:serverId];
  472. }
  473. ///自动登录
  474. - (void)hAutoWithComplete:(void (^)(id user, NSError* error))complete {
  475. [XSNetwork showHudLoading];
  476. //获取上次保存的登录信息.
  477. XSUser* user1 = [XSDataCenter valueForKey:@"User.current"];
  478. //未注册,
  479. if (user1.uid.length == 0) {
  480. __weak __typeof(self) ws = self;
  481. [XSNetwork loginWithComplete:^(id object, NSError *error) {
  482. if (error != nil) {
  483. [XSNetwork showHudFailure:error];
  484. complete(nil, error);
  485. return;
  486. }
  487. [ws setUser:object];
  488. //XenonSDK.sharedSDK.user = object;
  489. [XSNetwork showHudSuccess:@"登录成功!"];
  490. complete(object,nil);
  491. }];
  492. }else{
  493. //
  494. XenonSDK.sharedSDK.token = user1.token;
  495. __weak __typeof(self) ws = self;
  496. [XSNetwork authWithUser:user1.uid complete:^(XSUser* object, NSError *error) {
  497. if (error != nil && ![error.domain isEqual:@"XSNetwork"]) {
  498. [XSNetwork showHudFailure:error];
  499. complete(nil,[XSNetwork errorWithCode:-1 message:error.domain]);
  500. return;
  501. }
  502. [XSNetwork showHudSuccess:@"登录成功!"];
  503. if (user1.token.length != 0 && error == nil) {
  504. // Update user info.
  505. user1.token = object.token;
  506. user1.isRegister = NO;
  507. XenonSDK.sharedSDK.user = user1;
  508. [ws setUser:user1];
  509. complete(user1,nil);
  510. }
  511. }];
  512. }
  513. }
  514. // MARK: -检查版本更新
  515. - (void)sdk_checkVersion:(void(^)(void))complete {
  516. // If no configuration file is provided, initialization failed.
  517. if (self.configuration == nil) {
  518. complete();
  519. return;
  520. }
  521. // If update cheker is not enabled, ignore it.
  522. NSURL* url = [NSURL URLWithString:self.configuration.updateUrl];
  523. if (url == nil || self.configuration.updateState == 0) {
  524. complete();
  525. return;
  526. }
  527. // If the prompt is too frequent, wait.
  528. // 1 is normal update.
  529. if (self.configuration.updateState == 1 && !([XSDataCenter doubleForKey:@"verion-later"] < NSDate.new.timeIntervalSince1970)) {
  530. complete();
  531. return;
  532. }
  533. NoticeViewController* viewController = NoticeViewController.new;
  534. // Set the update title & contents.
  535. viewController.title = @"发现新版本";
  536. viewController.contents = [NSString stringWithFormat:@"亲爱的玩家您好,我们发布了新的版本, 更新到新版本可体验更多新奇有趣的玩法!\n\n最新版本: %@\n当前版本: %@\n\n\n", self.configuration.updateVersion, self.shortVersion];
  537. // Set the confirm closure.
  538. [viewController addActionWithName:@"立即升级" handler:^{
  539. // -[UIApplication openURL:]
  540. ((void(*)(id,SEL,id))objc_msgSend)(UIApplication.sharedApplication, NSSelectorFromString(fqsd(@"p2cAAMrAyrKwq5rIAA==")), url);
  541. }];
  542. // Set the cancel closure.
  543. if (self.configuration.updateState == 1) {
  544. __weak __typeof(self) ws = self;
  545. [viewController addActionWithName:@"稍后再说" handler:^{
  546. // Again 24 hours later.
  547. [XSDataCenter setDouble:[NSDate dateWithTimeIntervalSinceNow:24*60*60].timeIntervalSince1970 forKey:@"verion-later"];
  548. if (ws.rootViewController == nil) {
  549. complete();
  550. return;
  551. }
  552. // Automatic hidden controller.
  553. [ws.rootViewController dismissViewControllerAnimated:YES completion:complete];
  554. }];
  555. }
  556. // Show view contorller in key window.
  557. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  558. self.rootViewController = [[RootViewController alloc] initWithRootViewController:viewController];
  559. });
  560. }
  561. - (void)sdk_checkNote:(void(^)(void))complete {
  562. // If no configuration file is provided, initialization failed.
  563. NSURL* url = [NSURL URLWithString:self.configuration.closeUrl];
  564. if (url == nil || self.configuration.linkQq == 0) {
  565. complete();
  566. return ;
  567. }
  568. // If the announcement is displayed, it is no longer displayed.
  569. if (self.configuration.linkQq != 2 && [[XSDataCenter stringForKey:@"notice-later"] isEqualToString:url.absoluteString]) {
  570. complete();
  571. return;
  572. }
  573. NoticeViewController* viewController = NoticeViewController.new;
  574. // Set the update title & contents.
  575. viewController.title = @"系统公告";
  576. viewController.contents = url;
  577. // Set the confirm closure.
  578. __weak __typeof(self) ws = self;
  579. [viewController addActionWithName:@"我知道了" handler:^{
  580. // Never again.
  581. [XSDataCenter setString:url.absoluteString forKey:@"notice-later"];
  582. if (ws.rootViewController == nil) {
  583. complete();
  584. return;
  585. }
  586. // Automatic hidden controller.
  587. [ws.rootViewController dismissViewControllerAnimated:YES completion:complete];
  588. }];
  589. // Show view contorller in key window.
  590. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  591. self.rootViewController = [[RootViewController alloc] initWithRootViewController:viewController];
  592. });
  593. }
  594. - (void)sdk_checkPhone:(void(^)(void))complete {
  595. // Check if the phone character exists.
  596. if (self.user.isRegister || self.user.phone.length != 0 || self.configuration.serverStatus == 1) {
  597. complete();
  598. return;
  599. }
  600. // If the prompt is too frequent, wait.
  601. id key = [NSString stringWithFormat:@"%@-bind-later", self.user.uid];
  602. if ([XSDataCenter doubleForKey:key] > NSDate.new.timeIntervalSince1970) {
  603. complete();
  604. return;
  605. }
  606. UserBindPhoneViewController* bindViewController = UserBindPhoneViewController.new;
  607. RootViewController* rooViewController = [[RootViewController alloc] initWithRootViewController:bindViewController];
  608. UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"您的帐号存在风险, 为了您的帐号安全建议您绑定手机号。" preferredStyle:UIAlertControllerStyleAlert];
  609. // Add confirm action.
  610. [alert addAction:[UIAlertAction actionWithTitle:@"绑定手机" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
  611. bindViewController.callback = complete;
  612. self.rootViewController = rooViewController;
  613. }]];
  614. // Add cancel action.
  615. [alert addAction:[UIAlertAction actionWithTitle:@"稍后提醒" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  616. // Again 24 hours later.
  617. [XSDataCenter setDouble:[NSDate dateWithTimeIntervalSinceNow:24*60*60].timeIntervalSince1970 forKey:key];
  618. // Continue.
  619. complete();
  620. }]];
  621. (void)rooViewController.view; // preload;
  622. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  623. self.rootViewController = alert;
  624. });
  625. // Hide all hud if needed.
  626. [XSNetwork hideHud];
  627. }
  628. ///check In-app Purchase lost list.
  629. - (void)checkOrderStatus {
  630. //检查内购掉单.
  631. [KDIAPManager checkOrderStatus];
  632. }
  633. // MARK: -
  634. - (void)setUser:(XSUser *)user {
  635. _user = user;
  636. _token = user.token;
  637. // Cache.
  638. [XSDataCenter setValue:user forKey:@"User.current"];
  639. if (user == nil) {
  640. return;
  641. }
  642. // Make a new login history.
  643. NSMutableSet* ids = [NSMutableSet set];
  644. NSMutableArray* history = [NSMutableArray array];
  645. user.lastTime = NSDate.new.timeIntervalSince1970;
  646. [ids addObject:user.uid];
  647. [history addObject:user];
  648. for (XSUser* tmp in XSUser.history) {
  649. if (![ids containsObject:tmp.uid]) {
  650. [ids addObject:tmp.uid];
  651. [history addObject:tmp];
  652. }
  653. }
  654. XSUser.history = history;
  655. }
  656. - (XSUser*)user {
  657. if (_user != nil) {
  658. return _user;
  659. }
  660. static dispatch_once_t onceToken;
  661. dispatch_once(&onceToken, ^{
  662. self->_user = [XSDataCenter valueForKey:@"User.current"];
  663. self->_token = self->_user.token;
  664. });
  665. return _user;
  666. }
  667. - (void)setRootViewController:(UIViewController *)rootViewController {
  668. _rootViewController = rootViewController;
  669. if (rootViewController == nil) {
  670. return;
  671. }
  672. [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:rootViewController
  673. animated:YES
  674. completion:nil];
  675. }
  676. /// Permanent preservation of data.
  677. - (void)setPermanentValue:(NSString*)value forKey:(NSString*)key {
  678. // Set value to user defautls.
  679. [XSDataCenter setString:value forKey:key];
  680. // Configure the search setting.
  681. id setting = @{
  682. // Configure the keychain key type.
  683. CFBridgingRelease(kSecClass): CFBridgingRelease(kSecClassGenericPassword),
  684. CFBridgingRelease(kSecAttrAccount): key
  685. }.mutableCopy;
  686. // Delete old item before add new item
  687. SecItemDelete(CFBridgingRetain(setting));
  688. // Add new object to search dictionary.
  689. [setting setObject:[value dataUsingEncoding:NSUTF8StringEncoding] forKey:CFBridgingRelease(kSecValueData)];
  690. // Add item to keychain with the search dictionary
  691. SecItemAdd(CFBridgingRetain(setting), nil);
  692. }
  693. /// Read data for permanent preservationed.
  694. - (id)permanentValueForKey:(NSString*)key {
  695. // Read data from user defatuls.
  696. NSString* udid = [XSDataCenter stringForKey:key];
  697. if (udid.length != 0) {
  698. return udid;
  699. }
  700. // Configure the search setting.
  701. id setting = @{
  702. // Configure the keychain key type.
  703. CFBridgingRelease(kSecClass): CFBridgingRelease(kSecClassGenericPassword),
  704. // The class name of the SDK is dynamic.
  705. CFBridgingRelease(kSecAttrService): NSStringFromClass(self.class),
  706. CFBridgingRelease(kSecAttrAccount): key,
  707. // Gets result data of data.
  708. CFBridgingRelease(kSecReturnData): CFBridgingRelease(kCFBooleanTrue)
  709. };
  710. // Start query the keychain query.
  711. CFTypeRef result = nil;
  712. if (SecItemCopyMatching(CFBridgingRetain(setting), &result) == noErr) {
  713. return nil;
  714. }
  715. // Convert data to a string
  716. NSString* value = [[NSString alloc] initWithData:CFBridgingRelease(result) encoding:NSUTF8StringEncoding];
  717. if (value.length == 0) {
  718. return nil;
  719. }
  720. // Set value to user defautls, reduce Keychain access count.
  721. [XSDataCenter setString:value forKey:key];
  722. return value;
  723. }
  724. - (NSString*)advertisingIdentifier {
  725. // Read the data from keychain.
  726. NSString* advertisingIdentifier = [self permanentValueForKey:@"udid"];
  727. if (advertisingIdentifier.length != 0) {
  728. return advertisingIdentifier;
  729. }
  730. #if SDK_HAS_IDFA
  731. // Try to obtain idfa.
  732. ASIdentifierManager* advertisingManager = ASIdentifierManager.sharedManager;
  733. advertisingIdentifier = advertisingManager.advertisingIdentifier.UUIDString;
  734. if (!advertisingManager.isAdvertisingTrackingEnabled) {
  735. advertisingIdentifier = [NSString stringWithFormat:@"#%@", NSUUID.new.UUIDString];
  736. }
  737. #else
  738. // Generate an id to replace idfa.
  739. advertisingIdentifier = [NSString stringWithFormat:@"#%@", NSUUID.new.UUIDString];
  740. #endif
  741. // Save to keychain to prevent updates.
  742. [self setPermanentValue:advertisingIdentifier forKey:@"udid"];
  743. return advertisingIdentifier;
  744. }
  745. - (NSString*)advertisingVendor {
  746. // This parameter has been deprecated and must be empty string.
  747. return @"";
  748. }
  749. - (NSBundle*)bundle {
  750. return [NSBundle bundleForClass:self.class];
  751. }
  752. - (NSString*)model {
  753. struct utsname sinfo;
  754. uname(&sinfo);
  755. return [NSString stringWithUTF8String: sinfo.machine];
  756. }
  757. /// The sdk verions.
  758. - (NSString*)version {
  759. return self.bundle.infoDictionary[@"CFBundleShortVersionString"] ?: @"1.0";
  760. }
  761. /// The game verions.
  762. - (NSString*)shortVersion {
  763. return NSBundle.mainBundle.infoDictionary[@"CFBundleShortVersionString"] ?: @"1.0";
  764. }
  765. ///TalkingData 游戏运营统计
  766. - (void)TDGameOperationsinitWithAppID:(NSString *)appid ChannelId:(NSString *)channelId {
  767. if (appid.length == 0) {
  768. NSLog(@"TalkingData 游戏运营统计: appid为空!");
  769. return;
  770. }
  771. if (channelId) {
  772. NSLog(@"TalkingData 游戏运营统计: channelId为空!");
  773. }
  774. [TalkingDataGA onStart:appid withChannelId:channelId];
  775. }
  776. -(void)TDregisterWithAccount:(NSString *)account name:(NSString *)name {
  777. [[XSCollector sharedManager] registerWithAccount:account name:name];
  778. }
  779. -(void)TDloginWithAccount:(NSString *)account name:(NSString *)name {
  780. [[XSCollector sharedManager] loginWithAccount:account name:name];
  781. }
  782. -(void)TDreportWithAccount:(NSString*)account Name:(NSString *)name Age:(int)age Gender:(NSInteger)gender {
  783. [[XSCollector sharedManager] reportWithAccount:account name:name age:age gender:gender];
  784. }
  785. -(void)TDreportWithAccount:(NSString*)account name:(NSString*)name level:(NSInteger)level server:(NSString*)server {
  786. [[XSCollector sharedManager] reportWithAccount:account name:name level:level server:server];
  787. }
  788. -(void)TDonChargeRequst:(NSString *)orderId iapId:(NSString *)iapId currencyAmount:(double)currencyAmount currencyType:(NSString *)currencyType virtualCurrencyAmount:(double)virtualCurrencyAmount paymentType:(NSString *)paymentType {
  789. [[XSCollector sharedManager] onChargeRequst:orderId iapId:iapId currencyAmount:currencyAmount currencyType:currencyType virtualCurrencyAmount:virtualCurrencyAmount paymentType:paymentType];
  790. }
  791. - (void)TDonChargeSuccess:(NSString *)orderId {
  792. [[XSCollector sharedManager] onChargeSuccess:orderId];
  793. }
  794. //TD 自定义事件
  795. -(void)TDonEvent:(NSString *)eventId eventData:(id)parm {
  796. [[XSCollector sharedManager] onEvent:eventId eventData:parm];
  797. }
  798. - (void)TDAnalyticsinitWithAppID:(NSString *)appid ChannelId:(NSString *)channelId backgroundSession:(BOOL)flag {
  799. if (appid.length == 0 ) {
  800. NSLog(@"【TalkingData】,error=App ID参数为nil");
  801. return;
  802. }
  803. if (channelId.length == 0) {
  804. NSLog(@"【TalkingData】,error=渠道 ID参数为nil");
  805. }
  806. if (flag) {
  807. [TalkingData backgroundSessionEnabled]; //获取后台使用时长
  808. }
  809. [TalkingData sessionStarted:appid withChannelId:channelId]; //init
  810. [TalkingData setExceptionReportEnabled:YES]; //自动获取异常信息
  811. [TalkingData setSignalReportEnabled:YES]; //自动获取异常信号
  812. }
  813. -(void)TDAnalyticsTrackPageBegin:(NSString *)pageName {
  814. [TalkingData trackPageBegin:pageName];
  815. }
  816. -(void)TDAnalyticsTrackPageEnd:(NSString *)pageName {
  817. [TalkingData trackPageEnd:pageName];
  818. }
  819. //自定义事件1
  820. - (void)TDAnalyticsTrackEvent:(NSString *)eventID {
  821. [TalkingData trackEvent:eventID];
  822. }
  823. //自定义事件2
  824. - (void)TDAnalyticsTrackEvent:(NSString *)eventID label:(NSString *)event_label {
  825. [TalkingData trackEvent:eventID label:event_label];
  826. }
  827. //自定义事件3,eventID:自定义事件名称, event_label:自定义事件Label,用来区分具体场景. dict:自定义事件的参数及参数取值.
  828. - (void)TDAnalyticsTrackEvent:(NSString *)eventID label:(NSString *)event_label parameters:(NSDictionary *)dict {
  829. [TalkingData trackEvent:eventID label:event_label parameters:dict];
  830. }
  831. //orderId:订单ID total:订单总金额,货币单位为分 currencyType:货币种类,eg:人民币 CNY;美元 USD;欧元 EUR
  832. -(TalkingDataOrder *)TDAnalyticsCreateOrder:(NSString *)orderId total:(int)total currencyType:(NSString *)currencyType {
  833. TalkingDataOrder *order = [TalkingDataOrder createOrder:orderId total:total currencyType:currencyType];
  834. return order;
  835. }
  836. //应用内支付-添加订单详情.order为创建的订单
  837. - (void)TDAnalyticsWith:(TalkingDataOrder *)order AddItem:(NSString *)itemId category:(NSString *)category name:(NSString *)name unitPrice:(int)unitPrice amount:(int)amount {
  838. [order addItem:itemId category:category name:name unitPrice:unitPrice amount:amount];
  839. }
  840. //应用内支付-成功支付订单
  841. - (void)TDAnalyticsOnPlaceOrder:(NSString *)profileID order:(TalkingDataOrder *)order {
  842. [TalkingData onPlaceOrder:profileID order:order];
  843. }
  844. ///穿山甲广告Ad
  845. //1.init
  846. - (void)CSJAdSDKinit {
  847. [MLAdManager sharedInstance];
  848. }
  849. //优量汇广告Ad-init
  850. -(void)YLHAdSDKinit {
  851. [YLHAdManager sharedInstance];
  852. }
  853. //TopOn广告Ad-init
  854. -(void)TopOnAdSDKinit {
  855. [TOPONAdManager sharedInstance];
  856. }
  857. //2.打开全屏广告
  858. -(void)openBUDFullScreenVideoAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  859. [[MLAdManager sharedInstance] openFullScreenVideoAd:adName callback:callback];
  860. }
  861. //打开新插屏广告(新增)
  862. -(void)openBUDNewInterstitialAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  863. [[MLAdManager sharedInstance] openNewInterstitialAd:adName callback:callback];
  864. }
  865. //2.打开开屏广告
  866. -(void)openBUDSplashAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  867. [[MLAdManager sharedInstance] openSplashAd:adName callback:callback];
  868. }
  869. //3. 打开插屏广告
  870. -(void)openBUDInterstitialAd:(NSString *)adName width:(CGFloat)w Height:(CGFloat)h callback:(void (^)(BOOL))callback {
  871. [[MLAdManager sharedInstance] openExpressInterstitialAd:adName Width:w Height:h callback:callback];
  872. }
  873. //4. 打开视频激励广告
  874. -(void)openBUDExpressRewardedVideoAd:(NSString *)adName callback:(void (^)(BOOL,BOOL))callback {
  875. [[MLAdManager sharedInstance] openExpressRewardedVideoAd:adName callback:callback];
  876. }
  877. //5. 打开原生Banner广告
  878. -(void)openBUDNativeBannerAd:(NSString *)adName WithX:(CGFloat)x Y:(CGFloat)y Width:(CGFloat)w Height:(CGFloat)h callback:(void (^)(BOOL))callback {
  879. [[MLAdManager sharedInstance] openNativeExpressBannerAd:adName WithX:x Y:y Width:w Height:h callback:callback];
  880. }
  881. //6. 打开原生广告
  882. -(void)openBUDNativeAd:(NSString *)adName WidthCGRect:(CGRect)rect BUSize:(NSInteger)size callback:(void (^)(BOOL))callback {
  883. [[MLAdManager sharedInstance] openNativeAd:adName WidthCGRect:rect BUSize:size callback:callback];
  884. }
  885. //5.2 关闭Banner广告
  886. -(void)closeBUDBannerAd:(NSString *)adName {
  887. [[MLAdManager sharedInstance] closeBannerAd:adName];
  888. }
  889. //优量汇广告
  890. //init
  891. -(void)openYLHSplashAd:(NSString *)adName supportZoomoutView:(BOOL)flag callback:(void (^)(BOOL))callback {
  892. [[YLHAdManager sharedInstance] openSplashAd:adName supportZoomoutView:flag callback:callback];
  893. }
  894. -(void)openYLHInterstitialAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  895. [[YLHAdManager sharedInstance] openExpressInterstitialAd:adName callback:callback];
  896. }
  897. -(void)openYLHFullScreenAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  898. [[YLHAdManager sharedInstance] openFullScreenVideoAd:adName callback:callback];
  899. }
  900. -(void)openYLHExpressRewardedVideoAd:(NSString *)adName callback:(void (^)(BOOL, BOOL))callback {
  901. [[YLHAdManager sharedInstance] openExpressRewardedVideoAd:adName callback:callback];
  902. }
  903. //4.5 打开横幅广告
  904. -(void)openYLHExpressBannerAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  905. [[YLHAdManager sharedInstance] openExpressBannerVideoAd:adName callback:callback];
  906. }
  907. //4.6 打开原生广告
  908. -(void)openYLHExpressNativeAdWithPlacementId:(NSString *)placementId AdName:(NSString *)adName Frame:(CGRect)rect callback:(void (^)(BOOL))callback {
  909. [[YLHAdManager sharedInstance] openExpressNativeAdWithPlacementId:placementId AdName:adName Frame:rect callback:callback];
  910. }
  911. -(void)openTOPONSplashAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  912. [[TOPONAdManager sharedInstance] opensplashAd:adName callback:callback];
  913. }
  914. -(void)openTOPONInterstitialAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  915. [[TOPONAdManager sharedInstance] openInterstitialAd:adName callback:callback];
  916. }
  917. -(void)openTOPONRewardedVideoAd:(NSString *)adName callback:(void (^)(BOOL,BOOL))callback {
  918. [[TOPONAdManager sharedInstance] openRewardedVideoAd:adName callback:callback];
  919. }
  920. -(void)openTOPONExpressBannerAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  921. [[TOPONAdManager sharedInstance] openExpressBannerAd:adName callback:callback];
  922. }
  923. -(void)openTOPONNativeAdWithX:(int)x Y:(int)y width:(int)w height:(int)h adId:(NSString *)adName callback:(void (^)(BOOL))callback {
  924. [[TOPONAdManager sharedInstance] openNativeAdWithX:x Y:y width:w height:h adId:adName callback:callback];
  925. }
  926. -(void)showHudWith:(NSString *)name {
  927. [XSNetwork showHudSuccess:name];
  928. }
  929. @end