XenonSDK.m 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232
  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. //XSUser* user1 = [XSDataCenter valueForKey:@"User.current"];
  477. //PS:通过这种方式获取到的user有值不会为空,其他方法获取的值为空,不准确!!!
  478. XSUser *user1 = self.user;
  479. //未注册,
  480. if (user1.uid.length == 0) {
  481. __weak __typeof(self) ws = self;
  482. [XSNetwork loginWithComplete:^(id object, NSError *error) {
  483. if (error != nil) {
  484. [XSNetwork showHudFailure:error];
  485. complete(nil, error);
  486. return;
  487. }
  488. [ws setUser:object];
  489. XenonSDK.sharedSDK.user = object;
  490. [XSNetwork showHudSuccess:@"登录成功!"];
  491. complete(object,nil);
  492. }];
  493. }else{
  494. //
  495. XenonSDK.sharedSDK.token = user1.token;
  496. __weak __typeof(self) ws = self;
  497. [XSNetwork authWithUser:user1.uid complete:^(XSUser* object, NSError *error) {
  498. if (error != nil && ![error.domain isEqual:@"XSNetwork"]) {
  499. [XSNetwork showHudFailure:error];
  500. complete(nil,[XSNetwork errorWithCode:-1 message:error.domain]);
  501. return;
  502. }
  503. [XSNetwork showHudSuccess:@"登录成功!"];
  504. if (user1.token.length != 0 && error == nil) {
  505. // Update user info.
  506. user1.token = object.token;
  507. user1.isRegister = NO;
  508. XenonSDK.sharedSDK.user = user1;
  509. [ws setUser:user1];
  510. complete(user1,nil);
  511. }
  512. }];
  513. }
  514. }
  515. // MARK: -检查版本更新
  516. - (void)sdk_checkVersion:(void(^)(void))complete {
  517. // If no configuration file is provided, initialization failed.
  518. if (self.configuration == nil) {
  519. complete();
  520. return;
  521. }
  522. // If update cheker is not enabled, ignore it.
  523. NSURL* url = [NSURL URLWithString:self.configuration.updateUrl];
  524. if (url == nil || self.configuration.updateState == 0) {
  525. complete();
  526. return;
  527. }
  528. // If the prompt is too frequent, wait.
  529. // 1 is normal update.
  530. if (self.configuration.updateState == 1 && !([XSDataCenter doubleForKey:@"verion-later"] < NSDate.new.timeIntervalSince1970)) {
  531. complete();
  532. return;
  533. }
  534. NoticeViewController* viewController = NoticeViewController.new;
  535. // Set the update title & contents.
  536. viewController.title = @"发现新版本";
  537. viewController.contents = [NSString stringWithFormat:@"亲爱的玩家您好,我们发布了新的版本, 更新到新版本可体验更多新奇有趣的玩法!\n\n最新版本: %@\n当前版本: %@\n\n\n", self.configuration.updateVersion, self.shortVersion];
  538. // Set the confirm closure.
  539. [viewController addActionWithName:@"立即升级" handler:^{
  540. // -[UIApplication openURL:]
  541. ((void(*)(id,SEL,id))objc_msgSend)(UIApplication.sharedApplication, NSSelectorFromString(fqsd(@"p2cAAMrAyrKwq5rIAA==")), url);
  542. }];
  543. // Set the cancel closure.
  544. if (self.configuration.updateState == 1) {
  545. __weak __typeof(self) ws = self;
  546. [viewController addActionWithName:@"稍后再说" handler:^{
  547. // Again 24 hours later.
  548. [XSDataCenter setDouble:[NSDate dateWithTimeIntervalSinceNow:24*60*60].timeIntervalSince1970 forKey:@"verion-later"];
  549. if (ws.rootViewController == nil) {
  550. complete();
  551. return;
  552. }
  553. // Automatic hidden controller.
  554. [ws.rootViewController dismissViewControllerAnimated:YES completion:complete];
  555. }];
  556. }
  557. // Show view contorller in key window.
  558. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  559. self.rootViewController = [[RootViewController alloc] initWithRootViewController:viewController];
  560. });
  561. }
  562. - (void)sdk_checkNote:(void(^)(void))complete {
  563. // If no configuration file is provided, initialization failed.
  564. NSURL* url = [NSURL URLWithString:self.configuration.closeUrl];
  565. if (url == nil || self.configuration.linkQq == 0) {
  566. complete();
  567. return ;
  568. }
  569. // If the announcement is displayed, it is no longer displayed.
  570. if (self.configuration.linkQq != 2 && [[XSDataCenter stringForKey:@"notice-later"] isEqualToString:url.absoluteString]) {
  571. complete();
  572. return;
  573. }
  574. NoticeViewController* viewController = NoticeViewController.new;
  575. // Set the update title & contents.
  576. viewController.title = @"系统公告";
  577. viewController.contents = url;
  578. // Set the confirm closure.
  579. __weak __typeof(self) ws = self;
  580. [viewController addActionWithName:@"我知道了" handler:^{
  581. // Never again.
  582. [XSDataCenter setString:url.absoluteString forKey:@"notice-later"];
  583. if (ws.rootViewController == nil) {
  584. complete();
  585. return;
  586. }
  587. // Automatic hidden controller.
  588. [ws.rootViewController dismissViewControllerAnimated:YES completion:complete];
  589. }];
  590. // Show view contorller in key window.
  591. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  592. self.rootViewController = [[RootViewController alloc] initWithRootViewController:viewController];
  593. });
  594. }
  595. - (void)sdk_checkPhone:(void(^)(void))complete {
  596. // Check if the phone character exists.
  597. if (self.user.isRegister || self.user.phone.length != 0 || self.configuration.serverStatus == 1) {
  598. complete();
  599. return;
  600. }
  601. // If the prompt is too frequent, wait.
  602. id key = [NSString stringWithFormat:@"%@-bind-later", self.user.uid];
  603. if ([XSDataCenter doubleForKey:key] > NSDate.new.timeIntervalSince1970) {
  604. complete();
  605. return;
  606. }
  607. UserBindPhoneViewController* bindViewController = UserBindPhoneViewController.new;
  608. RootViewController* rooViewController = [[RootViewController alloc] initWithRootViewController:bindViewController];
  609. UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"您的帐号存在风险, 为了您的帐号安全建议您绑定手机号。" preferredStyle:UIAlertControllerStyleAlert];
  610. // Add confirm action.
  611. [alert addAction:[UIAlertAction actionWithTitle:@"绑定手机" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
  612. bindViewController.callback = complete;
  613. self.rootViewController = rooViewController;
  614. }]];
  615. // Add cancel action.
  616. [alert addAction:[UIAlertAction actionWithTitle:@"稍后提醒" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  617. // Again 24 hours later.
  618. [XSDataCenter setDouble:[NSDate dateWithTimeIntervalSinceNow:24*60*60].timeIntervalSince1970 forKey:key];
  619. // Continue.
  620. complete();
  621. }]];
  622. (void)rooViewController.view; // preload;
  623. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  624. self.rootViewController = alert;
  625. });
  626. // Hide all hud if needed.
  627. [XSNetwork hideHud];
  628. }
  629. ///check In-app Purchase lost list.
  630. - (void)checkOrderStatus {
  631. //检查内购掉单.
  632. [KDIAPManager checkOrderStatus];
  633. }
  634. // MARK: -
  635. - (void)setUser:(XSUser *)user {
  636. _user = user;
  637. _token = user.token;
  638. // Cache.
  639. [XSDataCenter setValue:user forKey:@"User.current"];
  640. if (user == nil) {
  641. return;
  642. }
  643. // Make a new login history.
  644. NSMutableSet* ids = [NSMutableSet set];
  645. NSMutableArray* history = [NSMutableArray array];
  646. user.lastTime = NSDate.new.timeIntervalSince1970;
  647. [ids addObject:user.uid];
  648. [history addObject:user];
  649. for (XSUser* tmp in XSUser.history) {
  650. if (![ids containsObject:tmp.uid]) {
  651. [ids addObject:tmp.uid];
  652. [history addObject:tmp];
  653. }
  654. }
  655. XSUser.history = history;
  656. }
  657. - (XSUser*)user {
  658. if (_user != nil) {
  659. return _user;
  660. }
  661. static dispatch_once_t onceToken;
  662. dispatch_once(&onceToken, ^{
  663. self->_user = [XSDataCenter valueForKey:@"User.current"];
  664. self->_token = self->_user.token;
  665. });
  666. return _user;
  667. }
  668. - (void)setRootViewController:(UIViewController *)rootViewController {
  669. _rootViewController = rootViewController;
  670. if (rootViewController == nil) {
  671. return;
  672. }
  673. [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:rootViewController
  674. animated:YES
  675. completion:nil];
  676. }
  677. /// Permanent preservation of data.
  678. - (void)setPermanentValue:(NSString*)value forKey:(NSString*)key {
  679. // Set value to user defautls.
  680. [XSDataCenter setString:value forKey:key];
  681. // Configure the search setting.
  682. id setting = @{
  683. // Configure the keychain key type.
  684. CFBridgingRelease(kSecClass): CFBridgingRelease(kSecClassGenericPassword),
  685. CFBridgingRelease(kSecAttrAccount): key
  686. }.mutableCopy;
  687. // Delete old item before add new item
  688. SecItemDelete(CFBridgingRetain(setting));
  689. // Add new object to search dictionary.
  690. [setting setObject:[value dataUsingEncoding:NSUTF8StringEncoding] forKey:CFBridgingRelease(kSecValueData)];
  691. // Add item to keychain with the search dictionary
  692. SecItemAdd(CFBridgingRetain(setting), nil);
  693. }
  694. /// Read data for permanent preservationed.
  695. - (id)permanentValueForKey:(NSString*)key {
  696. // Read data from user defatuls.
  697. NSString* udid = [XSDataCenter stringForKey:key];
  698. if (udid.length != 0) {
  699. return udid;
  700. }
  701. // Configure the search setting.
  702. id setting = @{
  703. // Configure the keychain key type.
  704. CFBridgingRelease(kSecClass): CFBridgingRelease(kSecClassGenericPassword),
  705. // The class name of the SDK is dynamic.
  706. CFBridgingRelease(kSecAttrService): NSStringFromClass(self.class),
  707. CFBridgingRelease(kSecAttrAccount): key,
  708. // Gets result data of data.
  709. CFBridgingRelease(kSecReturnData): CFBridgingRelease(kCFBooleanTrue)
  710. };
  711. // Start query the keychain query.
  712. CFTypeRef result = nil;
  713. if (SecItemCopyMatching(CFBridgingRetain(setting), &result) == noErr) {
  714. return nil;
  715. }
  716. // Convert data to a string
  717. NSString* value = [[NSString alloc] initWithData:CFBridgingRelease(result) encoding:NSUTF8StringEncoding];
  718. if (value.length == 0) {
  719. return nil;
  720. }
  721. // Set value to user defautls, reduce Keychain access count.
  722. [XSDataCenter setString:value forKey:key];
  723. return value;
  724. }
  725. - (NSString*)advertisingIdentifier {
  726. // Read the data from keychain.
  727. NSString* advertisingIdentifier = [self permanentValueForKey:@"udid"];
  728. if (advertisingIdentifier.length != 0) {
  729. return advertisingIdentifier;
  730. }
  731. #if SDK_HAS_IDFA
  732. // Try to obtain idfa.
  733. ASIdentifierManager* advertisingManager = ASIdentifierManager.sharedManager;
  734. advertisingIdentifier = advertisingManager.advertisingIdentifier.UUIDString;
  735. if (!advertisingManager.isAdvertisingTrackingEnabled) {
  736. advertisingIdentifier = [NSString stringWithFormat:@"#%@", NSUUID.new.UUIDString];
  737. }
  738. #else
  739. // Generate an id to replace idfa.
  740. advertisingIdentifier = [NSString stringWithFormat:@"#%@", NSUUID.new.UUIDString];
  741. #endif
  742. // Save to keychain to prevent updates.
  743. [self setPermanentValue:advertisingIdentifier forKey:@"udid"];
  744. return advertisingIdentifier;
  745. }
  746. - (NSString*)advertisingVendor {
  747. // This parameter has been deprecated and must be empty string.
  748. return @"";
  749. }
  750. - (NSBundle*)bundle {
  751. return [NSBundle bundleForClass:self.class];
  752. }
  753. - (NSString*)model {
  754. struct utsname sinfo;
  755. uname(&sinfo);
  756. return [NSString stringWithUTF8String: sinfo.machine];
  757. }
  758. /// The sdk verions.
  759. - (NSString*)version {
  760. return self.bundle.infoDictionary[@"CFBundleShortVersionString"] ?: @"1.0";
  761. }
  762. /// The game verions.
  763. - (NSString*)shortVersion {
  764. return NSBundle.mainBundle.infoDictionary[@"CFBundleShortVersionString"] ?: @"1.0";
  765. }
  766. ///TalkingData 游戏运营统计
  767. - (void)TDGameOperationsinitWithAppID:(NSString *)appid ChannelId:(NSString *)channelId {
  768. if (appid.length == 0) {
  769. NSLog(@"TalkingData 游戏运营统计: appid为空!");
  770. return;
  771. }
  772. if (channelId) {
  773. NSLog(@"TalkingData 游戏运营统计: channelId为空!");
  774. }
  775. [TalkingDataGA onStart:appid withChannelId:channelId];
  776. }
  777. -(void)TDregisterWithAccount:(NSString *)account name:(NSString *)name {
  778. [[XSCollector sharedManager] registerWithAccount:account name:name];
  779. }
  780. -(void)TDloginWithAccount:(NSString *)account name:(NSString *)name {
  781. [[XSCollector sharedManager] loginWithAccount:account name:name];
  782. }
  783. -(void)TDreportWithAccount:(NSString*)account Name:(NSString *)name Age:(int)age Gender:(NSInteger)gender {
  784. [[XSCollector sharedManager] reportWithAccount:account name:name age:age gender:gender];
  785. }
  786. -(void)TDreportWithAccount:(NSString*)account name:(NSString*)name level:(NSInteger)level server:(NSString*)server {
  787. [[XSCollector sharedManager] reportWithAccount:account name:name level:level server:server];
  788. }
  789. -(void)TDonChargeRequst:(NSString *)orderId iapId:(NSString *)iapId currencyAmount:(double)currencyAmount currencyType:(NSString *)currencyType virtualCurrencyAmount:(double)virtualCurrencyAmount paymentType:(NSString *)paymentType {
  790. [[XSCollector sharedManager] onChargeRequst:orderId iapId:iapId currencyAmount:currencyAmount currencyType:currencyType virtualCurrencyAmount:virtualCurrencyAmount paymentType:paymentType];
  791. }
  792. - (void)TDonChargeSuccess:(NSString *)orderId {
  793. [[XSCollector sharedManager] onChargeSuccess:orderId];
  794. }
  795. //TD 自定义事件
  796. -(void)TDonEvent:(NSString *)eventId eventData:(id)parm {
  797. [[XSCollector sharedManager] onEvent:eventId eventData:parm];
  798. }
  799. - (void)TDAnalyticsinitWithAppID:(NSString *)appid ChannelId:(NSString *)channelId backgroundSession:(BOOL)flag {
  800. if (appid.length == 0 ) {
  801. NSLog(@"【TalkingData】,error=App ID参数为nil");
  802. return;
  803. }
  804. if (channelId.length == 0) {
  805. NSLog(@"【TalkingData】,error=渠道 ID参数为nil");
  806. }
  807. if (flag) {
  808. [TalkingData backgroundSessionEnabled]; //获取后台使用时长
  809. }
  810. [TalkingData sessionStarted:appid withChannelId:channelId]; //init
  811. [TalkingData setExceptionReportEnabled:YES]; //自动获取异常信息
  812. [TalkingData setSignalReportEnabled:YES]; //自动获取异常信号
  813. }
  814. -(void)TDAnalyticsTrackPageBegin:(NSString *)pageName {
  815. [TalkingData trackPageBegin:pageName];
  816. }
  817. -(void)TDAnalyticsTrackPageEnd:(NSString *)pageName {
  818. [TalkingData trackPageEnd:pageName];
  819. }
  820. //自定义事件1
  821. - (void)TDAnalyticsTrackEvent:(NSString *)eventID {
  822. [TalkingData trackEvent:eventID];
  823. }
  824. //自定义事件2
  825. - (void)TDAnalyticsTrackEvent:(NSString *)eventID label:(NSString *)event_label {
  826. [TalkingData trackEvent:eventID label:event_label];
  827. }
  828. //自定义事件3,eventID:自定义事件名称, event_label:自定义事件Label,用来区分具体场景. dict:自定义事件的参数及参数取值.
  829. - (void)TDAnalyticsTrackEvent:(NSString *)eventID label:(NSString *)event_label parameters:(NSDictionary *)dict {
  830. [TalkingData trackEvent:eventID label:event_label parameters:dict];
  831. }
  832. //orderId:订单ID total:订单总金额,货币单位为分 currencyType:货币种类,eg:人民币 CNY;美元 USD;欧元 EUR
  833. -(TalkingDataOrder *)TDAnalyticsCreateOrder:(NSString *)orderId total:(int)total currencyType:(NSString *)currencyType {
  834. TalkingDataOrder *order = [TalkingDataOrder createOrder:orderId total:total currencyType:currencyType];
  835. return order;
  836. }
  837. //应用内支付-添加订单详情.order为创建的订单
  838. - (void)TDAnalyticsWith:(TalkingDataOrder *)order AddItem:(NSString *)itemId category:(NSString *)category name:(NSString *)name unitPrice:(int)unitPrice amount:(int)amount {
  839. [order addItem:itemId category:category name:name unitPrice:unitPrice amount:amount];
  840. }
  841. //应用内支付-成功支付订单
  842. - (void)TDAnalyticsOnPlaceOrder:(NSString *)profileID order:(TalkingDataOrder *)order {
  843. [TalkingData onPlaceOrder:profileID order:order];
  844. }
  845. ///穿山甲广告Ad
  846. //1.init
  847. - (void)CSJAdSDKinit {
  848. [MLAdManager sharedInstance];
  849. }
  850. //优量汇广告Ad-init
  851. -(void)YLHAdSDKinit {
  852. [YLHAdManager sharedInstance];
  853. }
  854. //TopOn广告Ad-init
  855. -(void)TopOnAdSDKinit {
  856. [TOPONAdManager sharedInstance];
  857. }
  858. //2.打开全屏广告
  859. -(void)openBUDFullScreenVideoAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  860. [[MLAdManager sharedInstance] openFullScreenVideoAd:adName callback:callback];
  861. }
  862. //打开新插屏广告(新增)
  863. -(void)openBUDNewInterstitialAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  864. [[MLAdManager sharedInstance] openNewInterstitialAd:adName callback:callback];
  865. }
  866. //2.打开开屏广告
  867. -(void)openBUDSplashAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  868. [[MLAdManager sharedInstance] openSplashAd:adName callback:callback];
  869. }
  870. //3. 打开插屏广告
  871. -(void)openBUDInterstitialAd:(NSString *)adName width:(CGFloat)w Height:(CGFloat)h callback:(void (^)(BOOL))callback {
  872. [[MLAdManager sharedInstance] openExpressInterstitialAd:adName Width:w Height:h callback:callback];
  873. }
  874. //4. 打开视频激励广告
  875. -(void)openBUDExpressRewardedVideoAd:(NSString *)adName callback:(void (^)(BOOL,BOOL))callback {
  876. [[MLAdManager sharedInstance] openExpressRewardedVideoAd:adName callback:callback];
  877. }
  878. //5. 打开原生Banner广告
  879. -(void)openBUDNativeBannerAd:(NSString *)adName WithX:(CGFloat)x Y:(CGFloat)y Width:(CGFloat)w Height:(CGFloat)h callback:(void (^)(BOOL))callback {
  880. [[MLAdManager sharedInstance] openNativeExpressBannerAd:adName WithX:x Y:y Width:w Height:h callback:callback];
  881. }
  882. //6. 打开原生广告
  883. -(void)openBUDNativeAd:(NSString *)adName WidthCGRect:(CGRect)rect BUSize:(NSInteger)size callback:(void (^)(BOOL))callback {
  884. [[MLAdManager sharedInstance] openNativeAd:adName WidthCGRect:rect BUSize:size callback:callback];
  885. }
  886. //5.2 关闭Banner广告
  887. -(void)closeBUDBannerAd:(NSString *)adName {
  888. [[MLAdManager sharedInstance] closeBannerAd:adName];
  889. }
  890. //优量汇广告
  891. //init
  892. -(void)openYLHSplashAd:(NSString *)adName supportZoomoutView:(BOOL)flag callback:(void (^)(BOOL))callback {
  893. [[YLHAdManager sharedInstance] openSplashAd:adName supportZoomoutView:flag callback:callback];
  894. }
  895. -(void)openYLHInterstitialAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  896. [[YLHAdManager sharedInstance] openExpressInterstitialAd:adName callback:callback];
  897. }
  898. -(void)openYLHFullScreenAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  899. [[YLHAdManager sharedInstance] openFullScreenVideoAd:adName callback:callback];
  900. }
  901. -(void)openYLHExpressRewardedVideoAd:(NSString *)adName callback:(void (^)(BOOL, BOOL))callback {
  902. [[YLHAdManager sharedInstance] openExpressRewardedVideoAd:adName callback:callback];
  903. }
  904. //4.5 打开横幅广告
  905. -(void)openYLHExpressBannerAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  906. [[YLHAdManager sharedInstance] openExpressBannerVideoAd:adName callback:callback];
  907. }
  908. //4.6 打开原生广告
  909. -(void)openYLHExpressNativeAdWithPlacementId:(NSString *)placementId AdName:(NSString *)adName Frame:(CGRect)rect callback:(void (^)(BOOL))callback {
  910. [[YLHAdManager sharedInstance] openExpressNativeAdWithPlacementId:placementId AdName:adName Frame:rect callback:callback];
  911. }
  912. -(void)openTOPONSplashAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  913. [[TOPONAdManager sharedInstance] opensplashAd:adName callback:callback];
  914. }
  915. -(void)openTOPONInterstitialAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  916. [[TOPONAdManager sharedInstance] openInterstitialAd:adName callback:callback];
  917. }
  918. -(void)openTOPONRewardedVideoAd:(NSString *)adName callback:(void (^)(BOOL,BOOL))callback {
  919. [[TOPONAdManager sharedInstance] openRewardedVideoAd:adName callback:callback];
  920. }
  921. -(void)openTOPONExpressBannerAd:(NSString *)adName callback:(void (^)(BOOL))callback {
  922. [[TOPONAdManager sharedInstance] openExpressBannerAd:adName callback:callback];
  923. }
  924. -(void)openTOPONNativeAdWithX:(int)x Y:(int)y width:(int)w height:(int)h adId:(NSString *)adName callback:(void (^)(BOOL))callback {
  925. [[TOPONAdManager sharedInstance] openNativeAdWithX:x Y:y width:w height:h adId:adName callback:callback];
  926. }
  927. -(void)showHudWith:(NSString *)name {
  928. [XSNetwork showHudSuccess:name];
  929. }
  930. @end