cdts/xdts-ios 3/TreeHole/Code/Base/PYHTTPManager.m

510 lines
21 KiB
Mathematica
Raw Normal View History

2023-07-27 09:20:00 +08:00
//
// PYHTTPManager.m
// Food
//
// Created by ko1o, on 2019/7/27.
// Copyright © 2019 ko1o. All rights reserved.
//
#import <NSString+TUIUtil.h>
#import "PYHTTPManager.h"
#import "AFHTTPSessionManager.h"
//#import "PYAccountService.h"
//#import "PYLoginViewController.h"
//#import "PYNewLoginViewController.h"
#import <AliyunOSSiOS/OSSService.h>
#if IS_DEBUG
static NSString * const salt = @"FFAsdaAoXidicS";
#else
static NSString * const salt = @"sdfsaAoXidiZs";
#endif
const NSInteger kNoLoginCode = 100;
//static BOSClient *bosClient = nil;
//static NSString *bucketname = nil;
//static NSDictionary *typeConfigDic = nil;
static OSSClient *_aliOSSClient;
static NSString *_expirationTimeInGMTFormat;
static NSString *kBucketName = nil;
//static NSString *kAccessKeyId = @"LTAI4GJ3K5yB7xnatvAQdEi5";
//static NSString *kAccessKeySecret = @"6dbahs8GFIZQtslSbQZa6xn2R1pdOA";
//static NSString *kEndpoint = @"https://oss-cn-shenzhen.aliyuncs.com";
static NSString *kSSOCacheAvatarDir = @"avatar"; //
static NSString *kSSOCacheAvatarBgDir = @"cover"; //
static NSString *kSSOCacheReport = @"report"; //
static NSString *kSSOCacheProfilePhoto = @"profile_photo"; //
static NSString *kSSOCacheBottlePhoto = @"bottle_photo"; //
static NSString *kSSOCacheBottleVoice = @"bottle_voice"; //
static NSString *kSSOCacheiOSTestDir = @"iostest";
static dispatch_queue_t uploadQueue; //
void runInMainThread(void(^action)(void)) {
dispatch_async(dispatch_get_main_queue(), action);
}
///Key
#define NotificationName_ReachabilityStatusChange @"TH_ReachabilityStatusChange"
@implementation PYHTTPManager
static AFHTTPSessionManager *_manager;
+ (void)load {
_manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:PYHttpBaseUrl]];
_manager.securityPolicy.allowInvalidCertificates =YES;
_manager.requestSerializer = [AFJSONRequestSerializer serializer];
// _manager.responseSerializer = [AFJSONResponseSerializer serializer];
_manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", nil];
AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
//YES
[securityPolicy setAllowInvalidCertificates:NO];
[_manager setSecurityPolicy:securityPolicy];
uploadQueue = dispatch_queue_create("com.youth.uploadfile", DISPATCH_QUEUE_SERIAL);
// [self getSetupOSSClientWithCompletion:^(BOOL succeed) {
//
// }];
}
+ (void)showLoginPage
{
// UINavigationController *currectNav = [PYAppService currentNavigationController];
// if ([currectNav.viewControllers.firstObject isKindOfClass:[PYNewLoginViewController class]]) {
// return;
// }
// PYNavigationViewController *nav = [[PYNavigationViewController alloc] initWithRootViewController:[PYNewLoginViewController new]];
//
[_manager.operationQueue cancelAllOperations];
// [[PYAppService currentViewController] presentViewController:nav animated:YES completion:nil];
}
+ (void)setReachabilityStatusChangeBlock:(nullable void (^)(AFNetworkReachabilityStatus status))block
{
[_manager.reachabilityManager startMonitoring];
[_manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
//,
[NSNotificationCenter.defaultCenter postNotificationName:NotificationName_ReachabilityStatusChange object:nil userInfo:@{NotificationName_ReachabilityStatusChange : @(status)}];
//
if (block) {
block(status);
}
}];
}
///
+ (void)addObserverForReachabilityStatusChange:(nullable void (^)(AFNetworkReachabilityStatus status))changeBlock {
[NSNotificationCenter.defaultCenter addObserverForName:NotificationName_ReachabilityStatusChange object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
if ([note.userInfo.allKeys containsObject:NotificationName_ReachabilityStatusChange]) {
NSNumber *statusNum = [note.userInfo objectForKey:NotificationName_ReachabilityStatusChange];
changeBlock(statusNum.integerValue);
}
}];
}
+ (BOOL)isNetReachable
{
return [_manager.reachabilityManager isReachable];
}
/// message
+ (NSArray *)showRspMessageServerNames
{
return @[
@"activebm/",
@"userwsub/",
@"invoiceaddc/",
@"invoiceadd/"
];
}
+ (NSArray *)ignoreErrorMsg {
return @[@""];
}
+ (NSArray *)handleErrorCodeWithPath:(NSString *)path {
if ([path isEqualToString:@"learnroomdetail"]) {
return @[@(1200), @(1201), @(1202)];
}
return nil;
}
+ (NSError *)errorWithPath:(NSString *)path forCode:(int)code userInfo:(NSDictionary *)userInfo {
if ([[self handleErrorCodeWithPath:path] containsObject:@(code)]) {
return [NSError errorWithDomain:NSCocoaErrorDomain code:code userInfo:userInfo];
}
return nil;
}
+ (NSDictionary *)headers {
NSMutableDictionary *headersM = [NSMutableDictionary dictionary];
if ([LoginService token]) {
headersM[@"Authorization"] = [@"Bearer " stringByAppendingString:[LoginService token]];
}
return headersM;
}
+ (NSMutableDictionary *)commonParamsM {
NSMutableDictionary *commonParamsM = [NSMutableDictionary dictionary];
// * post,:
// * device_brand: api
// * device_model: api
// * app_version_name: 34.1.12
// * app_version_code bundle id1/123
// * interface_version: 1.0
// * device_platform: iOS / Android
UIDevice *device = [UIDevice currentDevice];
commonParamsM[@"device_brand"] = @"Apple";
commonParamsM[@"device_model"] = device.model ?: @"Unknown";
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];//app
commonParamsM[@"app_version_name"] = infoDictionary[@"CFBundleShortVersionString"] ?: @"Unknown";
NSInteger interVersionCode = (NSInteger)infoDictionary[@"CFBundleVersion"];
NSString *versionCodeStr = [NSString stringWithFormat:@"%lu",interVersionCode];
commonParamsM[@"app_version_code"] = versionCodeStr;
// commonParamsM[@"app_version_code"] = infoDictionary[@"CFBundleVersion"] ?: @"Unknown";
commonParamsM[@"interface_version"] = infoDictionary[@"CFBundleShortVersionString"] ?: @"Unknown";
commonParamsM[@"device_platform"] = @"iOS";
commonParamsM[@"os_version"] = [UIDevice currentDevice].systemVersion;
return commonParamsM;
}
+ (NSString *)generateSignWithParams:(NSDictionary *)params {
NSArray *sortedKeys = [params.allKeys sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return obj1 > obj2;
}];
NSMutableString *signStrM = [NSMutableString stringWithFormat:@"%@,", salt];
for (NSString *key in sortedKeys) {
NSString *value = params[key];
if (key && value) {
[signStrM appendFormat:@"%@:%@,", key, value];
}
}
[signStrM appendString:salt];
return [signStrM md5];
}
+ (void)handleRsp:(id)responseObject path:(NSString *)path callback:(PYHTTPManagerCallback)callback {
int code = [responseObject[@"code"] intValue];
// NSLog(@"code==%d",code);
//9999
if (code == 9998 || code == 9999) { // APP
[SVProgressHUD dismiss];
[PYAppService logout];
return;
}
if (code == 10) { //
[SVProgressHUD dismiss];
[PYAppService showVipAlertWithPath:path title:responseObject[@"title"] msg:responseObject[@"message"] source:nil];
return;
}
NSError *handleError = [self errorWithPath:path forCode:code userInfo:responseObject];
if (code != 0 && !handleError) {
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:code userInfo:responseObject];
if (![[self ignoreErrorMsg] containsObject:path]) {
if (![responseObject[@"message"] isEqualToString:@"auth header is empty"]) {
[SVProgressHUD showErrorWithStatus:responseObject[@"message"] ?: @"网络异常,请稍后再试~"];
}
}
if (callback) {
callback(nil, error);
}
return;
}
id result = responseObject[@"data"];
if ([result isKindOfClass:NSNull.class]) {
result = nil;
}
if (callback) {
callback(result, handleError);
}
}
+ (void)postWithPath:(NSString *)path params:(NSDictionary *)params callback:(PYHTTPManagerCallback)callback{
NSLog(@"path===%@,[self headers]%@",path,[self headers]);
NSMutableDictionary *args = [self commonParamsM];
2024-01-02 18:08:42 +08:00
NSLog(@"path===%@,[self headers]%@",path,[self headers]);
2023-07-27 09:20:00 +08:00
[args addEntriesFromDictionary:params];
args[@"sign"] = [self generateSignWithParams:args];
2024-01-02 18:08:42 +08:00
NSLog(@"params===%@",params);
2023-07-27 09:20:00 +08:00
[_manager POST:path parameters:args headers:[self headers] progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[self handleRsp:responseObject path:path callback:callback];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (callback) {
if (error) {
[SVProgressHUD showErrorWithStatus:error.localizedDescription ?: @"网络异常,请稍后再试~"];
}
callback(nil, error);
}
}];
}
+ (void)getWithPath:(NSString *)path params:(NSDictionary *)params callback:(PYHTTPManagerCallback)callback {
NSMutableDictionary *args = [self commonParamsM];
[args addEntriesFromDictionary:params];
[_manager GET:path parameters:args headers:[self headers] progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[self handleRsp:responseObject path:path callback:callback];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (error.code == kNoLoginCode) {
[self showLoginPage];
return ;
}
if (callback) {
if (error) {
[SVProgressHUD showErrorWithStatus:error.localizedDescription ?: @"网络异常,请稍后再试~"];
}
callback(nil, error);
}
}];
}
+ (void)post:(NSString *)url params:(NSDictionary *)params imageses:(NSArray<NSArray<UIImage *> *> *)imageses imageNames:(NSArray<NSString *> *)imageNames callback:(PYHTTPManagerCallback)callback
{
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:PYHttpBaseUrl]];
// [manager.requestSerializer setValue:@"multipart/form-data;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"multipart/form-data", @"application/json", @"text/html", @"image/jpeg", @"image/png", @"application/octet-stream", @"text/json", nil];
NSMutableDictionary *args = [NSMutableDictionary dictionary];
[args addEntriesFromDictionary:params];
// NSLog(@"PYHttpBaseUrl===%@",PYHttpBaseUrl);
[manager POST:url
parameters:args
headers:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
for (int j = 0; j < imageses.count; j++) {
NSArray *images = imageses[j];
NSString *imageName = imageNames[j];
for (int i = 0 ;i < images.count; i++) {
UIImage *image = images[i];
NSData *data = UIImageJPEGRepresentation(image, 1.0);
[formData appendPartWithFileData:data name:imageName fileName:[NSString stringWithFormat:@"%@.jpg", [[NSUUID UUID]UUIDString]] mimeType:@"image/jpeg"];
}
}
} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if ([responseObject[@"code"] integerValue] != 200) {
NSError *error = [NSError errorWithDomain:@"" code:[responseObject[@"code"] integerValue] userInfo:responseObject];
callback(nil, error);
[SVProgressHUD showErrorWithStatus:responseObject[@"message"]];
} else {
callback(responseObject[@"data"], nil);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[SVProgressHUD showErrorWithStatus:[error localizedDescription]];
callback(nil, error);
}];
}
+ (NSString *)subfixForScene:(AliOSSUploadScene)scene
{
switch (scene) {
case AliOSSUploadSceneAvatar:
case AliOSSUploadSceneAvatarBg:
case AliOSSUploadSceneReport:
case AliOSSUploadSceneiOSTest:
case AliOSSUploadSceneProfilePhoto:
case AliOSSUploadSceneBottlePhoto:
return @"jpg";
case AliOSSUploadSceneBottleVoice:
return @"m4a";
}
return @"jpg";
}
+ (NSString *)cachePathForScene:(AliOSSUploadScene)scene
{
switch (scene) {
case AliOSSUploadSceneAvatar :
return kSSOCacheAvatarDir;
case AliOSSUploadSceneAvatarBg:
return kSSOCacheAvatarBgDir;
case AliOSSUploadSceneReport:
return kSSOCacheReport;
case AliOSSUploadSceneProfilePhoto:
return kSSOCacheProfilePhoto;
case AliOSSUploadSceneBottlePhoto:
return kSSOCacheBottlePhoto;
case AliOSSUploadSceneBottleVoice:
return kSSOCacheBottleVoice;
}
return kSSOCacheiOSTestDir;
}
+ (void)getSetupOSSClientWithCompletion:(void(^)(BOOL succeed))completion {
[self postWithPath:@"ossauth" params:nil callback:^(id _Nullable rsp, NSError * _Nullable error) {
if (!error && rsp) {
id<OSSCredentialProvider> credential = [[OSSFederationCredentialProvider alloc] initWithFederationTokenGetter:^OSSFederationToken * {
// FederationTokenOSSFederationToken
// nil
OSSFederationToken *token = [OSSFederationToken new];
// STS访AccessKey IDAccessKey Secret
token.tAccessKey = rsp[@"access_key_id"];
token.tSecretKey = rsp[@"access_key_secret"];
// STSSecurityToken
token.tToken = rsp[@"security_token"];
// 访
token.expirationTimeInGMTFormat = rsp[@"expiration"];
return token;
}];
_expirationTimeInGMTFormat = rsp[@"expiration"];
_aliOSSClient = [[OSSClient alloc] initWithEndpoint:rsp[@"end_point"] credentialProvider:credential];
kBucketName = rsp[@"bucket_name"] ?: @"xidi-official-website";
runInMainThread(^{
if (completion) {
completion(YES);
}
});
} else {
runInMainThread(^{
if (completion) {
completion(NO);
}
});
}
}];
}
+ (void)uploadFileWithScene:(AliOSSUploadScene)scene
data:(NSData *)data
completion:(PYHTTPManagerCallback)completion
{
dispatch_async(uploadQueue, ^{
@synchronized (self) {
BOOL needNewOssClient = YES;
if (_expirationTimeInGMTFormat != nil && _aliOSSClient != nil) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
//2022-06-06T10:01:27Z
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss'Z'"];
NSDate *date = [dateFormatter dateFromString:_expirationTimeInGMTFormat];
if (date != nil && date.timeIntervalSinceNow > 60) {
needNewOssClient = NO;
}
}
if (needNewOssClient == YES || _aliOSSClient == nil) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self getSetupOSSClientWithCompletion:^(BOOL succeed) {
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
}
if (!_aliOSSClient) {
runInMainThread(^{
[SVProgressHUD showErrorWithStatus:@"上传失败"];
completion(nil, [NSError errorWithDomain:@"com.youth" code:-1 userInfo:nil]);
});
return;
}
}
OSSPutObjectRequest * put = [OSSPutObjectRequest new];
put.bucketName = kBucketName;
NSString *userID = [LoginService tokenInfo][@"id"] ?: [NSString stringWithFormat:@"random_%d", arc4random()];
NSString *prefix = [NSString stringWithFormat:@"%@_%.0f", userID, [[NSDate date] timeIntervalSince1970] * 100000.0]; //
NSString *fileName = [NSString stringWithFormat:@"%@.%@", prefix, [self subfixForScene:scene]];
//objectKeyobjectNameOSSabc/efg/123.jpg
NSString *cacheDir = [self cachePathForScene:scene];
put.objectKey = [NSString stringWithFormat:@"%@/%@", cacheDir, fileName];
// NSData
put.uploadingData = data;
// put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
// NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
// };
// [SVProgressHUD showWithStatus:@"文件上传中..."];
OSSTask * putTask = [_aliOSSClient putObject:put];
[putTask continueWithBlock:^id(OSSTask *task) {
if (completion) {
if (!task.error) {
// [SVProgressHUD dismiss];
NSLog(@"upload object success!");
// sign public url
OSSTask *task = [_aliOSSClient presignPublicURLWithBucketName:kBucketName
withObjectKey:put.objectKey];
if (!task.error) {
runInMainThread(^{
completion(task.result, nil);
});
} else {
NSLog(@"sign url error: %@", task.error);
runInMainThread(^{
completion(nil, task.error);
[SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:@"上传失败 sign %@", [task.error.userInfo objectForKey:@"message"]]];
});
}
} else {
NSLog(@"upload object failed, error: %@" , task.error);
runInMainThread(^{
completion(nil, task.error);
[SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:@"上传失败%@", [task.error.userInfo objectForKey:@"message"]]];
});
}
}
return nil;
}];
});
}
+ (void)uploadFileWithScene:(AliOSSUploadScene)scene
datas:(NSArray<NSData *> *)datas
completion:(PYHTTPManagerCallback)completion
{
NSInteger totalTaskCount = datas.count;
__block NSInteger finishTaskCount = 0;
NSMutableArray *fileUrls = [NSMutableArray array];
for (NSData *data in datas) {
[self uploadFileWithScene:scene data:data completion:^(id _Nullable rsp, NSError * _Nullable error) {
@synchronized (self) {
finishTaskCount++;
if (rsp && !error && completion) {
[fileUrls addObject:rsp];
if (finishTaskCount >= totalTaskCount && fileUrls.count == finishTaskCount) {
//
[fileUrls sortUsingComparator:^NSComparisonResult(NSString *url1, NSString *url2) {
return [url1 compare:url2];
}];
runInMainThread(^{
completion(fileUrls, nil);
});
}
}
if (error) {
runInMainThread(^{
completion(nil, error);
});
}
}
}];
usleep(10000); // 10
}
}
@end