XSNetwork.m 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  1. //
  2. // XSNetwork.m
  3. // XenonSDK
  4. //
  5. // Created by SAGESSE on 2019/5/28.
  6. // Copyright © 2019 SAGESSE. All rights reserved.
  7. //
  8. #import "XenonSDK.h"
  9. #import "JSONModel.h"
  10. #import "XSTracker.h"
  11. #import "XSUtils.h"
  12. #import "MBProgressHUD.h"
  13. #import <StoreKit/StoreKit.h>
  14. #import <FBSDKCoreKit/FBSDKCoreKit.h>
  15. #if SDK_HAS_IAP_PAYMENT
  16. //#import "IAPAgnet.h"
  17. #import "KDIAPManager.h"
  18. #endif
  19. @interface XSNetwork ()
  20. @end
  21. @implementation XSNetwork
  22. dispatch_semaphore_t sdk_net_semaphore;
  23. dispatch_queue_t sdk_net_waiting;
  24. NSInteger sdk_net_count;
  25. NSString* sdk_net_baseURL;
  26. MBProgressHUD* sdk_net_hud;
  27. + (NSString*)baseURL {
  28. return sdk_net_baseURL;
  29. }
  30. + (void)setBaseURL:(NSString *)baseURL {
  31. sdk_net_baseURL = baseURL;
  32. }
  33. + (NSError*)errorWithCode:(NSInteger)code message:(NSString*)message {
  34. return [NSError errorWithDomain:@"XSNetwork"
  35. code:code
  36. userInfo:@{NSLocalizedDescriptionKey:message}];
  37. }
  38. + (void)showHudLoading {
  39. [sdk_net_hud removeFromSuperview];
  40. sdk_net_hud = [MBProgressHUD showHUDAddedTo:UIApplication.sharedApplication.keyWindow animated:YES];
  41. sdk_net_hud.labelText = nil;
  42. sdk_net_hud.removeFromSuperViewOnHide = YES;
  43. [sdk_net_hud layoutIfNeeded];
  44. [sdk_net_hud show:YES];
  45. }
  46. + (void)showHudSuccess:(id)error {
  47. [sdk_net_hud removeFromSuperview];
  48. sdk_net_hud = [MBProgressHUD showHUDAddedTo:UIApplication.sharedApplication.keyWindow animated:YES];
  49. sdk_net_hud.detailsLabelText = error;
  50. sdk_net_hud.userInteractionEnabled = NO;
  51. sdk_net_hud.mode = MBProgressHUDModeText;
  52. //hud?.customView = UIImageView(image: UIImage(named: "success", in: nil, compatibleWith: nil))
  53. sdk_net_hud.removeFromSuperViewOnHide = YES;
  54. [sdk_net_hud hide:YES afterDelay:1.8];
  55. }
  56. + (void)showHudFailure:(id)error {
  57. NSString* message = error;
  58. if ([error isKindOfClass:NSError.class]) {
  59. message = [error localizedDescription];
  60. }
  61. [sdk_net_hud removeFromSuperview];
  62. sdk_net_hud = [MBProgressHUD showHUDAddedTo:UIApplication.sharedApplication.keyWindow animated:YES];
  63. sdk_net_hud.detailsLabelText = message;
  64. sdk_net_hud.userInteractionEnabled = NO;
  65. sdk_net_hud.mode = MBProgressHUDModeText;
  66. //hud?.customView = UIImageView(image: UIImage(named: "error", in: nil, compatibleWith: nil))
  67. sdk_net_hud.removeFromSuperViewOnHide = YES;
  68. [sdk_net_hud layoutIfNeeded];
  69. [sdk_net_hud hide:YES afterDelay:2];
  70. }
  71. + (void)hideHud {
  72. [sdk_net_hud removeFromSuperview];
  73. }
  74. + (void)showPrompt:(NSString*)user {
  75. // If no user information is provided, it is turned off by default.
  76. if (user.length == 0) {
  77. [self showHudSuccess:@"登录成功"];
  78. return;
  79. }
  80. // Hide the hud first to prevent errors.
  81. [self hideHud];
  82. UIWindow* window = UIApplication.sharedApplication.keyWindow;
  83. UIView* view = [[UIView alloc] initWithFrame:window.bounds];
  84. UIToolbar* prompt = [[UIToolbar alloc] init];
  85. UILabel* label = [[UILabel alloc] init];
  86. // A tag must be set and the view hierarchy needs to be reset when adding a hover window.
  87. view.tag = -1;
  88. view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  89. // Additional actions are allowed during the hud pop-up.
  90. view.userInteractionEnabled = NO;
  91. NSMutableAttributedString* value = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"欢迎 %@ 加入游戏", user]];
  92. [value addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:0 green:0.48 blue:1 alpha:1] range:NSMakeRange(2, user.length + 2)];
  93. label.attributedText = value;
  94. label.textAlignment = NSTextAlignmentCenter;
  95. label.numberOfLines = 0;
  96. label.font = [UIFont systemFontOfSize:14];
  97. CGSize size = [label sizeThatFits:CGSizeMake(window.frame.size.width - 80, 0)];
  98. CGFloat width = fmax(size.width + 32, 120);
  99. CGFloat height = fmax(size.height + 16, 32);
  100. CGFloat sp = 8;
  101. if (UIApplication.sharedApplication.statusBarFrame.size.height < 20) {
  102. sp += 16;
  103. }
  104. CGFloat top = UIApplication.sharedApplication.statusBarFrame.size.height + sp;
  105. if (@available(iOS 11.0, *)) {
  106. top = window.safeAreaInsets.top + sp;
  107. }
  108. prompt.layer.cornerRadius = 8;
  109. prompt.layer.masksToBounds = YES;
  110. prompt.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
  111. prompt.frame = CGRectMake((window.frame.size.width - width) / 2, top, width, height);
  112. label.frame = prompt.bounds;
  113. // [prompt addSubview:label];
  114. // [view addSubview:prompt];
  115. // [window addSubview:view];
  116. prompt.transform = CGAffineTransformMakeTranslation(0, -CGRectGetMaxY(prompt.frame));
  117. [UIView animateWithDuration:0.25 animations:^{
  118. prompt.transform = CGAffineTransformIdentity;
  119. } completion:^(BOOL t) {
  120. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  121. [UIView animateWithDuration:0.25 animations:^{
  122. prompt.transform = CGAffineTransformMakeTranslation(0, -CGRectGetMaxY(prompt.frame));
  123. } completion:^(BOOL x) {
  124. [view removeFromSuperview];
  125. }];
  126. });
  127. }];
  128. }
  129. + (NSData*)encryptWithParameters:(NSData*)data forKey:(NSString*)key {
  130. #if SDK_HAS_PROTECT_NETWORK_ENCRYPT
  131. if (data != nil) {
  132. NSString* dkey = sdk_md5(key);
  133. NSData* ddata = sdk_encrypt(data, [dkey substringFromIndex:dkey.length - 8]);
  134. return [ddata base64EncodedDataWithOptions:0];
  135. }
  136. #endif
  137. return data;
  138. }
  139. + (NSData*)decryptWithParameters:(NSData*)data forKey:(NSString*)key {
  140. #if SDK_HAS_PROTECT_NETWORK_ENCRYPT
  141. if (data != nil) {
  142. NSString* dkey = sdk_md5(key);
  143. NSData* ddata = [[NSData alloc] initWithBase64EncodedData:data options:0];
  144. return sdk_decrypt(ddata, [dkey substringFromIndex:dkey.length - 8]);
  145. }
  146. #endif
  147. return data;
  148. }
  149. + (NSDictionary*)bodyWithParameters:(id)parameters {
  150. // Generate request header parameters.
  151. NSString* timestamp = @((NSInteger)(NSDate.new.timeIntervalSince1970 * 1000)).stringValue;
  152. NSDictionary* header = @{
  153. @"appId": XenonSDK.sharedSDK.appId ?: @"",
  154. @"channelId": XenonSDK.sharedSDK.channelId ?: @"",
  155. @"adId": XenonSDK.sharedSDK.adId ?: @"",
  156. @"adFlag": XenonSDK.sharedSDK.adFlag ?: @"",
  157. @"sdkVersion": XenonSDK.sharedSDK.version,
  158. @"gameVersion": XenonSDK.sharedSDK.shortVersion,
  159. @"timestamp": timestamp,
  160. @"token": XenonSDK.sharedSDK.token ?: @"",
  161. @"osInfo": [NSString stringWithFormat:@"iOS%@", UIDevice.currentDevice.systemVersion],
  162. @"osType": @"2",
  163. @"idfa": XenonSDK.sharedSDK.advertisingIdentifier,
  164. @"idfv": XenonSDK.sharedSDK.advertisingVendor,
  165. @"model": XenonSDK.sharedSDK.model,
  166. @"wifi": @"Not Found", /*Network.state.SSID ?? */
  167. @"networkType": @"2", // 1 is wifi, 2 is other. /*Network.state.isWifi ? "1" : */
  168. @"tdid": XSCollector.shared.identifer ?: @"",
  169. @"trackData": @"",
  170. //
  171. @"requestIp": @"",
  172. @"imei": @"",
  173. @"mac": @"",
  174. @"androidid": @"",
  175. @"verificationCode": sdk_signature(parameters, timestamp)
  176. };
  177. // Generate results, or add parameters dynamically.
  178. id result = @{
  179. @"head": header,
  180. @"body": parameters
  181. }.mutableCopy;
  182. // When the network needs encryption, 1-12 parameters are generated randomly in order to scramble the ciphertext length.
  183. #if SDK_HAS_PROTECT_NETWORK_ENCRYPT
  184. NSMutableArray* arr = [NSMutableArray new];
  185. for (int i = arc4random() % 12; i > 0; --i) {
  186. [arr addObject: sdk_md5([NSString stringWithFormat:@"%zu", (NSUInteger)arc4random()])];
  187. }
  188. [result setObject:arr forKey:@"other"];
  189. #endif
  190. return result;
  191. }
  192. + (void)busy {
  193. dispatch_async(dispatch_get_main_queue(), ^{
  194. sdk_net_count += 1;
  195. if (sdk_net_count == 1) {
  196. UIApplication.sharedApplication.networkActivityIndicatorVisible = YES;
  197. }
  198. });
  199. }
  200. + (void)idle {
  201. dispatch_async(dispatch_get_main_queue(), ^{
  202. if (sdk_net_count == 0) {
  203. return;
  204. }
  205. sdk_net_count = sdk_net_count - 1;
  206. if (sdk_net_count == 0) {
  207. UIApplication.sharedApplication.networkActivityIndicatorVisible = NO;
  208. }
  209. });
  210. }
  211. /// Suspended all network requests.
  212. + (void)suspend {
  213. if (sdk_net_waiting != nil) {
  214. return;
  215. }
  216. sdk_net_waiting = dispatch_queue_create("XSNetwork", 0);
  217. sdk_net_semaphore = dispatch_semaphore_create(0);
  218. dispatch_async(sdk_net_waiting, ^{
  219. // Lock the thread.
  220. dispatch_semaphore_wait(sdk_net_semaphore, DISPATCH_TIME_FOREVER);
  221. });
  222. }
  223. /// Resume all network requests.
  224. + (void)resume {
  225. if (sdk_net_waiting == nil) {
  226. return;
  227. }
  228. sdk_net_waiting = nil;
  229. dispatch_semaphore_signal(sdk_net_semaphore);
  230. sdk_net_semaphore = nil;
  231. }
  232. /// Send a request(maybe suspend).
  233. + (void)requestWithURL:(id)url parameters:(id)parameters model:(Class)model complete:(void(^)(id obj, NSError* error))complete {
  234. // Need wait from queue?
  235. if (sdk_net_waiting == nil) {
  236. [self requestWithoutSuspend:url parameters:parameters model:model complete:complete];
  237. return;
  238. }
  239. // Enter waiting status.
  240. dispatch_async(sdk_net_waiting, ^{
  241. dispatch_async(dispatch_get_main_queue(), ^{
  242. [self requestWithoutSuspend:url parameters:parameters model:model complete:complete];
  243. });
  244. });
  245. }
  246. /// Send a request.
  247. + (void)requestWithoutSuspend:(id)url parameters:(id)parameters model:(Class)model complete:(void(^)(id obj, NSError* error))complete {
  248. // Generate encryption options.
  249. #if SDK_HAS_PROTECT_NETWORK_ENCRYPT
  250. NSUInteger options = arc4random() | 1;
  251. #else
  252. NSUInteger options = arc4random() & ~1;
  253. #endif
  254. // Convert to URL
  255. NSString* path = [NSString stringWithFormat:@"/data/%@-%@-%@-%zd", XenonSDK.sharedSDK.appId, XenonSDK.sharedSDK.adId, url, options];
  256. NSURL* req = [NSURL URLWithString:path relativeToURL:[NSURL URLWithString: self.baseURL]];
  257. if (req == nil) {
  258. complete(nil, nil);
  259. return;
  260. }
  261. // Generate request & parameters.
  262. NSDictionary* body = [self bodyWithParameters:parameters];
  263. NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:req cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:60];
  264. NSError* serror = nil;
  265. NSData* sdata = [NSJSONSerialization dataWithJSONObject:body options:0 error:&serror];
  266. if (sdata == nil || serror != nil) {
  267. complete(nil, serror);
  268. }
  269. request.HTTPBody = [self encryptWithParameters:sdata forKey:path];
  270. request.HTTPMethod = @"POST";
  271. [request addValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
  272. //#if DEBUG
  273. // NSLog(@"%@ << %@", path, [[NSString alloc] initWithData:sdata encoding:NSUTF8StringEncoding]);
  274. //#endif
  275. // Network start request.
  276. [self busy];
  277. // Send a request to server.
  278. NSURLSessionDataTask* task = [NSURLSession.sharedSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
  279. // Must be calleback in the main thread.
  280. dispatch_async(dispatch_get_main_queue(), ^{
  281. // Network request completed.
  282. [self idle];
  283. // decode data;
  284. NSData* ddata = [self decryptWithParameters:data forKey:path];
  285. NSError* derror = nil;
  286. NSDictionary* djson = nil;
  287. if (ddata) {
  288. djson = [NSJSONSerialization JSONObjectWithData:ddata options:0 error:&derror];
  289. }
  290. // #if DEBUG
  291. // NSLog(@"%@ >> %@", path, error.description ?: [[NSString alloc] initWithData:ddata encoding:NSUTF8StringEncoding]);
  292. // #endif
  293. // If data is nil, the request is failure.
  294. if (data == nil || error != nil || derror != nil) {
  295. // Request failure for system error.
  296. complete(nil, error ?: derror);
  297. return;
  298. }
  299. id header = djson[@"head"];
  300. if ([header[@"responseCode"] integerValue] != 0) {
  301. // Request failure for system error.
  302. NSInteger code = [header[@"responseCode"] integerValue];
  303. NSString* message = header[@"responseMsg"];
  304. complete(nil, [self errorWithCode:code message:message]);
  305. return;
  306. }
  307. // In request success case.
  308. id dbody = djson[@"body"];
  309. id obj = [[model alloc] initWithDictionary:dbody error:&derror];
  310. if (obj == nil && derror == nil) {
  311. obj = dbody;
  312. }
  313. complete(obj , derror);
  314. });
  315. }];
  316. // Start.
  317. [task resume];
  318. }
  319. /// Request systme configure.
  320. + (void)configureWithIdentifier:(NSString*)identifier flags:(NSString*)flags complete:(void(^)(id object, NSError* error))complete {
  321. // Prepare request parameters.
  322. id url = @"0";//"/api/game/v1/active"
  323. id ps = @{
  324. @"adId": identifier,
  325. @"adFlag": flags
  326. };
  327. // Suspend requests for other.
  328. [self suspend];
  329. // Send a request to server.
  330. [self requestWithoutSuspend:url parameters:ps model:XSConfiguration.self complete:^(id obj, NSError *error) {
  331. // Resume requests for other.
  332. [self resume];
  333. // Next.
  334. complete(obj, error);
  335. }];
  336. }
  337. /// Send SMS security code.
  338. + (void)sendSMSWithPhone:(NSString*)phone type:(NSInteger)type complete:(void(^)(id object, NSError* error))complete {
  339. // Prepare request parameters.
  340. id url = @"7";//"/api/sms/v1/send"
  341. id ps = @{
  342. @"phone": phone,
  343. @"sendType": @(type).stringValue // 1 bind, 2 forget, 3 login
  344. };
  345. // Send a request to server.
  346. [self requestWithURL:url parameters:ps model:nil complete:^(id obj, NSError *error) {
  347. complete(nil, error);
  348. }];
  349. }
  350. /// Auth login.
  351. + (void)authWithUser:(NSString*)uid complete:(void(^)(id object, NSError* error))complete {
  352. // Prepare request parameters.
  353. id url = @"1";//"/api/user/v1/checkToken"
  354. id ps = @{
  355. @"uid": uid
  356. };
  357. // Send a request to server.
  358. [self requestWithURL:url parameters:ps model:XSUser.self complete:complete];
  359. }
  360. /// Check user with phone
  361. + (void)checkWithPhone:(NSString*)phone complete:(void(^)(id object, NSError* error))complete {
  362. // Prepare request parameters.
  363. id url = @"5";//"/api/user/v1/checkUserPhone"
  364. id ps = @{
  365. @"phone": phone
  366. };
  367. // Send a request to server.
  368. [self requestWithURL:url parameters:ps model:nil complete:complete];
  369. }
  370. /// Bind user with phone.
  371. + (void)bindWithPhone:(NSString*)phone code:(NSString*)code username:(NSString*)username complete:(void(^)(id object, NSError* error))complete {
  372. // Prepare request parameters.
  373. id url = @"6";//"/api/user/v1/bindPhone"
  374. id ps = @{
  375. @"userName": username,
  376. @"phone": phone,
  377. @"code": code
  378. };
  379. // Send a request to server.
  380. [self requestWithURL:url parameters:ps model:nil complete:complete];
  381. }
  382. /// Reset password.
  383. + (void)resetWithPhone:(NSString*)phone code:(NSString*)code password:(NSString*)password complete:(void(^)(id object, NSError* error))complete {
  384. // Prepare request parameters.
  385. id url = @"4";//"/api/user/v1/forget"
  386. id ps = @{
  387. @"phone": phone,
  388. @"pwd": [sdk_md5(password) uppercaseString],
  389. @"code": code
  390. };
  391. // Send a request to server.
  392. [self requestWithURL:url parameters:ps model:nil complete:complete];
  393. }
  394. /// Fast login a user.
  395. + (void)loginWithComplete:(void(^)(id object, NSError* error))complete {
  396. // Prepare request parameters.
  397. id url = @"2";//"/api/user/v1/register"
  398. id ps = @{
  399. @"userName": @"",
  400. @"pwd": @"",
  401. @"loginType": @"0" // falst login
  402. };
  403. // Send a request to server.
  404. [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
  405. if (user != nil) {
  406. if (user.isRegister) {
  407. [XSCollector.shared registerWithAccount:user.uid name:user.userName];
  408. } else {
  409. [XSCollector.shared loginWithAccount:user.uid name:user.userName];
  410. }
  411. }
  412. complete(user, error);
  413. }];
  414. }
  415. //Facebook login a user
  416. +(void)loginFacebookWithToken:(NSString *)token appId:(NSString *)appid playerId:(NSString *)playerid complete:(void (^)(id, NSError *))complete {
  417. // Prepare request parameters.
  418. id url = @"f";//"/api/third/facebook/v1/login"
  419. id ps = @{
  420. @"idToken": token,
  421. @"appId": appid,
  422. @"playerid": playerid
  423. };
  424. // Send a request to server.
  425. [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
  426. if (user != nil) {
  427. if (user.isRegister) {
  428. [XSCollector.shared registerWithAccount:user.uid name:user.userName];
  429. } else {
  430. [XSCollector.shared loginWithAccount:user.uid name:user.userName];
  431. }
  432. }
  433. complete(user, error);
  434. }];
  435. }
  436. //Facebook bind a user
  437. +(void)bindFacebookWithToken:(NSString *)token appId:(NSString *)appid playerId:(NSString *)playerid complete:(void (^)(id, NSError *))complete {
  438. XSUser* user1 = [XSDataCenter valueForKey:@"User.current"];
  439. // Prepare request parameters.
  440. id url = @"g";//"/api/third/facebook/v1/bind"
  441. id ps = @{
  442. @"idToken": token,
  443. @"appId": appid,
  444. @"playerid": playerid,
  445. @"uid":user1.uid?:@""
  446. };
  447. // Send a request to server.
  448. [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
  449. complete(user, error);
  450. }];
  451. }
  452. /// Apple login a user.
  453. +(void)loginApplekWithToken:(NSString *)token complete:(void (^)(id, NSError *))complete {
  454. // Prepare request parameters.
  455. id url = @"m"; //"/api/third/apple/v1/login"
  456. id ps = @{
  457. @"idToken": token
  458. };
  459. // Send a request to server.
  460. [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
  461. if (user != nil) {
  462. if (user.isRegister) {
  463. [XSCollector.shared registerWithAccount:user.uid name:user.userName];
  464. } else {
  465. [XSCollector.shared loginWithAccount:user.uid name:user.userName];
  466. }
  467. }
  468. complete(user, error);
  469. }];
  470. }
  471. /// Phone & Security Code login a user.
  472. + (void)loginWithPhone:(NSString*)phone code:(NSString*)code complete:(void(^)(id object, NSError* error))complete {
  473. // Prepare request parameters.
  474. id url = @"3";//"/api/user/v1/login"
  475. id ps = @{
  476. @"userName": phone,
  477. @"pwd": code,
  478. @"loginType": @"3" // Phone & Security Code login
  479. };
  480. // Send a request to server.
  481. [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
  482. user.account = phone;
  483. user.pwd = nil;
  484. if (user != nil) {
  485. if (user.isRegister) {
  486. [XSCollector.shared registerWithAccount:user.uid name:user.userName];
  487. } else {
  488. [XSCollector.shared loginWithAccount:user.uid name:user.userName];
  489. }
  490. }
  491. complete(user, error);
  492. }];
  493. }
  494. /// Account & Password login a user.
  495. + (void)loginWithAccount:(NSString*)account password:(NSString*)password complete:(void(^)(id object, NSError* error))complete {
  496. // Prepare request parameters.
  497. id url = @"3";//"/api/user/v1/login"
  498. id ps = @{
  499. @"userName": account,
  500. @"pwd": [sdk_md5(password) uppercaseString],
  501. @"loginType": @"1" // account login
  502. };
  503. // Send a request to server.
  504. [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
  505. user.account = account;
  506. user.pwd = password;
  507. if (user != nil) {
  508. [XSCollector.shared loginWithAccount:user.uid name:user.userName];
  509. }
  510. complete(user, error);
  511. }];
  512. }
  513. /// Account & Password login a user.
  514. + (void)registerWithAccount:(NSString*)account password:(NSString*)password complete:(void(^)(id object, NSError* error))complete {
  515. // Prepare request parameters.
  516. id url = @"2";//"/api/user/v1/register"
  517. id ps = @{
  518. @"userName": account,
  519. @"pwd": [sdk_md5(password) uppercaseString],
  520. @"loginType": @"1" // account login
  521. };
  522. // Send a request to server.
  523. [self requestWithURL:url parameters:ps model:XSUser.self complete:^(XSUser* user, NSError *error) {
  524. user.account = account;
  525. user.pwd = password;
  526. user.isRegister = YES;
  527. if (user != nil) {
  528. [XSCollector.shared registerWithAccount:user.uid name:user.userName];
  529. }
  530. complete(user, error);
  531. }];
  532. }
  533. // MARK - 广告记录
  534. +(void)adRecord:(NSString *)action
  535. spaceId:(NSString *)spaceId
  536. agentName:(NSString *)agentName
  537. medium:(NSString *)medium
  538. adUnitId:(NSString *)adUnitId
  539. type:(NSString *)type
  540. unitAdId:(NSString *)unitAdId
  541. errorMsg:(NSString *)errorMeg{
  542. NSString *uid = [XenonSDK sharedSDK].user.uid;
  543. //广告组ID,在plist文件里配置.
  544. //NSBundle *mainBundle = [NSBundle mainBundle];
  545. //NSString *unitAdId1 = mainBundle.infoDictionary[@"ironsource-app-unitAdId"];
  546. id url = @"e"; //"/api/game/v1/adAction"
  547. id ps = @{
  548. @"action": action,
  549. @"spaceId": spaceId,
  550. @"uid" : uid? uid:@"",
  551. @"agentName" : agentName,
  552. @"medium" : medium,
  553. @"adUnitId" : adUnitId? adUnitId:@"",
  554. @"type" : type,
  555. @"unitAdId" : unitAdId,
  556. @"errmsg" : errorMeg
  557. };
  558. // Send a request to server.
  559. [self requestWithoutSuspend:url parameters:ps model:XSUser.self complete:^(id obj, NSError *error) {
  560. //complete(obj, error);
  561. }];
  562. }
  563. // MARK - Utils
  564. /// Auto trigger;
  565. + (void)trigger:(NSInteger)count {
  566. #if SDK_HAS_PROTECT_NETWORK_PRETEND
  567. // If tracking is not enabled, turn it off.
  568. if (XSTracker.shared == nil) {
  569. return;
  570. }
  571. // Prepare request parameters.
  572. NSString* url = @"*";
  573. NSMutableDictionary* ps = [NSMutableDictionary new];
  574. for (int i = arc4random() % 12 + 1; i > 0; --i) {
  575. id key = [sdk_md5(@(arc4random()).stringValue) substringToIndex:((arc4random() % 14) + 1)];
  576. id value = [[key dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
  577. ps[key] = value;
  578. }
  579. // Send a request to server.
  580. [self requestWithURL:url parameters:ps model:nil complete:^(id obj, NSError *error) {
  581. if (error == nil || count > 0) {
  582. return;
  583. }
  584. NSInteger ft = arc4random() % 10000;
  585. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_MSEC * ft), dispatch_get_main_queue(), ^{
  586. [self trigger:count - 1];
  587. });
  588. }];
  589. #endif
  590. }
  591. + (void)log:(NSInteger)code session:(NSString*)session extra:(NSString*)extra {
  592. // Prepare request parameters.
  593. id url = @"9";//"/api/ardent/v1/add"
  594. id ps = @{
  595. @"digitId": [NSString stringWithFormat:@"0x%06zx", code],
  596. @"sessionId": session,
  597. @"iosStr": extra
  598. };
  599. // Send a request to server.
  600. [self requestWithoutSuspend:url parameters:ps model:nil complete:^(id obj, NSError *error) {
  601. // Nothing.
  602. }];
  603. }
  604. + (void)reportWithUser:(NSString*)uid Name:(NSString*)name level:(NSInteger)level server:(NSString*)server {
  605. // Prepare request parameters.
  606. id url = @"a";//"/api/game/v1/sendServer"
  607. id ps = @{
  608. @"uid": uid ?: @"",
  609. @"gameServerId": server,
  610. @"roleLev": @(level).stringValue,
  611. @"roleName": name
  612. };
  613. // Send a request to server.
  614. [self requestWithURL:url parameters:ps model:nil complete:^(id obj, NSError *error) {
  615. }];
  616. }
  617. /// Get pay route.
  618. + (void)routeWithComplete:(void(^)(id object, NSError* error))complete {
  619. // Prepare request parameters.
  620. id url = @"8";//"/api/p/v1/pCheck"
  621. id ps = @{
  622. @"uid": XenonSDK.sharedSDK.user.uid ?: @""
  623. };
  624. // Send a request to server.
  625. [self requestWithURL:url parameters:ps model:nil complete:complete];
  626. }
  627. #if SDK_HAS_IAP_PAYMENT
  628. /// Pay a product.
  629. + (void)payWithParameters:(id)parameters complete:(void(^)(id object, NSError* error))complete {
  630. // Prepare request parameters.
  631. id url = @"b";//"/api/p/v1/apple/create"
  632. id ps = parameters;
  633. // Check if in-app purchases are available.
  634. if (!SKPaymentQueue.canMakePayments) {
  635. complete(nil, [XSNetwork errorWithCode:-2 message:@"该设备不支持内购"]);
  636. return;
  637. }
  638. // Send a request to server.
  639. [self requestWithURL:url parameters:ps model:nil complete:^(id obj, NSError *error) {
  640. if (error != nil) {
  641. complete(nil, error);
  642. return;
  643. }
  644. // Get prarmeter
  645. NSString* orderId = [obj valueForKeyPath:@"orderId"];
  646. NSString* productId = [obj valueForKeyPath:@"product.productId"];
  647. if (orderId.length == 0 || productId.length == 0) {
  648. complete(nil, [XSNetwork errorWithCode:-2 message:@"服务器异常"]);
  649. return;
  650. }
  651. [[KDIAPManager shareIAPManager] startIAPWithOrderId:orderId productID:productId completeHandle:^(IAPResultType type, NSData *data) {
  652. //complete(nil, [XSNetwork errorWithCode:-2 message:@"购买成功!"]);
  653. if (type == IAPResultSuccess) {
  654. [XSNetwork showHudSuccess:@"购买成功!"];
  655. complete(ps,nil);
  656. }else if (type == IAPResultVerFailed){
  657. [XSNetwork showHudSuccess:@"订单校验失败!"];
  658. }else{
  659. [XSNetwork showHudFailure:@"购买失败!"];
  660. }
  661. }];
  662. }];
  663. }
  664. /// Pay a product with receipt.
  665. + (void)payWithReceipt:(id)receipt orderId:(id)orderId complete:(void(^)(id object, NSError* error))complete {
  666. // Prepare request parameters.
  667. id url = @"c";//"/api/p/v1/apple/p"
  668. id ps = @{
  669. @"data": receipt,
  670. @"orderId": orderId,
  671. @"uid": XenonSDK.sharedSDK.user.uid ?: @""
  672. };
  673. // Send a request to server.
  674. [self requestWithURL:url parameters:ps model:nil complete:complete];
  675. }
  676. #endif
  677. @end