1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126 |
- //
- // RQHTTPService.m
- // RQCommon
- //
- // Created by 张嵘 on 2018/11/16.
- // Copyright © 2018 张嵘. All rights reserved.
- //
- #import "RQHTTPService.h"
- #import <AFNetworking/AFNetworkActivityIndicatorManager.h>
- #import <CocoaSecurity/CocoaSecurity.h>
- #import <MJExtension/MJExtension.h>
- #import <JDStatusBarNotification/JDStatusBarNotification.h>
- #import <CoreTelephony/CTCellularData.h>
- /**
- * 知识点
- //- (RACSignal *)replayLast 就是用Capacity为1的RACReplaySubject来替换- (RACSignal *)replay的`subject。
- 其作用是使后来订阅者只收到最后的历史值。
- //- (RACSignal *)replayLazily和- (RACSignal *)replay的区别就是replayLazily会在第一次订阅的时候才订阅sourceSignal。
- // replay、replayLast、replayLazily的区别 ReactiveCocoa提供了这三个简便的方法允许多个订阅者订阅一个信号,却不会重复执行订阅代码,并且能给新加的订阅者提供订阅前的值。
- replay和replayLast使信号变成热信号,且会提供所有值(-replay) 或者最新的值(-replayLast) 给订阅者。
- replayLazily 会提供所有的值给订阅者 replayLazily还是冷信号 避免了冷信号的副作用
- *
- */
- /// The Http request error domain
- NSString *const RQHTTPServiceErrorDomain = @"RQHTTPServiceErrorDomain";
- /// 请求成功,但statusCode != 0
- NSString *const RQHTTPServiceErrorResponseCodeKey = @"RQHTTPServiceErrorResponseCodeKey";
- NSString * const RQHTTPServiceErrorRequestURLKey = @"RQHTTPServiceErrorRequestURLKey";
- NSString * const RQHTTPServiceErrorHTTPStatusCodeKey = @"RQHTTPServiceErrorHTTPStatusCodeKey";
- NSString * const RQHTTPServiceErrorDescriptionKey = @"RQHTTPServiceErrorDescriptionKey";
- NSString * const RQHTTPServiceErrorMessagesKey = @"RQHTTPServiceErrorMessagesKey";
- NSString * const RQNetworkingReachabilityDidChangeNotification = @"RQNetworkingReachabilityDidChangeNotification";
- /// 连接服务器失败 default
- NSInteger const RQHTTPServiceErrorConnectionFailed = 668;
- NSInteger const RQHTTPServiceErrorJSONParsingFailed = 669;
- NSInteger const RQHTTPServiceErrorBadRequest = 670;
- NSInteger const RQHTTPServiceErrorRequestForbidden = 671;
- /// 服务器请求失败
- NSInteger const RQHTTPServiceErrorServiceRequestFailed = 672;
- NSInteger const RQHTTPServiceErrorSecureConnectionFailed = 673;
- /// 微信登录相关
- NSString * const RQWeChatOnRespNotification = @"RQWeChatOnRespNotification";
- /// 抖音登录相关
- NSString * const RQDouYinOnRespNotification = @"RQDouYinOnRespNotification";
- @interface RQHTTPService ()
- @property (nonatomic, assign, readwrite) AFNetworkReachabilityStatus networkReachabilityStatus;
- @property (nonatomic, readwrite, assign) BOOL isShowNetWorkAuth;
- @end
- @implementation RQHTTPService
- static id service_ = nil;
- #pragma mark - HTTPService
- +(instancetype) sharedInstance {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- service_ = [[self alloc] initWithBaseURL:[NSURL URLWithString:[RQConfigureManager requestBaseUrl]] sessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
- });
- return service_;
- }
- + (id)allocWithZone:(struct _NSZone *)zone{
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- service_ = [super allocWithZone:zone];
- });
- return service_;
- }
- - (id)copyWithZone:(NSZone *)zone {
- return service_;
- }
- - (instancetype)initWithBaseURL:(NSURL *)url sessionConfiguration:(nullable NSURLSessionConfiguration *)configuration{
- if (self = [super initWithBaseURL:url sessionConfiguration:configuration]) {
- /// 配置
- [self _configHTTPService];
- [self wechatOnRespNotification];
- [self douYinOnRespNotification];
- }
- return self;
- }
- /// config service
- - (void)_configHTTPService{
- AFJSONResponseSerializer *responseSerializer = [AFJSONResponseSerializer serializer];
- #if DEBUG
- responseSerializer.removesKeysWithNullValues = NO;
- #else
- responseSerializer.removesKeysWithNullValues = YES;
- #endif
- responseSerializer.readingOptions = NSJSONReadingAllowFragments;
- /// config
- self.responseSerializer = responseSerializer;
- self.requestSerializer = [AFJSONRequestSerializer serializer];
-
-
- /// 安全策略
- AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
- //allowInvalidCertificates 是否允许无效证书(也就是自建的证书),默认为NO
- //如果是需要验证自建证书,需要设置为YES
- securityPolicy.allowInvalidCertificates = YES;
- //validatesDomainName 是否需要验证域名,默认为YES;
- //假如证书的域名与你请求的域名不一致,需把该项设置为NO
- //主要用于这种情况:客户端请求的是子域名,而证书上的是另外一个域名。因为SSL证书上的域名是独立的,假如证书上注册的域名是www.google.com,那么mail.google.com是无法验证通过的;当然,有钱可以注册通配符的域名*.google.com,但这个还是比较贵的。
- securityPolicy.validatesDomainName = NO;
-
- self.securityPolicy = securityPolicy;
- /// 支持解析
- self.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",
- @"text/json",
- @"text/javascript",
- @"text/html",
- @"text/plain",
- @"text/html; charset=UTF-8",
- nil];
-
- /// 开启网络监测
- [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
- [self.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
- switch (status) {
- case AFNetworkReachabilityStatusUnknown:
- // 未知网络
-
- NSLog(@"当前网络:未知网络");
- break;
-
- case AFNetworkReachabilityStatusNotReachable:
- // 无网络
- NSLog(@"当前网络:无网络");
- break;
-
- case AFNetworkReachabilityStatusReachableViaWWAN:
- // 蜂窝数据
- NSLog(@"当前网络:蜂窝数据");
- break;
-
- case AFNetworkReachabilityStatusReachableViaWiFi:
- // 无线网络
- NSLog(@"当前网络:无线网络");
- break;
-
- default:
- break;
- }
-
- if (_networkReachabilityStatus != status) {
- _networkReachabilityStatus = status;
- // 网络改变通知
- [[NSNotificationCenter defaultCenter] postNotificationName:RQNetworkingReachabilityDidChangeNotification object:[NSNumber numberWithInteger:status]];
- }
- }];
- [self.reachabilityManager startMonitoring];
- }
- #pragma mark - Request
- - (RACSignal *)enqueueRequest:(RQHTTPRequest *) request resultClass:(Class /*subclass of RQObject*/) resultClass{
- /// request 必须的有值
- if (!request) return [RACSignal error:[NSError errorWithDomain:RQHTTPServiceErrorDomain code:-1 userInfo:nil]];
-
- @weakify(self);
- if ([request.urlParameters.method isEqualToString:RQ_HTTTP_METHOD_GET] || [request.urlParameters.path isEqualToString:RQ_POST_Code] || [request.urlParameters.path isEqualToString:RQ_POST_Code_IOS] || [request.urlParameters.path isEqualToString:RQ_POST_Code_DouYin]) {
- /// 覆盖manager请求序列化
- self.requestSerializer = [self _requestSerializerWithRequest:request];
- } else if ([request.urlParameters.method isEqualToString:RQ_HTTTP_METHOD_POST] && ![request.urlParameters.path isEqualToString:RQ_POST_Code] && ![request.urlParameters.path isEqualToString:RQ_POST_Code_IOS] && ![request.urlParameters.path isEqualToString:RQ_POST_PrepareOrder]) {
- self.requestSerializer = [self _requestJSONSerializerWithRequest:request];
- } else if ([request.urlParameters.method isEqualToString:RQ_HTTTP_METHOD_DELETE]) {
- if (request.urlParameters.parameters.allValues.count > 1) {
- self.requestSerializer = [self _requestJSONSerializerWithRequest:request];
- } else {
- NSString *deletePath = [NSString stringWithFormat:@"%@/%@",request.urlParameters.path,request.urlParameters.parameters.allValues.firstObject];
- request.urlParameters.path = deletePath;
- request.urlParameters.parameters = @{};
- self.requestSerializer = [self _requestSerializerWithRequest:request];
- }
- } else {
- self.requestSerializer = [self _requestSerializerWithRequest:request];
- }
- // self.requestSerializer.HTTPMethodsEncodingParametersInURI = [NSSet setWithObjects:@"GET", @"HEAD", nil];
- if (RQ_USER_MANAGER.isLogin) {
- [self.requestSerializer setValue:RQ_USER_MANAGER.currentUser.token forHTTPHeaderField:@"Authorization"];
- }
-
-
- /// @RQ-MARK:请求参数
-
- // request.urlParameters.path = [NSString stringWithFormat:@"%@?%@",request.urlParameters.path, [self _signWithParameters:request.urlParameters.parameters]];
-
- // request.urlParameters.path = [NSString stringWithFormat:@"%@",request.urlParameters.path];
- /// 发起请求
- /// concat:按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号。 这里传进去的参数,不是parameters而是之前通过
- /// urlParametersWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters;穿进去的参数
- return [[[self enqueueRequestWithPath:request.urlParameters.path parameters:request.urlParameters.parameters method:request.urlParameters.method]
- reduceEach:^RACStream *(NSURLResponse *response, NSDictionary * responseObject){
- @strongify(self);
- /// 请求成功 这里解析数据
- return [[self parsedResponseOfClass:resultClass fromJSON:responseObject]
- map:^(id parsedResult) {
- RQHTTPResponse *parsedResponse = [[RQHTTPResponse alloc] initWithResponseObject:responseObject parsedResult:parsedResult];
- NSAssert(parsedResponse != nil, @"Could not create RQHTTPResponse with response %@ and parsedResult %@", response, parsedResult);
- return parsedResponse;
- }];
- }]
- concat];
- }
- /// 请求数据
- - (RACSignal *)enqueueRequestWithPath:(NSString *)path parameters:(id)parameters method:(NSString *)method{
- @weakify(self);
- /// 创建信号
- RACSignal *signal = [RACSignal createSignal:^(id<RACSubscriber> subscriber) {
- @strongify(self);
- /// 获取request
- NSError *serializationError = nil;
- NSMutableURLRequest *request;
-
- // NSDictionary *dic = parameters;
- // YYCache *cache = [[YYCache alloc] initWithName:@"getTeachingVideoByTypeId"];
- // NSString *cacheResponseKeyName = [NSString stringWithFormat:@"Response-getTeachingVideoByTypeId=%@",dic[@"videoTypeId"]];
- // NSString *cacheResponseObjectKeyName = [NSString stringWithFormat:@"ResponseObject-getTeachingVideoByTypeId=%@",dic[@"videoTypeId"]];
- if ([RQ_CACHE_MANAGER isNeedCacheWithPath:path]) {
- // if ([cache objectForKey:cacheResponseObjectKeyName] && [cache objectForKey:cacheResponseKeyName]) {
- // /// 打包成元祖 回调数据
- // NSURLResponse *response = (NSURLResponse *)[cache objectForKey:cacheResponseKeyName];
- // NSDictionary *responseObject = (NSDictionary *)[cache objectForKey:cacheResponseObjectKeyName];
- // dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
- // [subscriber sendNext:RACTuplePack(response , responseObject)];
- // [subscriber sendCompleted];
- // });
- // return [RACDisposable disposableWithBlock:^{
- //
- // }];
- // }
-
- NSDictionary *dic = [RQ_CACHE_MANAGER getCacheWithPath:path parameters:parameters];
- if (!RQObjectIsNil(dic)) {
- NSURLResponse *response = (NSURLResponse *)dic[@"response"];
- NSDictionary *responseObject = (NSDictionary *)dic[@"responseObject"];
- dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
- [subscriber sendNext:RACTuplePack(response , responseObject)];
- [subscriber sendCompleted];
- });
- return [RACDisposable disposableWithBlock:^{
-
- }];
- }
- }
-
-
-
- if ([path containsString:@"api.weixin.qq.com"] || [path containsString:@"zzjs.zzxcx.net"] || [path containsString:@"192.168.8.213:8080"]) {
- request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:path relativeToURL:[NSURL URLWithString:@""]] absoluteString] parameters:parameters error:&serializationError];
- } else {
- if ([path isEqualToString:RQ_POST_AddCollections]) {
- NSDictionary *dic = parameters;
- request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:path relativeToURL:self.baseURL] absoluteString] parameters:dic[@"list"] error:&serializationError];
- } else if ([path isEqualToString:RQ_DELETE_Collection_All] || [path isEqualToString:RQ_DELETE_Wrong_All]) {
- request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:path relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
- [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
- NSString *dataStr = [parameters mj_JSONString];
- NSData * bodyData = [dataStr mj_JSONData];
- [request setHTTPBody:bodyData];
- } else {
- request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:path relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
- }
- }
-
-
- if (serializationError) {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wgnu"
- dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
- [subscriber sendError:serializationError];
- });
- #pragma clang diagnostic pop
- return [RACDisposable disposableWithBlock:^{
- }];
- }
- /// 获取请求任务
- __block NSURLSessionDataTask *task = nil;
- task = [self dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse *response, NSDictionary * responseObject, NSError *error) {
- NSDictionary *erroInfo = error.userInfo;
- NSData *data = [erroInfo valueForKey:@"com.alamofire.serialization.response.error.data"];
- NSString *errorString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- if (error) {
- NSError *parseError = [self _errorFromRequestWithTask:task httpResponse:(NSHTTPURLResponse *)response responseObject:responseObject error:error];
- [self HTTPRequestLog:task body:parameters error:parseError];
- [subscriber sendError:parseError];
- } else {
- /// 断言
- NSAssert([responseObject isKindOfClass:NSDictionary.class], @"responseObject is not an NSDictionary: %@", responseObject);
- /// 在这里判断数据是否正确
- /// 判断
- NSInteger statusCode = [responseObject[RQHTTPServiceResponseCodeKey] integerValue];
- if (statusCode == RQHTTPResponseCodeSuccess) {
-
- // NSHTTPURLResponse *httpUrlResponse = (NSHTTPURLResponse *)response;
- // /// 存储token
- // NSString *token = [[[httpUrlResponse allHeaderFields] valueForKey:RQHTTPRequestTokenKey] rq_stringValueExtension];
- // [self saveToken:token];
-
- [self HTTPRequestLog:task body:parameters error:nil];
- /// 打包成元祖 回调数据
- [subscriber sendNext:RACTuplePack(response , responseObject)];
- if ([RQ_CACHE_MANAGER isNeedCacheWithPath:path]) {
- // [cache setObject:response forKey:cacheResponseKeyName];
- // [cache setObject:responseObject forKey:cacheResponseObjectKeyName];
-
- [RQ_CACHE_MANAGER saveCacheWithPath:path parameters:parameters response:response responseObject:responseObject];
- }
- [subscriber sendCompleted];
- }else{
- if (([path isEqualToString:RQ_GET_Userinfo] || [path isEqualToString:RQ_GET_Refresh_token]) && statusCode == 0) {
- /// 打包成元祖 回调数据
- NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:responseObject];
- [dic setValue:path forKey:@"path"];
- [subscriber sendNext:RACTuplePack(response , dic.copy)];
- [subscriber sendCompleted];
- }
-
- if (statusCode == RQHTTPResponseCodeNotLogin && ![RQControllerHelper.currentViewController isKindOfClass:[RQLoginViewController class]]) {
- RACSignal *signalA = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
- /// 删除账号
- [SAMKeychain deleteRawLogin];
- /// 先退出用户
- [RQ_USER_MANAGER logoutUser];
- [subscriber sendNext:@1];
- [subscriber sendCompleted];
- return nil;
- }] delay:1] deliverOnMainThread];
- RACSignal *signalB = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
- /// 这里切换 主页面
- [RQNotificationCenter postNotificationName:RQSwitchRootViewControllerNotification object:nil userInfo:@{RQSwitchRootViewControllerUserInfoKey:@(RQSwitchRootViewControllerFromTypeLogout)}];
- [subscriber sendNext:@2];
- return nil;
- }] delay:1] deliverOnMainThread];
-
- // 把signalA拼接到signalB后,signalA发送完成,signalB才会被激活。
- RACSignal *concatSignal = [signalA concat:signalB];
-
- // 以后只需要面对拼接信号开发。
- // 订阅拼接的信号,不需要单独订阅signalA,signalB
- // 内部会自动订阅。
- // 注意:第一个信号必须发送完成,第二个信号才会被激活
- [concatSignal subscribeNext:^(id x) {
-
-
- NSLog(@"%@",x);
-
- if ([x integerValue] == 2) {
- RQ_USER_MANAGER.isShouldLogin;
- }
- }];
-
- // [[[[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
- //
- // /// 延迟一段时间
- // [subscriber sendNext:@1];
- // return nil;
- // }] delay:1] deliverOnMainThread] then:^RACSignal * _Nonnull{
- // return [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
- // /// 这里切换 主页面
- // [RQNotificationCenter postNotificationName:RQSwitchRootViewControllerNotification object:nil userInfo:@{RQSwitchRootViewControllerUserInfoKey:@(RQSwitchRootViewControllerFromTypeLogout)}];
- // /// 延迟一段时间
- // [subscriber sendNext:@2];
- // return nil;
- // }] delay:1] deliverOnMainThread];
- // }] subscribeNext:^(id x) {
- // /// 这里切换 到账号登录的界面
- // NSLog(@"%@",x);
- // RQ_USER_MANAGER.isShouldLogin;
- // }];
-
-
-
- // [self login:^{
- // /// 这里需要重新配置序列化
- // self.requestSerializer = [self _requestSerializerWithRequest:[RQHTTPRequest requestWithParameters:[RQURLParameters urlParametersWithMethod:method path:path parameters:parameters]]];
- // /// 重新发起请求
- // [[self enqueueRequestWithPath:path parameters:parameters method:method] subscribe:subscriber];
- // } cancel:^{
- // NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
- // userInfo[RQHTTPServiceErrorResponseCodeKey] = @(statusCode);
- // NSString *msgTips = responseObject[RQHTTPServiceResponseMsgKey];
- //#if defined(DEBUG)||defined(_DEBUG)
- // msgTips = RQStringIsNotEmpty(msgTips)?[NSString stringWithFormat:@"%@(%zd)",msgTips,statusCode]:[NSString stringWithFormat:@"服务器出错了,请稍后重试(%zd)~",statusCode]; /// 调试模式
- //#else
- // msgTips = RQStringIsNotEmpty(msgTips)?msgTips:@"服务器出错了,请稍后重试~"; /// 发布模式
- //#endif
- // userInfo[RQHTTPServiceErrorMessagesKey] = msgTips;
- // if (task.currentRequest.URL != nil) userInfo[RQHTTPServiceErrorRequestURLKey] = task.currentRequest.URL.absoluteString;
- // if (task.error != nil) userInfo[NSUnderlyingErrorKey] = task.error;
- // NSError *requestError = [NSError errorWithDomain:RQHTTPServiceErrorDomain code:statusCode userInfo:userInfo];
- // [self HTTPRequestLog:task body:parameters error:requestError];
- // [subscriber sendError:requestError];
- // }];
- } else if (statusCode == RQHTTPResponseInsufficientRequestPermissionCode) {
- NSString *savePath = path;
- NSString *saveParameters = parameters;
- NSString *saveMethod = method;
- /// token过期 请求权限不足
- [[RQ_HTTP_Service wechatRefreshToken] subscribeNext:^(RQWechatRefreshTokenModel *wechatRefreshTokenModel) {
- RQ_USER_MANAGER.currentUser.thirdResult.access_token = wechatRefreshTokenModel.access_token;
- RQ_USER_MANAGER.currentUser.thirdResult.refresh_token = wechatRefreshTokenModel.refresh_token;
- RQ_USER_MANAGER.currentUser.thirdResult.scope = wechatRefreshTokenModel.scope;
- RQ_USER_MANAGER.currentUser.thirdResult.openid = wechatRefreshTokenModel.openid;
- [self enqueueRequestWithPath:savePath parameters:saveParameters method:saveMethod];
- }];
- } else {
- NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
- userInfo[RQHTTPServiceErrorResponseCodeKey] = @(statusCode);
- NSString *msgTips = responseObject[RQHTTPServiceResponseMsgKey];
- if ([responseObject[RQHTTPServiceResponseDataKey] isKindOfClass:[NSString class]] && RQStringIsEmpty(msgTips)) {
- msgTips = responseObject[RQHTTPServiceResponseDataKey];
- #if defined(DEBUG)||defined(_DEBUG)
- msgTips = RQStringIsNotEmpty(msgTips)?[NSString stringWithFormat:@"%@(%zd)",msgTips,statusCode]:[NSString stringWithFormat:@"服务器出错了,请稍后重试(%zd)~",statusCode]; /// 调试模式
- #else
- msgTips = RQStringIsNotEmpty(msgTips)?msgTips:@"服务器出错了,请稍后重试~";/// 发布模式
- #endif
- } else {
- #if defined(DEBUG)||defined(_DEBUG)
- msgTips = RQObjectIsNil(msgTips)? [NSString stringWithFormat:@"服务器出错了,请稍后重试(%zd)~",statusCode] : (RQStringIsNotEmpty(msgTips)?[NSString stringWithFormat:@"%@(%zd)",msgTips,statusCode]:[NSString stringWithFormat:@"服务器出错了,请稍后重试(%zd)~",statusCode]); /// 调试模式
- #else
- msgTips = RQStringIsNotEmpty(msgTips)?msgTips:@"服务器出错了,请稍后重试~";/// 发布模式
- #endif
- }
- userInfo[RQHTTPServiceErrorMessagesKey] = msgTips;
- if (task.currentRequest.URL != nil) userInfo[RQHTTPServiceErrorRequestURLKey] = task.currentRequest.URL.absoluteString;
- if (task.error != nil) userInfo[NSUnderlyingErrorKey] = task.error;
- NSError *requestError = [NSError errorWithDomain:RQHTTPServiceErrorDomain code:statusCode userInfo:userInfo];
- [self HTTPRequestLog:task body:parameters error:requestError];
- [subscriber sendError:requestError];
- }
- }
- }
- }];
- /// 开启请求任务
- [task resume];
- return [RACDisposable disposableWithBlock:^{
- [task cancel];
- }];
- }];
- /// replayLazily:replayLazily会在第一次订阅的时候才订阅sourceSignal
- /// 会提供所有的值给订阅者 replayLazily还是冷信号 避免了冷信号的副作用
- return [[signal
- replayLazily]
- setNameWithFormat:@"-enqueueRequestWithPath: %@ parameters: %@ method: %@", path, parameters , method];
- }
- #pragma mark - Upload
- - (RACSignal *)enqueueUploadRequest:(RQHTTPRequest *)request resultClass:(Class)resultClass fileDatas:(NSArray<NSData *> *)fileDatas name:(NSString *)name mimeType:(NSString *)mimeType{
- /// request 必须的有值
- if (!request) return [RACSignal error:[NSError errorWithDomain:RQHTTPServiceErrorDomain code:-1 userInfo:nil]];
- /// 断言
- NSAssert(RQStringIsNotEmpty(name), @"name is empty: %@", name);
-
- @weakify(self);
-
- /// 覆盖manager 请求序列化
- self.requestSerializer = [self _requestSerializerWithRequest:request];
-
- /// 发起请求
- /// concat:按一定顺序拼接信号,当多个信号发出的时候,有顺序的接收信号。 这里传进去的参数,不是parameters而是之前通过
- /// urlParametersWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters;穿进去的参数
- return [[[self enqueueUploadRequestWithPath:request.urlParameters.path parameters:request.urlParameters.parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
- NSInteger count = fileDatas.count;
- for (int i = 0; i< count; i++) {
- /// 取出fileData
- NSData *fileData = fileDatas[i];
-
- /// 断言
- NSAssert([fileData isKindOfClass:NSData.class], @"fileData is not an NSData class: %@", fileData);
-
- // 在网络开发中,上传文件时,是文件不允许被覆盖,文件重名
- // 要解决此问题,
- // 可以在上传时使用当前的系统事件作为文件名
-
- static NSDateFormatter *formatter = nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- formatter = [[NSDateFormatter alloc] init];
- });
- // 设置时间格式
- [formatter setDateFormat:@"yyyyMMddHHmmss"];
- NSString *dateString = [formatter stringFromDate:[NSDate date]];
- NSString *fileName = [NSString stringWithFormat:@"senba_empty_%@_%d.jpg", dateString , i];
- [formData appendPartWithFileData:fileData name:name fileName:fileName mimeType:RQStringIsNotEmpty(mimeType)?mimeType:@"application/octet-stream"];
- }
- }]
- reduceEach:^RACStream *(NSURLResponse *response, NSDictionary * responseObject){
- @strongify(self);
- /// 请求成功 这里解析数据
- return [[self parsedResponseOfClass:resultClass fromJSON:responseObject]
- map:^(id parsedResult) {
- RQHTTPResponse *parsedResponse = [[RQHTTPResponse alloc] initWithResponseObject:responseObject parsedResult:parsedResult];
- NSAssert(parsedResponse != nil, @"Could not create RQHTTPResponse with response %@ and parsedResult %@", response, parsedResult);
- return parsedResponse;
- }];
- }]
- concat];;
- }
- - (RACSignal *)enqueueUploadRequestWithPath:(NSString *)path parameters:(id)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block{
- @weakify(self);
- /// 创建信号
- RACSignal *signal = [RACSignal createSignal:^(id<RACSubscriber> subscriber) {
- @strongify(self);
- /// 获取request
- NSError *serializationError = nil;
-
- NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:path relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError];
- if (serializationError) {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wgnu"
- dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
- [subscriber sendError:serializationError];
- });
- #pragma clang diagnostic pop
-
- return [RACDisposable disposableWithBlock:^{
- }];
- }
-
- __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:nil completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
- if (error) {
- NSError *parseError = [self _errorFromRequestWithTask:task httpResponse:(NSHTTPURLResponse *)response responseObject:responseObject error:error];
- [self HTTPRequestLog:task body:parameters error:parseError];
- [subscriber sendError:parseError];
- } else {
-
- /// 断言
- NSAssert([responseObject isKindOfClass:NSDictionary.class], @"responseObject is not an NSDictionary: %@", responseObject);
-
- /// 在这里判断数据是否正确
- /// 判断
- NSInteger statusCode = [responseObject[RQHTTPServiceResponseCodeKey] integerValue];
-
- if (statusCode == RQHTTPResponseCodeSuccess) {
- /// 打包成元祖 回调数据
- [subscriber sendNext:RACTuplePack(response , responseObject)];
- [subscriber sendCompleted];
- }else{
-
- if (statusCode == RQHTTPResponseCodeNotLogin && ![RQControllerHelper.currentViewController isKindOfClass:[RQLoginViewController class]]) {
- RACSignal *signalA = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
- /// 删除账号
- [SAMKeychain deleteRawLogin];
- /// 先退出用户
- [RQ_USER_MANAGER logoutUser];
- [subscriber sendNext:@1];
- [subscriber sendCompleted];
- return nil;
- }] delay:1] deliverOnMainThread];
- RACSignal *signalB = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
- /// 这里切换 主页面
- [RQNotificationCenter postNotificationName:RQSwitchRootViewControllerNotification object:nil userInfo:@{RQSwitchRootViewControllerUserInfoKey:@(RQSwitchRootViewControllerFromTypeLogout)}];
- [subscriber sendNext:@2];
- return nil;
- }] delay:1] deliverOnMainThread];
-
- // 把signalA拼接到signalB后,signalA发送完成,signalB才会被激活。
- RACSignal *concatSignal = [signalA concat:signalB];
-
- // 以后只需要面对拼接信号开发。
- // 订阅拼接的信号,不需要单独订阅signalA,signalB
- // 内部会自动订阅。
- // 注意:第一个信号必须发送完成,第二个信号才会被激活
- [concatSignal subscribeNext:^(id x) {
-
-
- NSLog(@"%@",x);
-
- if ([x integerValue] == 2) {
- RQ_USER_MANAGER.isShouldLogin;
- }
- }];
-
-
- /// 需要登录
- // [self login:^{
- // /// 这里需要重新配置序列化
- // self.requestSerializer = [self _requestSerializerWithRequest:[RQHTTPRequest requestWithParameters:[RQURLParameters urlParametersWithMethod:@"POST" path:path parameters:parameters]]];
- // /// 重新发起请求
- // [self enqueueUploadRequestWithPath:path parameters:parameters constructingBodyWithBlock:block];
- // } cancel:^{
- // NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
- // userInfo[RQHTTPServiceErrorResponseCodeKey] = @(statusCode);
- // NSString *msgTips = responseObject[RQHTTPServiceResponseMsgKey];
- //#if defined(DEBUG)||defined(_DEBUG)
- // msgTips = RQStringIsNotEmpty(msgTips)?[NSString stringWithFormat:@"%@(%zd)",msgTips,statusCode]:[NSString stringWithFormat:@"服务器出错了,请稍后重试(%zd)~",statusCode]; /// 调试模式
- //#else
- // msgTips = RQStringIsNotEmpty(msgTips)?msgTips:@"服务器出错了,请稍后重试~"; /// 发布模式
- //#endif
- // userInfo[RQHTTPServiceErrorMessagesKey] = msgTips;
- // if (task.currentRequest.URL != nil) userInfo[RQHTTPServiceErrorRequestURLKey] = task.currentRequest.URL.absoluteString;
- // if (task.error != nil) userInfo[NSUnderlyingErrorKey] = task.error;
- // [subscriber sendError:[NSError errorWithDomain:RQHTTPServiceErrorDomain code:statusCode userInfo:userInfo]];
- // }];
- }else{
-
- NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
- userInfo[RQHTTPServiceErrorResponseCodeKey] = @(statusCode);
- NSString *msgTips = responseObject[RQHTTPServiceResponseMsgKey];
- #if defined(DEBUG)||defined(_DEBUG)
- msgTips = RQStringIsNotEmpty(msgTips)?[NSString stringWithFormat:@"%@(%zd)",msgTips,statusCode]:[NSString stringWithFormat:@"服务器出错了,请稍后重试(%zd)~",statusCode]; /// 调试模式
- #else
- msgTips = RQStringIsNotEmpty(msgTips)?msgTips:@"服务器出错了,请稍后重试~"; /// 发布模式
- #endif
- userInfo[RQHTTPServiceErrorMessagesKey] = msgTips;
- if (task.currentRequest.URL != nil) userInfo[RQHTTPServiceErrorRequestURLKey] = task.currentRequest.URL.absoluteString;
- if (task.error != nil) userInfo[NSUnderlyingErrorKey] = task.error;
- [subscriber sendError:[NSError errorWithDomain:RQHTTPServiceErrorDomain code:statusCode userInfo:userInfo]];
- }
- }
-
- }
- }];
-
- [task resume];
- return [RACDisposable disposableWithBlock:^{
- [task cancel];
- }];
-
- }];
- /// replayLazily:replayLazily会在第一次订阅的时候才订阅sourceSignal
- /// 会提供所有的值给订阅者 replayLazily还是冷信号 避免了冷信号的副作用
- return [[signal
- replayLazily]
- setNameWithFormat:@"-enqueueUploadRequestWithPath: %@ parameters: %@", path, parameters];
- }
- #pragma mark Parsing (数据解析)
- - (NSError *)parsingErrorWithFailureReason:(NSString *)localizedFailureReason {
- NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
- userInfo[NSLocalizedDescriptionKey] = NSLocalizedString(@"Could not parse the service response.", @"");
- if (localizedFailureReason != nil) userInfo[NSLocalizedFailureReasonErrorKey] = localizedFailureReason;
- return [NSError errorWithDomain:RQHTTPServiceErrorDomain code:RQHTTPServiceErrorJSONParsingFailed userInfo:userInfo];
- }
- /// 解析数据
- - (RACSignal *)parsedResponseOfClass:(Class)resultClass fromJSON:(NSDictionary *)responseObject {
- /// 必须是RQBaseModel的子类 且 最外层responseObject必须是字典
- NSParameterAssert((resultClass == nil || [resultClass isSubclassOfClass:RQBaseModel.class]));
-
- /// 这里主要解析的是 data:对应的数据
- if ([responseObject.allKeys containsObject:RQHTTPServiceResponseDataKey]) {
- responseObject = responseObject[RQHTTPServiceResponseDataKey];
- }
-
- /// 解析
- return [RACSignal createSignal:^ id (id<RACSubscriber> subscriber) {
- /// 解析字典
- void (^parseJSONDictionary)(NSDictionary *) = ^(NSDictionary *JSONDictionary) {
- if (resultClass == nil) {
- [subscriber sendNext:JSONDictionary];
- return;
- }
- /// 这里继续取出数据 data{"list":[]}
- NSArray * JSONArray = JSONDictionary[RQHTTPServiceResponseDataListKey];
- if ([JSONArray isKindOfClass:[NSArray class]]) {
- /// 字典数组 转对应的模型
- NSArray *parsedObjects = [NSArray yy_modelArrayWithClass:resultClass.class json:JSONArray];
- /// 这里还需要解析是否是RQObject的子类
- for (id parsedObject in parsedObjects) {
- /// 确保解析出来的类 也是 RQObject
- ((RQBaseModel *)parsedObject).total = [JSONDictionary[RQHTTPServiceResponseDataTotalKey] integerValue];
-
- NSAssert([parsedObject isKindOfClass:RQBaseModel.class], @"Parsed model object is not an RQObject: %@", parsedObject);
- }
- [subscriber sendNext:parsedObjects];
-
- }else{
- /// 字典转模型
- RQBaseModel *parsedObject = [resultClass yy_modelWithDictionary:JSONDictionary];
- if (parsedObject == nil) {
- // Don't treat "no class found" errors as real parsing failures.
- // In theory, this makes parsing code forward-compatible with
- // API additions.
- // 模型解析失败
- NSError *error = [NSError errorWithDomain:@"" code:2222 userInfo:@{}];
- [subscriber sendError:error];
- return;
- }
-
- /// 确保解析出来的类 也是 BaseModel
- NSAssert([parsedObject isKindOfClass:RQBaseModel.class], @"Parsed model object is not an BaseModel: %@", parsedObject);
- /// 发送数据
- [subscriber sendNext:parsedObject];
- }
- };
-
- if ([responseObject isKindOfClass:NSArray.class]) {
-
- if (resultClass == nil) {
- [subscriber sendNext:responseObject];
- }else{
- /// 数组 保证数组里面装的是同一种 NSDcitionary
- for (NSDictionary *JSONDictionary in responseObject) {
- if (![JSONDictionary isKindOfClass:NSDictionary.class]) {
- NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"Invalid JSON array element: %@", @""), JSONDictionary];
- [subscriber sendError:[self parsingErrorWithFailureReason:failureReason]];
- return nil;
- }
- }
-
- /// 字典数组 转对应的模型
- NSArray *parsedObjects = [NSArray yy_modelArrayWithClass:resultClass.class json:responseObject];
-
- /// 这里还需要解析是否是RQObject的子类
- for (id parsedObject in parsedObjects) {
- /// 确保解析出来的类 也是 BaseModel
- NSAssert([parsedObject isKindOfClass:RQBaseModel.class], @"Parsed model object is not an BaseModel: %@", parsedObject);
- }
- [subscriber sendNext:parsedObjects];
- }
- [subscriber sendCompleted];
- } else if ([responseObject isKindOfClass:NSDictionary.class]) {
- /// 解析字典
- parseJSONDictionary(responseObject);
- [subscriber sendCompleted];
- } else if (responseObject == nil || [responseObject isKindOfClass:[NSNull class]]) {
- [subscriber sendNext:nil];
- [subscriber sendCompleted];
- } else if ([responseObject isKindOfClass:[NSString class]]) {
- /// RQ-MARK: 如果responseObject是NSString类型进入该条件
- [subscriber sendNext:responseObject];
- [subscriber sendCompleted];
- } else if ([responseObject isKindOfClass:[NSNumber class]]) {
- /// RQ-MARK: 如果responseObject是NSNumber类型进入该条件
- [subscriber sendNext:responseObject];
- [subscriber sendCompleted];
- } else {
- NSString *failureReason = [NSString stringWithFormat:NSLocalizedString(@"Response wasn't an array or dictionary (%@): %@", @""), [responseObject class], responseObject];
- [subscriber sendError:[self parsingErrorWithFailureReason:failureReason]];
- }
- return nil;
- }];
- }
- #pragma mark - Error Handling
- /// 请求错误解析
- - (NSError *)_errorFromRequestWithTask:(NSURLSessionTask *)task httpResponse:(NSHTTPURLResponse *)httpResponse responseObject:(NSDictionary *)responseObject error:(NSError *)error {
- /// 不一定有值,则HttpCode = 0;
- NSInteger HTTPCode = httpResponse.statusCode;
- NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
- /// default errorCode is RQHTTPServiceErrorConnectionFailed,意味着连接不上服务器
- NSInteger errorCode = RQHTTPServiceErrorConnectionFailed;
- NSString *errorDesc = @"服务器出错了,请稍后重试~";
- /// 其实这里需要处理后台数据错误,一般包在 responseObject
- /// HttpCode错误码解析 https://www.guhei.net/post/jb1153
- /// 1xx : 请求消息 [100 102]
- /// 2xx : 请求成功 [200 206]
- /// 3xx : 请求重定向[300 307]
- /// 4xx : 请求错误 [400 417] 、[422 426] 、449、451
- /// 5xx 、600: 服务器错误 [500 510] 、600
- NSInteger httpFirstCode = HTTPCode/100;
- if (httpFirstCode>0) {
- if (httpFirstCode==4) {
- /// 请求出错了,请稍后重试
- if (HTTPCode == 408) {
- #if defined(DEBUG)||defined(_DEBUG)
- errorDesc = @"请求超时,请稍后再试(408)~"; /// 调试模式
- #else
- errorDesc = @"请求超时,请稍后再试~"; /// 发布模式
- #endif
- }else{
- #if defined(DEBUG)||defined(_DEBUG)
- errorDesc = [NSString stringWithFormat:@"请求出错了,请稍后重试(%zd)~",HTTPCode]; /// 调试模式
- #else
- errorDesc = @"请求出错了,请稍后重试~"; /// 发布模式
- #endif
- }
- }else if (httpFirstCode == 5 || httpFirstCode == 6){
- /// 服务器出错了,请稍后重试
- #if defined(DEBUG)||defined(_DEBUG)
- errorDesc = [NSString stringWithFormat:@"服务器出错了,请稍后重试(%zd)~",HTTPCode]; /// 调试模式
- #else
- errorDesc = @"服务器出错了,请稍后重试~"; /// 发布模式
- #endif
-
- }else if (!self.reachabilityManager.isReachable){
- /// 网络不给力,请检查网络
- errorDesc = @"网络开小差了,请稍后重试~";
- }
- }else{
- if (!self.reachabilityManager.isReachable){
- /// 网络不给力,请检查网络
- errorDesc = @"网络开小差了,请稍后重试~";
- }
- }
- switch (HTTPCode) {
- case 400:{
- errorCode = RQHTTPServiceErrorBadRequest; /// 请求失败
- break;
- }
- case 403:{
- errorCode = RQHTTPServiceErrorRequestForbidden; /// 服务器拒绝请求
- break;
- }
- case 422:{
- errorCode = RQHTTPServiceErrorServiceRequestFailed; /// 请求出错
- break;
- }
- default:
- /// 从error中解析
- if ([error.domain isEqual:NSURLErrorDomain]) {
- #if defined(DEBUG)||defined(_DEBUG)
- errorDesc = [NSString stringWithFormat:@"请求出错了,请稍后重试(%zd)~",error.code]; /// 调试模式
- #else
- errorDesc = @"请求出错了,请稍后重试~"; /// 发布模式
- #endif
- switch (error.code) {
- case NSURLErrorSecureConnectionFailed:
- case NSURLErrorServerCertificateHasBadDate:
- case NSURLErrorServerCertificateHasUnknownRoot:
- case NSURLErrorServerCertificateUntrusted:
- case NSURLErrorServerCertificateNotYetValid:
- case NSURLErrorClientCertificateRejected:
- case NSURLErrorClientCertificateRequired:
- errorCode = RQHTTPServiceErrorSecureConnectionFailed; /// 建立安全连接出错了
- break;
- case NSURLErrorTimedOut:{
- #if defined(DEBUG)||defined(_DEBUG)
- errorDesc = @"请求超时,请稍后再试(-1001)~"; /// 调试模式
- #else
- errorDesc = @"请求超时,请稍后再试~"; /// 发布模式
- #endif
- break;
- }
- case NSURLErrorNotConnectedToInternet:{
- #if defined(DEBUG)||defined(_DEBUG)
- errorDesc = @"网络开小差了,请稍后重试(-1009)~"; /// 调试模式
- #else
- errorDesc = @"网络开小差了,请稍后重试~"; /// 发布模式
- #endif
- break;
- }
- }
- }
- }
- userInfo[RQHTTPServiceErrorHTTPStatusCodeKey] = @(HTTPCode);
- userInfo[RQHTTPServiceErrorDescriptionKey] = errorDesc;
- if (task.currentRequest.URL != nil) userInfo[RQHTTPServiceErrorRequestURLKey] = task.currentRequest.URL.absoluteString;
- if (task.error != nil) userInfo[NSUnderlyingErrorKey] = task.error;
- return [NSError errorWithDomain:RQHTTPServiceErrorDomain code:errorCode userInfo:userInfo];
- }
- #pragma mark - 打印请求日志
- - (void)HTTPRequestLog:(NSURLSessionTask *)task body:params error:(NSError *)error {
- NSLog(@">>>>>>>>>>>>>>>>>>>>>👇 REQUEST FINISH 👇>>>>>>>>>>>>>>>>>>>>>>>>>>");
- NSLog(@"Request%@=======>:%@", error?@"失败":@"成功", task.currentRequest.URL.absoluteString);
- NSLog(@"requestBody======>:%@", params);
- NSLog(@"requstHeader=====>:%@", task.currentRequest.allHTTPHeaderFields);
- NSLog(@"response=========>:%@", task.response);
- NSLog(@"error============>:%@", error);
- NSLog(@"<<<<<<<<<<<<<<<<<<<<<👆 REQUEST FINISH 👆<<<<<<<<<<<<<<<<<<<<<<<<<<");
- }
- #pragma mark - Parameter 签名 MD5 生成一个 sign ,这里请根据实际项目来定
- /// 基础的请求参数
- -(NSMutableDictionary *)_parametersWithRequest:(RQHTTPRequest *)request{
- NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
- /// 模型转字典
- NSDictionary *extendsUrlParams = [request.urlParameters.extendsParameters mj_keyValues].copy;
- if ([extendsUrlParams count]) {
- [parameters addEntriesFromDictionary:extendsUrlParams];
- }
- if ([request.urlParameters.parameters count]) {
- [parameters addEntriesFromDictionary:request.urlParameters.parameters];
- }
- return parameters;
- }
- /// 带签名的请求参数
- - (NSString *)_signWithParameters:(NSDictionary *) parameters {
- /// 按照ASCII码排序
- NSArray *sortedKeys = [[parameters allKeys] sortedArrayUsingSelector:@selector(compare:)];
-
- NSMutableArray *kvs = [NSMutableArray array];
- for (id key in sortedKeys) {
- /// value 为 empty 跳过
- if(RQObjectIsNil(parameters[key])) continue;
- NSString * value = [parameters[key] rq_stringValueExtension];
- // if (RQObjectIsNil(value)||!RQStringIsNotEmpty(value)) continue;
- value = [value rq_removeBothEndsWhitespaceAndNewline];
- // value = [value rq_URLEncoding];
- [kvs addObject:[NSString stringWithFormat:@"%@=%@",key,value]];
- }
-
- NSString *paramString = [kvs componentsJoinedByString:@"&"];
- /// 拼接私钥
- // NSString *keyValue = RQHTTPServiceKeyValue;
- // NSString *signedString = [NSString stringWithFormat:@"%@&%@=%@",paramString,RQHTTPServiceKey,keyValue];
-
- /// 拼接时间戳
- NSString *ts = [NSString stringWithFormat:@"%.f", [NSDate date].timeIntervalSince1970 * 1000];
- NSString *sign = [NSString stringWithFormat:@"%@&key=%@",paramString ,ts];
- /// md5
- sign = [CocoaSecurity md5:sign].hex;
- NSString *signedStr = [NSString stringWithFormat:@"ts=%@&sign=%@&user=ios&v=jsjp",ts ,sign];
-
- return signedStr;
- }
- /// 序列化
- - (AFHTTPRequestSerializer *)_requestSerializerWithRequest:(RQHTTPRequest *) request {
-
- /// 获取基础参数(参数+拓展参数)
- NSMutableDictionary *parameters = [self _parametersWithRequest:request];
- /// 获取带签名的参数
- NSString *sign = [self _signWithParameters:parameters];
- /// 赋值
- parameters[RQHTTPServiceSignKey] = [sign length]?sign:@"";
-
- /// 请求序列化
- AFHTTPRequestSerializer *requestSerializer = [AFHTTPRequestSerializer serializer];
- /// 配置请求头
- for (NSString *key in parameters) {
- NSString *value = [[parameters[key] rq_stringValueExtension] copy];
- if (value.length==0) continue;
- /// value只能是字符串,否则崩溃
- [requestSerializer setValue:value forHTTPHeaderField:key];
- }
- return requestSerializer;
- }
- - (AFJSONRequestSerializer *)_requestJSONSerializerWithRequest:(RQHTTPRequest *) request {
- /// 获取基础参数(参数+拓展参数)
- NSMutableDictionary *parameters = [self _parametersWithRequest:request];
- /// 获取带签名的参数
- NSString *sign = [self _signWithParameters:parameters];
- /// 赋值
- parameters[RQHTTPServiceSignKey] = [sign length]?sign:@"";
-
- /// 请求序列化
- AFJSONRequestSerializer *requestSerializer = [AFJSONRequestSerializer serializer];
- /// 配置请求头
- for (NSString *key in parameters) {
- NSString *value = [[parameters[key] rq_stringValueExtension] copy];
- if (value.length==0) continue;
- /// value只能是字符串,否则崩溃
- [requestSerializer setValue:value forHTTPHeaderField:key];
-
- }
- return requestSerializer;
- }
- - (AFHTTPRequestSerializer *)_requestRawSerializerWithRequest:(RQHTTPRequest *) request {
- /// 获取基础参数(参数+拓展参数)
- NSMutableDictionary *parameters = [self _parametersWithRequest:request];
- /// 获取带签名的参数
- NSString *sign = [self _signWithParameters:parameters];
- /// 赋值
- parameters[RQHTTPServiceSignKey] = [sign length]?sign:@"";
- /// 请求序列化
- AFHTTPRequestSerializer *requestSerializer = [AFHTTPRequestSerializer serializer];
-
- /// 配置请求头
- for (NSString *key in parameters) {
- NSString *value = [[parameters[key] rq_stringValueExtension] copy];
- if (value.length==0) continue;
- /// value只能是字符串,否则崩溃
- [requestSerializer setValue:value forHTTPHeaderField:key];
- }
- return requestSerializer;
- }
- #pragma mark - LoginMethod
- - (void)wechatOnRespNotification {
- /// 监听微信回调的通知
- [[[RQNotificationCenter rac_addObserverForName:RQWeChatOnRespNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSNotification * note) {
- [MBProgressHUD rq_showProgressHUD:@"正在登录..." addedToView:RQControllerHelper.currentViewController.view];
- [[RQ_HTTP_Service studentThirdLoginWithAuthorizationCode:note.object] subscribeNext:^(RQThirdLoginModel *thirdLoginModel) {
- [MBProgressHUD rq_hideHUD];
- /// 存储用户数据
- [MBProgressHUD rq_showTips:@"登录成功"];
- RQUserModel *userModel = [[RQUserModel alloc] init];
- userModel.channel = RQUserLoginChannelTypeWeChatId;
- userModel.token = thirdLoginModel.token;
- userModel.thirdResult = thirdLoginModel.thirdResult;
- // userModel.wechatUserInfoModel = wechatUserInfoModel;
- [RQ_USER_MANAGER loginUser:userModel];
- /// 切换更控制器
- dispatch_async(dispatch_get_main_queue(), ^{
- /// 发通知
- [[NSNotificationCenter defaultCenter] postNotificationName:RQSwitchRootViewControllerNotification object:nil userInfo:@{RQSwitchRootViewControllerUserInfoKey:@(RQSwitchRootViewControllerFromTypeLogin)}];
- });
-
-
-
- // [[RQ_HTTP_Service wechatGetUserInfoWithAccess_token:thirdLoginModel.thirdResult.access_token openid:thirdLoginModel.thirdResult.openid lang:@"c"] subscribeNext:^(RQWechatUserInfoModel *wechatUserInfoModel) {
- // [MBProgressHUD rq_hideHUD];
- // /// 存储用户数据
- // [MBProgressHUD rq_showTips:@"登录成功"];
- // RQUserModel *userModel = [[RQUserModel alloc] init];
- // userModel.channel = RQUserLoginChannelTypeWeChatId;
- // userModel.token = thirdLoginModel.token;
- // userModel.thirdResult = thirdLoginModel.thirdResult;
- // userModel.wechatUserInfoModel = wechatUserInfoModel;
- // [RQ_USER_MANAGER loginUser:userModel];
- // /// 切换更控制器
- // dispatch_async(dispatch_get_main_queue(), ^{
- // /// 发通知
- // [[NSNotificationCenter defaultCenter] postNotificationName:RQSwitchRootViewControllerNotification object:nil userInfo:@{RQSwitchRootViewControllerUserInfoKey:@(RQSwitchRootViewControllerFromTypeLogin)}];
- // });
- // }];
- } error:^(NSError * _Nullable error) {
- [MBProgressHUD rq_hideHUD];
- [MBProgressHUD rq_showErrorTips:error];
- }];
- }];
- }
- /// studentDouYinThirdLoginWithAuthorizationCode
- - (void)douYinOnRespNotification {
- /// 监听抖音回调的通知
- [[[RQNotificationCenter rac_addObserverForName:RQDouYinOnRespNotification object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(NSNotification * note) {
- [MBProgressHUD rq_showProgressHUD:@"正在登录..." addedToView:RQControllerHelper.currentViewController.view];
- [[RQ_HTTP_Service studentDouYinThirdLoginWithAuthorizationCode:note.object] subscribeNext:^(RQThirdLoginModel *thirdLoginModel) {
- [MBProgressHUD rq_hideHUD];
- /// 存储用户数据
- [MBProgressHUD rq_showTips:@"登录成功"];
- RQUserModel *userModel = [[RQUserModel alloc] init];
- userModel.channel = RQUserLoginChannelTypeDouYin;
- userModel.token = thirdLoginModel.token;
- userModel.thirdResult = thirdLoginModel.thirdResult;
- [RQ_USER_MANAGER loginUser:userModel];
- /// 切换更控制器
- dispatch_async(dispatch_get_main_queue(), ^{
- /// 发通知
- [[NSNotificationCenter defaultCenter] postNotificationName:RQSwitchRootViewControllerNotification object:nil userInfo:@{RQSwitchRootViewControllerUserInfoKey:@(RQSwitchRootViewControllerFromTypeLogin)}];
- });
- } error:^(NSError * _Nullable error) {
- [MBProgressHUD rq_showErrorTips:error];
- }];
- }];
- }
- /// 获取网络权限
- - (void)networkAuthStatus {
- CTCellularData *cellularData = [[CTCellularData alloc]init];
- cellularData.cellularDataRestrictionDidUpdateNotifier = ^(CTCellularDataRestrictedState state) {
- if (state == kCTCellularDataRestricted) {
- //拒绝
- [self networkSettingAlert];
- } else if (state == kCTCellularDataNotRestricted) {
- //允许
- } else {
- //未知
- [self unknownNetwork];
- }
- };
- }
- - (void)networkSettingAlert {
- dispatch_async(dispatch_get_main_queue(), ^{
- NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
-
- NSString *app_Name = [infoDictionary objectForKey:@"CFBundleDisplayName"];
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:[NSString stringWithFormat:@"您尚未授权“%@”访问网络的权限,请前往设置开启网络授权", app_Name] preferredStyle:UIAlertControllerStyleAlert];
-
- [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
- _isShowNetWorkAuth = NO;
- }]];
-
- [alertController addAction:[UIAlertAction actionWithTitle:@"去设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
- _isShowNetWorkAuth = NO;
- if (@available(iOS 10.0, *)) {
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
- } else {
- // Fallback on earlier versions
- }
- }]];
-
- if (!_isShowNetWorkAuth) {
- _isShowNetWorkAuth = YES;
- [RQControllerHelper.topViewController presentViewController:alertController animated:YES completion:nil];
- }
- });
- }
- - (void)unknownNetwork {
- dispatch_async(dispatch_get_main_queue(), ^{
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"未知网络" preferredStyle:UIAlertControllerStyleAlert];
-
- [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
- }]];
-
- [RQControllerHelper.topViewController presentViewController:alertController animated:YES completion:nil];
- });
- }
- @end
|