Files
peko-ios/YuMi/Network/HttpRequestHelper.m
2025-02-05 18:15:41 +08:00

416 lines
17 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// HttpRequestHelper.m
// YUMI
//
// Created by zu on 2021/9/3.
//
#import "HttpRequestHelper.h"
#import "YYUtility.h"
#import "AccountInfoStorage.h"
#import "YYReachability.h"
#import <AFNetworking.h>
#import "YUMIMacroUitls.h"
#import "MSParamsDecode.h"
#import "NSData+GZIP.h"
@implementation HttpRequestHelper
+(AFHTTPSessionManager *)requestManager
{
static AFHTTPSessionManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.HTTPShouldUsePipelining = YES; // 启用 HTTP/2 pipelining
configuration.HTTPMaximumConnectionsPerHost = 5; // 提升并发
manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:[HttpRequestHelper getHostUrl]]
sessionConfiguration:configuration];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:
@"application/json",
@"text/json",
@"text/javascript",
@"text/html",
@"text/plain",
@"image/jpeg",
@"image/png", nil];
manager.requestSerializer.HTTPShouldHandleCookies = YES;
manager.requestSerializer.timeoutInterval = 60;
// 声明开启 gzip 和 br
[manager.requestSerializer setValue:@"gzip, br" forHTTPHeaderField:@"Accept-Encoding"];
// 确保所有请求走 HTTPS避免降级到 HTTP/1.1
manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
manager.securityPolicy.allowInvalidCertificates = NO;
manager.securityPolicy.validatesDomainName = YES;
});
return manager;
}
+(NSString *)getHostUrl{
#ifdef DEBUG
NSString *isProduction = [[NSUserDefaults standardUserDefaults]valueForKey:@"kIsProductionEnvironment"];
if([isProduction isEqualToString:@"YES"]){
return API_HOST_URL;
}
return API_HOST_TEST_URL;
#else
return API_HOST_URL;
#endif
}
+ (void)GET:(NSString *)method
params:(NSDictionary *)params
success:(void (^)(BaseModel *data))success
failure:(void (^)(NSInteger resCode, NSString *message))failure
{
if ([self checkNetworkStatusWithFailure:^{
failure(-1, YMLocalizedString(@"HttpRequestHelper0"));
}]) {
return;
}
[self configHeaders];
AFHTTPSessionManager *manager = [HttpRequestHelper requestManager];
NSString *key = @"NeedChangeTimeOut";
NSMutableDictionary *editParam = [params mutableCopy];
if ([editParam.allKeys containsObject:key]) {
NSInteger timeout = [[editParam objectForKey:key] integerValue];
[editParam removeObjectForKey:key];
if (timeout > 0) {
manager.requestSerializer.timeoutInterval = timeout;
}
}
else {
manager.requestSerializer.timeoutInterval = 60;
}
editParam = [MSParamsDecode msDecodeParams:editParam];
params = [self configBaseParmars:editParam];
#ifdef DEBUG
NSLog(@"\nmethod:\n%@\nparameter:\n%@", method, params);
#endif
@kWeakify(self);
[manager GET:method parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject];
#ifdef DEBUG
NSLog(@"%@ - \n%@", method, [baseModel toJSONString]);
#else
#endif
success(baseModel);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
@kStrongify(self);
[self handleNetError:error method:method failure:failure];
}];
}
+ (void)POST:(NSString *)method
params:(NSDictionary *)params
success:(void (^)(BaseModel *data))success
failure:(void (^)(NSInteger resCode, NSString *message))failure
{
if ([self checkNetworkStatusWithFailure:^{
failure(-1, YMLocalizedString(@"HttpRequestHelper0"));
}]) {
return;
}
[self configHeaders];
AFHTTPSessionManager *manager = [HttpRequestHelper requestManager];
params = [MSParamsDecode msDecodeParams:[params mutableCopy] ];
params = [self configBaseParmars:params];
#ifdef DEBUG
NSLog(@"\nmethod:\n%@\nparameter:\n%@", method, params);
#else
#endif
// 将 NSDictionary 转换为 JSON
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:0 error:nil];
// Gzip 压缩数据
NSData *gzipData = [jsonData gzippedData];
@kWeakify(self);
[manager POST:method
parameters:params
headers:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
[formData appendPartWithFormData:gzipData name:@"data"];
}
progress:nil
success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject];
#ifdef DEBUG
NSLog(@"\n%@", [baseModel toJSONString]);
#else
#endif
success(baseModel);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
@kStrongify(self);
[self handleNetError:error method:method failure:failure];
}];
}
+ (void)DELETE:(NSString *)method
params:(NSDictionary *)params
success:(void (^)(BaseModel *data))success
failure:(void (^)(NSInteger resCode, NSString *message))failure
{
if ([self checkNetworkStatusWithFailure:^{
failure(-1, YMLocalizedString(@"HttpRequestHelper0"));
}]) {
return;
}
[self configHeaders];
params = [MSParamsDecode msDecodeParams:[params mutableCopy] ];
params = [self configBaseParmars:params];
AFHTTPSessionManager *manager = [HttpRequestHelper requestManager];
#ifdef DEBUG
NSLog(@"\nmethod:\n%@\nparameter:\n%@", method, params);
#else
#endif
@kWeakify(self);
[manager DELETE:method parameters:params headers:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject];
#ifdef DEBUG
NSLog(@"\n%@", [baseModel toJSONString]);
#else
#endif
success(baseModel);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
@kStrongify(self);
[self handleNetError:error method:method failure:failure];
}];
}
+ (void)request:(NSString *)url
method:(HttpRequestHelperMethod)method
params:(NSDictionary *)params
success:(void (^)(BaseModel *data))success
failure:(void (^)(NSInteger resCode, NSString *message))failure
{
switch (method) {
case HttpRequestHelperMethodGET: {
[self GET:url params:params success:success failure:failure];
}
break;
case HttpRequestHelperMethodPOST:{
[self POST:url params:params success:success failure:failure];
}
break;
case HttpRequestHelperMethodDELETE:{
[self DELETE:url params:params success:success failure:failure];
}
break;
}
}
+ (void)request:(NSString *)path
method:(HttpRequestHelperMethod)method
params:(NSDictionary *)params
completion:(HttpRequestHelperCompletion)completion
{
[self request:path method:method params:params success:^(BaseModel *data) {
if (completion) {
completion(data, data.code, data.message);
}
} failure:^(NSInteger resCode, NSString *message) {
if (completion) {
completion(nil, resCode, message);
}
}];
}
+ (void)configHeaders
{
AFHTTPSessionManager *client = [HttpRequestHelper requestManager];
if ([[AccountInfoStorage instance] getUid].length > 0) {
[client.requestSerializer setValue:[[AccountInfoStorage instance] getUid] forHTTPHeaderField:@"pub_uid"];
} else {
[client.requestSerializer setValue:nil forHTTPHeaderField:@"pub_uid"];
}
if ([[AccountInfoStorage instance] getTicket].length > 0) {
[client.requestSerializer setValue:[[AccountInfoStorage instance] getTicket] forHTTPHeaderField:@"pub_ticket"];
}else {
[client.requestSerializer setValue:nil forHTTPHeaderField:@"pub_ticket"];
}
[client.requestSerializer setValue:[NSBundle uploadLanguageText] forHTTPHeaderField:@"Accept-Language"];
[client.requestSerializer setValue:PI_App_Version forHTTPHeaderField:@"App-Version"];
}
+ (NSDictionary*)configBaseParmars:(NSDictionary * _Nullable)parmars
{
NSDictionary *defaultBasciParame = @{
@"Accept-Language":[NSBundle uploadLanguageText],
@"os" : @"iOS",
@"osVersion" : [YYUtility systemVersion],
@"netType" : ([YYUtility networkStatus] == ReachableViaWiFi) ? @2 : @1,
@"ispType" : @([YYUtility carrierIdentifier]),
@"channel" : [YYUtility getAppSource] ? : @"",
@"model" : [YYUtility modelType],
@"deviceId" : [YYUtility deviceUniqueIdentification],
@"appVersion" : [YYUtility appVersion],
@"app" : [YYUtility appName],
@"lang" : [YYUtility getLanguage],
};
if (!parmars||![parmars isKindOfClass:[NSDictionary class]]){
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:defaultBasciParame];
if(![[YYUtility getMobileCountryCode] isEqualToString:@"65535"]){
[dic setValue:[YYUtility getMobileCountryCode] forKey:@"mcc"];
}
return dic;
}
NSMutableDictionary * dic = [NSMutableDictionary dictionaryWithDictionary:parmars];
if(![[YYUtility getMobileCountryCode] isEqualToString:@"65535"]){
[dic setValue:[YYUtility getMobileCountryCode] forKey:@"mcc"];
}
[dic addEntriesFromDictionary:defaultBasciParame];
return dic;
}
+ (void)handleNetError:(NSError *)error method:(NSString *)method
failure:(void (^)(NSInteger resCode, NSString *message))failure
{
// 别问,反正 oauth/ticket 接口要通过这种方式取错误码。
NSHTTPURLResponse *response = error.userInfo[@"com.alamofire.serialization.response.error.response"];
NSString *NETWORK_ERROR = error.description.length > 0 ? error.description : YMLocalizedString(@"HttpRequestHelper5");;
if (response && response.statusCode == 401) {
failure(response.statusCode, YMLocalizedString(@"HttpRequestHelper7"));
} else {
if (error.code == -1009 || error.code == -1001 || error.code == -1004 || error.code == -1003 || error.code == -1002 || error.code == 3840) {
failure(error.code, @"");
} else {
failure(error.code, error.localizedDescription.length > 0 ? error.localizedDescription : YMLocalizedString(@"HttpRequestHelper4"));
}
}
#ifdef DEBUG
NSLog(@"\n%@", error);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSDictionary *allHeaders = response.allHeaderFields;
//3,
NSMutableDictionary *blockDict = [[NSMutableDictionary alloc]init];
[blockDict setObject:@(response.statusCode) forKey:@"resultCode"];
[blockDict setObject:NETWORK_ERROR forKey:@"resultDesc"];
[BSNetListenModel addHttpRsp:method header:allHeaders result:blockDict isSuccess:NO time:[NSDate getCurrentTimeWithFormat:@"yyyy-MM-dd HH:mm:ss"]];
});
#else
#endif
}
/// 增加或编辑技能卡专用接口 Post 请求参数放入到 body 里 使用 application/json 类型传递
/// @param path 请求地址
/// @param params 参数
/// @param completion 回调
+ (void)postSkillCard:(NSString *)path
params:(NSString *)params
completion:(HttpRequestHelperCompletion)completion{
if ([self checkNetworkStatusWithFailure:^{
completion(nil, -1, YMLocalizedString(@"HttpRequestHelper0"));
}]) {
return;
}
[self configHeaders];
params = [MSParamsDecode msDecodeParams:[params.mj_JSONObject mutableCopy] ].toJSONString;
NSDictionary *baseParams = [self configBaseParmars:nil];
AFHTTPSessionManager *manager = [HttpRequestHelper requestManager];
NSString *url = [self getHostUrl];
NSString *urlPath = [NSString stringWithFormat:@"%@/%@", url ,path];
#ifdef DEBUG
NSLog(@"\nmethod:\n%@\nparameter:\n%@", path, params);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[BSNetListenModel addHttpReq:urlPath header:manager.requestSerializer.HTTPRequestHeaders param:[params copy] time:[NSDate getCurrentTimeWithFormat:@"yyyy-MM-dd HH:mm:ss"]];
});
#else
#endif
__block NSString *requestUrl = @"";
[baseParams.allKeys enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSString *value = baseParams[obj];
requestUrl = [requestUrl stringByAppendingString:[NSString stringWithFormat:@"%@=%@&", obj, value]];
}];
urlPath = [NSString stringWithFormat:@"%@?%@", urlPath, requestUrl];
urlPath = [urlPath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSMutableURLRequest *request = [[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:urlPath parameters:baseParams error:nil];
request.timeoutInterval= [[[NSUserDefaults standardUserDefaults] valueForKey:@"timeoutInterval"] longValue];
[request setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
if ([[AccountInfoStorage instance] getUid].length > 0) {
[request setValue:[[AccountInfoStorage instance] getUid] forHTTPHeaderField:@"pub_uid"];
[manager.requestSerializer setValue:[[AccountInfoStorage instance] getUid] forHTTPHeaderField:@"pub_uid"];
} else {
[request setValue:nil forHTTPHeaderField:@"pub_uid"];
}
if ([[AccountInfoStorage instance] getTicket].length > 0) {
[request setValue:[[AccountInfoStorage instance] getTicket] forHTTPHeaderField:@"pub_ticket"];
[manager.requestSerializer setValue:[[AccountInfoStorage instance] getTicket] forHTTPHeaderField:@"pub_ticket"];
}else {
[request setValue:nil forHTTPHeaderField:@"pub_ticket"];
}
[request setValue:[NSBundle uploadLanguageText] forHTTPHeaderField:@"Accept-Language"];
[request setValue:PI_App_Version forHTTPHeaderField:@"App-Version"];
[manager.requestSerializer setValue:[NSBundle uploadLanguageText] forHTTPHeaderField:@"Accept-Language"];
[manager.requestSerializer setValue:PI_App_Version forHTTPHeaderField:@"App-Version"];
[request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
[[manager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (responseObject) {
BaseModel *baseModel = [BaseModel modelWithDictionary:responseObject];
#ifdef DEBUG
NSLog(@"\n%@", [baseModel toJSONString]);
#else
#endif
if (baseModel.code == 200) {
#ifdef DEBUG
NSHTTPURLResponse *urlresponse = (NSHTTPURLResponse *)response;
NSDictionary *allHeaders = urlresponse.allHeaderFields;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[BSNetListenModel addHttpRsp:urlPath header:allHeaders result:baseModel.data isSuccess:YES time:[NSDate getCurrentTimeWithFormat:@"yyyy-MM-dd HH:mm:ss"]];
});
#else
#endif
if (completion) {
completion(baseModel, 200, nil);
}
} else {
if (completion) {
completion(nil, baseModel.code, baseModel.message);
}
}
}
if (error) {
[self handleNetError:error method:path failure:^(NSInteger resCode, NSString *message) {
completion(nil, resCode, message);
}];
}
}] resume];
}
+ (BOOL)checkNetworkStatusWithFailure:(void (^)(void))failure {
if ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable) {
if (failure) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
failure();
});
}
return YES;
}
return NO;
}
@end