SPSBNetworkManager.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. //
  2. // SPSBNetworkManager.m
  3. // 我的社保
  4. //
  5. // Created by shanp on 2021/4/20.
  6. //
  7. #import "SPSBNetworkManager.h"
  8. #import <AFNetworking.h>
  9. #import <JXHGeneralTools.h>
  10. #import <JXHMacro.h>
  11. #import "SPSBConstantProfile.h"
  12. #import "SPSBKeyProfile.h"
  13. #import "SPSBEnumerationProfile.h"
  14. #import "SPSBBusinessManager.h"
  15. #import <JXHSystemShortcut.h>
  16. #import "SPSBNotificationDelegateManager.h"
  17. #import <SDWebImage.h>
  18. static const NSInteger SPSBTimeOutMinute = 60;
  19. const NSInteger SPSBNetworkCallbackSuccessCode = 200;
  20. const NSInteger SPSBNetworkCallbackNeedLogin = 10004;
  21. const NSInteger SPSBNetworkCallbackKeyInvalid = 601;
  22. typedef void(^SPSBNetworkSuccessBlock)(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject);
  23. typedef void(^SPSBNetworkFailureBlock)(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error);
  24. @interface SPSBUrlDicValue : NSObject
  25. @property (nonatomic, strong) SPSBNetworkManagerCallbackBlock spsb_callbackBlock;
  26. @property (nonatomic, strong, nullable) NSURLSessionTask *spsb_task;
  27. @end
  28. @implementation SPSBUrlDicValue @end
  29. @interface SPSBNetworkManager ()<SPSBNotificationDelegate> {
  30. AFHTTPSessionManager *_manager;
  31. NSInteger _timeOut;//超时标识
  32. bool _isLogin;//60秒循环时判断是否已经登录成功,发起请求是不用做判断
  33. NSMutableDictionary<NSString *, SPSBUrlDicValue *> *_urlDic;//判断重复请求
  34. }
  35. @end
  36. @implementation SPSBNetworkManager
  37. - (instancetype)init {
  38. self = [super init];
  39. if (!self) return nil;
  40. _manager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
  41. _timeOut = 0;
  42. _isLogin = false;
  43. NSString *sysVersion = [[UIDevice currentDevice] systemVersion];
  44. [_manager.requestSerializer setValue:[NSString stringWithFormat:@"iOS%@#%ld", sysVersion, (long)SPSBCurrentVersion] forHTTPHeaderField:@"User-Agent"];
  45. spsb_setNotificationKey(SPSBLoggingNotificationKey);
  46. _urlDic = NSMutableDictionary.new;
  47. return self;
  48. }
  49. - (void)dealloc {
  50. spsb_removeNotificationKey(SPSBLoggingNotificationKey);
  51. }
  52. - (void)networkUseMethod:(SPSBNetworkMethod)method isLogin:(bool)isLogin url:(NSString *)url urlParameters:(nullable NSDictionary *)urlParameters parameters:(nullable NSDictionary *)parameters completion:(SPSBNetworkManagerCallbackBlock)completion {
  53. [self networkUseMethod:method isLogin:isLogin url:url filtrationKey:@"" urlParameters:urlParameters parameters:parameters completion:completion];
  54. }
  55. - (void)networkUseMethod:(SPSBNetworkMethod)method isLogin:(bool)isLogin url:(NSString *)url filtrationKey:(NSString *)filtrationKey urlParameters:(nullable NSDictionary *)urlParameters parameters:(nullable NSDictionary *)parameters completion:(SPSBNetworkManagerCallbackBlock)completion {
  56. NSMutableString *u = [url mutableCopy];
  57. if (urlParameters) {
  58. [urlParameters enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
  59. if (![obj isKindOfClass:[NSString class]]) {
  60. obj = [NSString stringWithFormat:@"%@", obj];
  61. }
  62. [u replaceOccurrencesOfString:[NSString stringWithFormat:@"{%@}", key] withString:obj options:NSLiteralSearch range:NSMakeRange(0, u.length)];
  63. }];
  64. }
  65. debugLog(@"method=>%@----url=>%@----parameters=>%@", @[@"get", @"post", @"put", @"delete"][method], url ,parameters);
  66. NSString *key = [self getDicKeyWithUrl:url filtrationKey:filtrationKey];
  67. SPSBUrlDicValue *value = SPSBUrlDicValue.new;
  68. value.spsb_callbackBlock = completion;
  69. if (_urlDic[key]) {
  70. _urlDic[key] = value;
  71. return;
  72. };
  73. _urlDic[key] = value;
  74. if (isLogin) {
  75. [self networkNeedLoginUseMethod:method url:u parameters:parameters key:key];
  76. } else {
  77. [self networkUseMethod:method url:u parameters:parameters key:key];
  78. }
  79. }
  80. - (void)networkUseMethod:(SPSBNetworkMethod)method url:(NSString *)url parameters:(nullable NSDictionary *)parameters key:(NSString *)key {
  81. @weakify(self)
  82. SPSBNetworkSuccessBlock successBlock = ^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  83. @strongify(self)
  84. if (!self) return;
  85. debugLog(@"url=>%@----response=>%@", url, responseObject);
  86. [self handleCallBackData:responseObject key:key circulationAction:nil];
  87. };
  88. SPSBNetworkFailureBlock failureBlock = ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  89. debugLog(@"url=>%@----error=>%@", url, error);
  90. @strongify(self)
  91. if (!self) return;
  92. if (error.code != -999) {
  93. [self handleFailureWithKey:key message:nil data:nil];
  94. }
  95. };
  96. [self useAFNetworkWithMethod:method url:url key:key parameters:parameters callBackSuccess:successBlock callBacekFail:failureBlock];
  97. }
  98. - (void)networkNeedLoginUseMethod:(SPSBNetworkMethod)method url:(NSString *)url parameters:(nullable NSDictionary *)parameters key:(NSString *)key {
  99. if ([spsb_loginToken() isEqualToString:@""]) {
  100. @weakify(self)
  101. [self circulationWithIsNeedToLoginNotification:false url:url key:key circulationAction:^{
  102. @strongify(self)
  103. [self networkNeedLoginUseMethod:method url:url parameters:parameters key:key];
  104. }];
  105. } else {
  106. @weakify(self)
  107. SPSBNetworkSuccessBlock successBlock = ^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  108. debugLog(@"url=>%@----response=>%@", url, responseObject);
  109. @strongify(self)
  110. if (!self) return;
  111. [self handleCallBackData:responseObject key:key circulationAction:^{
  112. @weakify(self)
  113. [self circulationWithIsNeedToLoginNotification:true url:url key:key circulationAction:^{
  114. @strongify(self)
  115. [self networkNeedLoginUseMethod:method url:url parameters:parameters key:key];
  116. }];
  117. }];
  118. };
  119. SPSBNetworkFailureBlock failureBlock = ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  120. debugLog(@"url=>%@----error=>%@", url, error);
  121. @strongify(self)
  122. if (!self) return;
  123. if (error.code != -999) {
  124. [self handleFailureWithKey:key message:nil data:nil];
  125. }
  126. };
  127. NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:parameters];
  128. [dic setObject:spsb_loginToken() forKey:@"key"];
  129. [self useAFNetworkWithMethod:method url:url key:key parameters:dic callBackSuccess:successBlock callBacekFail:failureBlock];
  130. }
  131. }
  132. - (void)useAFNetworkWithMethod:(SPSBNetworkMethod)method url:(NSString *)url key:(NSString *)key parameters:(nullable NSDictionary *)parameters callBackSuccess:(SPSBNetworkSuccessBlock)successBlock callBacekFail:(SPSBNetworkFailureBlock)failureBlock {
  133. NSURLSessionDataTask *task;
  134. switch (method) {
  135. case SPSBNetworkMethodGET: {
  136. task = [_manager GET:url parameters:parameters headers:@{} progress:nil success:successBlock failure:failureBlock];
  137. }
  138. break;
  139. case SPSBNetworkMethodPOST: {
  140. task = [_manager POST:url parameters:parameters headers:@{} progress:nil success:successBlock failure:failureBlock];
  141. }
  142. break;
  143. case SPSBNetworkMethodPUT: {
  144. task = [_manager PUT:url parameters:parameters headers:@{} success:successBlock failure:failureBlock];
  145. }
  146. break;
  147. case SPSBNetworkMethodDELETE: {
  148. task = [_manager DELETE:url parameters:parameters headers:@{} success:successBlock failure:failureBlock];
  149. }
  150. break;
  151. default:
  152. break;
  153. }
  154. if (_urlDic[key] && task) {
  155. _urlDic[key].spsb_task = task;
  156. }
  157. }
  158. - (void)circulationWithIsNeedToLoginNotification:(bool)flag url:(NSString *)url key:(NSString *)key circulationAction:(void(^_Nullable)(void))circulationAction {
  159. //60秒超时让用户自行选择退出还是继续
  160. debugLog(@"timeout=>%ld", (long)_timeOut);
  161. debugLog(@"networkStatus=>%@", [jxh_userDefaults() objectForKey:SPSBNetworkStatusKey]);
  162. if (_timeOut > SPSBTimeOutMinute || [[jxh_userDefaults() objectForKey:SPSBNetworkStatusKey] unsignedIntegerValue] == SPSBNetworkStatusNo) {
  163. _timeOut = 0;
  164. [self handleFailureWithKey:key message:nil data:nil];
  165. } else {
  166. if (flag) {
  167. spsb_postNotification(SPSBAppStatusNotificationKey, @selector(spsb_appNeedLogin), spsb_appNeedLogin);
  168. }
  169. NSMutableDictionary *dic = [@{@"url": url, @"key": key} mutableCopy];
  170. if (circulationAction) {
  171. dic[@"circulationAction"] = circulationAction;
  172. }
  173. [self performSelector:@selector(waitForLogin:) withObject:dic afterDelay:2.0];
  174. _timeOut += 2;
  175. }
  176. }
  177. - (void)waitForLogin:(NSDictionary *)dic {
  178. if (self && self->_isLogin && dic[@"circulationAction"]) {
  179. ((void(^)(void))dic[@"circulationAction"])();
  180. } else {
  181. [self circulationWithIsNeedToLoginNotification:false url:dic[@"url"] key:dic[@"key"] circulationAction:dic[@"circulationAction"]];
  182. }
  183. }
  184. - (void)handleCallBackData:(id)responseObject key:(NSString *)key circulationAction:(void(^_Nullable)(void))circulationAction {
  185. _timeOut = 0;
  186. if (responseObject) {
  187. NSDictionary *data = [self changeData:responseObject];
  188. if ([data[@"code"] integerValue] == SPSBNetworkCallbackSuccessCode) {
  189. NSError *error = [NSError errorWithDomain:@"成功" code:SPSBNetworkErrorCodeSuccess userInfo:nil];
  190. if (_urlDic[key]) {
  191. _urlDic[key].spsb_callbackBlock(error, data);
  192. [_urlDic removeObjectForKey:key];
  193. }
  194. } else if ([data[@"code"] integerValue] == SPSBNetworkCallbackNeedLogin || [data[@"code"] integerValue] == SPSBNetworkCallbackKeyInvalid) {
  195. _isLogin = false;
  196. //去掉本地token
  197. [jxh_userDefaults() setObject:nil forKey:SPSBToken];
  198. [jxh_userDefaults() synchronize];
  199. if (circulationAction) {
  200. circulationAction();
  201. }
  202. } else {
  203. [self handleFailureWithKey:key message:data[@"msg"] data:data];
  204. }
  205. } else {
  206. [self handleFailureWithKey:key message:nil data:nil];
  207. }
  208. }
  209. - (NSDictionary *)changeData:(NSDictionary *)data {
  210. NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:data];
  211. if (dict[@"msg"] && (jxh_isNullClass(dict[@"msg"]) || [dict[@"msg"] isEqualToString:@""])) {
  212. [dict removeObjectForKey:@"msg"];
  213. }
  214. if (dict[@"data"] && jxh_isNullClass(dict[@"data"])) {
  215. [dict removeObjectForKey:@"data"];
  216. }
  217. return dict;
  218. }
  219. - (void)handleFailureWithKey:(NSString *)key message:(nullable NSString *)message data:(nullable id)data {
  220. NSError *error;
  221. if ([[jxh_userDefaults() objectForKey:SPSBNetworkStatusKey] unsignedIntegerValue] == SPSBNetworkStatusNo) {
  222. error = [NSError errorWithDomain:@"网络连接不稳定" code:SPSBNetworkErrorCodeNetwrokMiss userInfo:nil];
  223. } else if (message) {
  224. error = [NSError errorWithDomain:message code:SPSBNetworkErrorCodeConnectErrorMessage userInfo:nil];
  225. } else {
  226. error = [NSError errorWithDomain:@"" code:SPSBNetworkErrorCodeConnectError userInfo:nil];
  227. }
  228. if (_urlDic[key]) {
  229. _urlDic[key].spsb_callbackBlock(error, data);
  230. [_urlDic removeObjectForKey:key];
  231. }
  232. }
  233. - (NSString *)getDicKeyWithUrl:(NSString *)url filtrationKey:(nonnull NSString *)filtrationKey {
  234. return [NSString stringWithFormat:@"%@%@", url, filtrationKey];
  235. }
  236. - (void)cancelUrl:(NSString *)url filtrationKey:(nonnull NSString *)filtrationKey {
  237. NSString *key = [self getDicKeyWithUrl:url filtrationKey:filtrationKey];
  238. if (_urlDic[key].spsb_task) {
  239. [_urlDic[key].spsb_task cancel];
  240. }
  241. _urlDic[key] = nil;
  242. }
  243. - (void)cancelAll {
  244. [_manager.operationQueue cancelAllOperations];
  245. [_urlDic removeAllObjects];
  246. [NSObject cancelPreviousPerformRequestsWithTarget:self];
  247. }
  248. - (void)networkDownloadImageWithUrl:(NSString *)url key:(NSString *)key completion:(SPSBNetworkManagerCallbackBlock)completion {
  249. @weakify(self)
  250. [[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:url] options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
  251. @strongify(self)
  252. if (!completion || !self) return;
  253. if (image) {
  254. NSError *error = [NSError errorWithDomain:@"成功" code:SPSBNetworkErrorCodeSuccess userInfo:nil];
  255. completion(error, @{@"image": image, @"key": key});
  256. return;
  257. } else if (error && error.code == SDWebImageErrorCancelled) {
  258. return;
  259. }
  260. SPSBUrlDicValue *value = SPSBUrlDicValue.new;
  261. value.spsb_callbackBlock = completion;
  262. self->_urlDic[key] = value;
  263. [self handleFailureWithKey:key message:nil data:@{@"key": key}];
  264. }];
  265. }
  266. - (void)networkPostImageWihtUrl:(NSString *)url parameters:(nullable NSDictionary *)parameters imageArray:(NSArray<UIImage *> *)imageArray completion:(SPSBNetworkManagerCallbackBlock)completion {
  267. NSString *key = [self getDicKeyWithUrl:url filtrationKey:[NSString stringWithFormat:@"%lf", [[NSDate new] timeIntervalSince1970] * 1000]];
  268. SPSBUrlDicValue *value = SPSBUrlDicValue.new;
  269. value.spsb_callbackBlock = completion;
  270. if (_urlDic[key]) {
  271. _urlDic[key] = value;
  272. return;
  273. };
  274. _urlDic[key] = value;
  275. [self networkPostImageWihtUrl:url key:key parameters:parameters imageArray:imageArray completion:completion];
  276. }
  277. - (void)networkPostImageWihtUrl:(NSString *)url key:(NSString *)key parameters:(nullable NSDictionary *)parameters imageArray:(NSArray<UIImage *> *)imageArray completion:(SPSBNetworkManagerCallbackBlock)completion {
  278. if ([spsb_loginToken() isEqualToString:@""]) {
  279. @weakify(self)
  280. [self circulationWithIsNeedToLoginNotification:false url:url key:key circulationAction:^{
  281. @strongify(self)
  282. [self networkPostImageWihtUrl:url key:key parameters:parameters imageArray:imageArray completion:completion];
  283. }];
  284. } else {
  285. NSMutableDictionary *dict;
  286. if (parameters) {
  287. dict = [NSMutableDictionary dictionaryWithDictionary:parameters];
  288. } else {
  289. dict = NSMutableDictionary.new;
  290. }
  291. [dict setObject:spsb_loginToken() forKey:@"key"];
  292. @weakify(self)
  293. SPSBNetworkSuccessBlock successBlock = ^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  294. @strongify(self)
  295. debugLog(@"url=>%@----response=>%@", url, responseObject);
  296. if (!self) return;
  297. [self handleCallBackData:responseObject key:key circulationAction:^{
  298. @weakify(self)
  299. [self circulationWithIsNeedToLoginNotification:true url:url key:key circulationAction:^{
  300. @strongify(self)
  301. [self networkPostImageWihtUrl:url key:key parameters:parameters imageArray:imageArray completion:completion];
  302. }];
  303. }];
  304. };
  305. SPSBNetworkFailureBlock failureBlock = ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  306. debugLog(@"url=>%@----error=>%@", url, error);
  307. @strongify(self)
  308. if (!self) return;
  309. if (error.code != -999) {
  310. [self handleFailureWithKey:key message:nil data:nil];
  311. }
  312. };
  313. NSURLSessionDataTask *task = [_manager POST:url parameters:dict headers:@{} constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
  314. @strongify(self)
  315. [self appendData:formData imageArray:imageArray];
  316. } progress:nil success:successBlock failure:failureBlock];
  317. if (_urlDic[key]) {
  318. _urlDic[key].spsb_task = task;
  319. }
  320. }
  321. }
  322. - (void)appendData:(id<AFMultipartFormData>)formData imageArray:(NSArray<UIImage *> *)imageArray {
  323. for (NSInteger i = 0; i < imageArray.count; i ++) {
  324. UIImage *image = imageArray[i];
  325. NSData *data = UIImageJPEGRepresentation(image, 0.5);
  326. NSString *str;
  327. if (data) {
  328. str = @"jpg";
  329. } else {
  330. data = UIImagePNGRepresentation(image);
  331. str = @"png";
  332. }
  333. [formData appendPartWithFileData:data name:[NSString stringWithFormat:@"file%ld", (long)i + 1] fileName:[NSString stringWithFormat:@"file%ld.%@", (long)i + 1, str] mimeType:@"application/octet-stream"];
  334. }
  335. }
  336. #pragma mark - SPSBNotificationDelegate
  337. - (void)spsb_loggingStatusChanged:(SPSBLoggingStatus)status needCheckOrderBalanceNotPayOrders:(bool)flag {
  338. if (status == SPSBLoggingStatusLogin) {
  339. _isLogin = true;
  340. } else {
  341. _isLogin = false;
  342. }
  343. }
  344. @end