// // HBApiParams.m // FlyChat1 // // Created by Liv on 2022/3/6. // #import "HBApiParams.h" #import #import #import "CommonCrypto/CommonDigest.h" #import "NSString+AES.h" @implementation HBApiParams /** client:结构为获取的当前的终端信息,参考字面义 clientVer:当前开发的前端(app、pc、h5)版本号,参与验签 cont:请求包体内容内容为空时则直接接留空,参与验签 timestamp:时间戳,毫秒值,参与验签 clientType:请求终端,传值为:ios android h5 web;参与验签 apiVer:调用接口版本,默认为1 ;参与验签 验签key:使用sha1(终端类型)转hex值获取; 以上验签字段使用key=value结构拼接;按照字段排序key即可; 生成的验签串如下: apiVer=1&clientType=web&clientVer=1&cont=哈哈哈×tamp=1572760249513&key=CA84D1343B96BAA8137C943ED1860E522CACB238 再将验签串进行md5加密转hex获得sign的值如下: 最终生成的签名内容为:A6218946715FF5272527BFEADE70D022 ***/ + (NSDictionary *)fetchPostParams:(id)info encryption:(BOOL)encryption{ NSMutableDictionary * tempInfo = [NSMutableDictionary dictionary]; [tempInfo addEntriesFromDictionary:@{@"client":[self fetchClient]}]; [tempInfo addEntriesFromDictionary:@{@"clientVer":@"1"}]; [tempInfo addEntriesFromDictionary:@{@"apiVer":[self fetchApiVer]}]; [tempInfo addEntriesFromDictionary:@{@"clientType":[self fetchClientType]}]; [tempInfo addEntriesFromDictionary:@{@"timestamp":[self fetchTimestamp]}]; [tempInfo addEntriesFromDictionary:@{@"param":@"param"}]; if (info) { NSError *error; NSString * infoJson = @"{}"; NSData * jsonData = [NSJSONSerialization dataWithJSONObject:info options:0 error:&error]; if (jsonData) { infoJson = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; } if (encryption) { infoJson = [infoJson aci_encryptWithAES]; [tempInfo addEntriesFromDictionary:@{@"cont":infoJson}]; } else { [tempInfo setValue:info forKey:@"cont"]; } } else { [tempInfo addEntriesFromDictionary:@{@"cont":@""}]; } [tempInfo addEntriesFromDictionary:@{@"sign":[self fetchMD5Sha1Sign:tempInfo]}]; if ([tempInfo[@"cont"] isKindOfClass:[NSString class]] && [tempInfo[@"cont"] isEqualToString:@""]) { [tempInfo removeObjectForKey:@"cont"]; } return tempInfo; } + (NSDictionary *)fetchClient{ NSDictionary * clientDic = @{@"deviceId": [self fetchCurrentDeviceModel], @"osType":@"iOS", @"deviceType":@"ios", @"osVersion":@"1.0", @"appVersion":[self fetchAppVersion]}; return clientDic; } + (NSString *)fetchCurrentDeviceModel{ struct utsname systemInfo; uname(&systemInfo); NSString *deviceModel = [NSString stringWithCString:systemInfo.machine encoding:NSASCIIStringEncoding]; if ([deviceModel isEqualToString:@"iPhone3,1"]) return @"iPhone 4"; if ([deviceModel isEqualToString:@"iPhone3,2"]) return @"iPhone 4"; if ([deviceModel isEqualToString:@"iPhone3,3"]) return @"iPhone 4"; if ([deviceModel isEqualToString:@"iPhone4,1"]) return @"iPhone 4S"; if ([deviceModel isEqualToString:@"iPhone5,1"]) return @"iPhone 5"; if ([deviceModel isEqualToString:@"iPhone5,2"]) return @"iPhone 5 (GSM+CDMA)"; if ([deviceModel isEqualToString:@"iPhone5,3"]) return @"iPhone 5c (GSM)"; if ([deviceModel isEqualToString:@"iPhone5,4"]) return @"iPhone 5c (GSM+CDMA)"; if ([deviceModel isEqualToString:@"iPhone6,1"]) return @"iPhone 5s (GSM)"; if ([deviceModel isEqualToString:@"iPhone6,2"]) return @"iPhone 5s (GSM+CDMA)"; if ([deviceModel isEqualToString:@"iPhone7,1"]) return @"iPhone 6 Plus"; if ([deviceModel isEqualToString:@"iPhone7,2"]) return @"iPhone 6"; if ([deviceModel isEqualToString:@"iPhone8,1"]) return @"iPhone 6s"; if ([deviceModel isEqualToString:@"iPhone8,2"]) return @"iPhone 6s Plus"; if ([deviceModel isEqualToString:@"iPhone8,4"]) return @"iPhone SE"; // 日行两款手机型号均为日本独占,可能使用索尼FeliCa支付方案而不是苹果支付 if ([deviceModel isEqualToString:@"iPhone9,1"]) return @"iPhone 7"; if ([deviceModel isEqualToString:@"iPhone9,2"]) return @"iPhone 7 Plus"; if ([deviceModel isEqualToString:@"iPhone9,3"]) return @"iPhone 7"; if ([deviceModel isEqualToString:@"iPhone9,4"]) return @"iPhone 7 Plus"; if ([deviceModel isEqualToString:@"iPhone10,1"]) return @"iPhone_8"; if ([deviceModel isEqualToString:@"iPhone10,4"]) return @"iPhone_8"; if ([deviceModel isEqualToString:@"iPhone10,2"]) return @"iPhone_8_Plus"; if ([deviceModel isEqualToString:@"iPhone10,5"]) return @"iPhone_8_Plus"; if ([deviceModel isEqualToString:@"iPhone10,3"]) return @"iPhone X"; if ([deviceModel isEqualToString:@"iPhone10,6"]) return @"iPhone X"; if ([deviceModel isEqualToString:@"iPhone11,8"]) return @"iPhone XR"; if ([deviceModel isEqualToString:@"iPhone11,2"]) return @"iPhone XS"; if ([deviceModel isEqualToString:@"iPhone11,6"]) return @"iPhone XS Max"; if ([deviceModel isEqualToString:@"iPhone11,4"]) return @"iPhone XS Max"; if ([deviceModel isEqualToString:@"iPhone12,1"]) return @"iPhone 11"; if ([deviceModel isEqualToString:@"iPhone12,3"]) return @"iPhone 11 Pro"; if ([deviceModel isEqualToString:@"iPhone12,5"]) return @"iPhone 11 Pro Max"; if ([deviceModel isEqualToString:@"iPhone12,8"]) return @"iPhone SE2"; if ([deviceModel isEqualToString:@"iPhone13,1"]) return @"iPhone 12 mini"; if ([deviceModel isEqualToString:@"iPhone13,2"]) return @"iPhone 12"; if ([deviceModel isEqualToString:@"iPhone13,3"]) return @"iPhone 12 Pro"; if ([deviceModel isEqualToString:@"iPhone13,4"]) return @"iPhone 12 Pro Max"; if ([deviceModel isEqualToString:@"iPhone14,1"]) return @"iPhone 13 mini"; if ([deviceModel isEqualToString:@"iPhone14,2"]) return @"iPhone 13"; if ([deviceModel isEqualToString:@"iPhone14,3"]) return @"iPhone 13 Pro"; if ([deviceModel isEqualToString:@"iPhone14,4"]) return @"iPhone 13 Pro Max"; if ([deviceModel isEqualToString:@"iPod1,1"]) return @"iPod Touch 1G"; if ([deviceModel isEqualToString:@"iPod2,1"]) return @"iPod Touch 2G"; if ([deviceModel isEqualToString:@"iPod3,1"]) return @"iPod Touch 3G"; if ([deviceModel isEqualToString:@"iPod4,1"]) return @"iPod Touch 4G"; if ([deviceModel isEqualToString:@"iPod5,1"]) return @"iPod Touch (5 Gen)"; if ([deviceModel isEqualToString:@"iPad1,1"]) return @"iPad"; if ([deviceModel isEqualToString:@"iPad1,2"]) return @"iPad 3G"; if ([deviceModel isEqualToString:@"iPad2,1"]) return @"iPad 2 (WiFi)"; if ([deviceModel isEqualToString:@"iPad2,2"]) return @"iPad 2"; if ([deviceModel isEqualToString:@"iPad2,3"]) return @"iPad 2 (CDMA)"; if ([deviceModel isEqualToString:@"iPad2,4"]) return @"iPad 2"; if ([deviceModel isEqualToString:@"iPad2,5"]) return @"iPad Mini (WiFi)"; if ([deviceModel isEqualToString:@"iPad2,6"]) return @"iPad Mini"; if ([deviceModel isEqualToString:@"iPad2,7"]) return @"iPad Mini (GSM+CDMA)"; if ([deviceModel isEqualToString:@"iPad3,1"]) return @"iPad 3 (WiFi)"; if ([deviceModel isEqualToString:@"iPad3,2"]) return @"iPad 3 (GSM+CDMA)"; if ([deviceModel isEqualToString:@"iPad3,3"]) return @"iPad 3"; if ([deviceModel isEqualToString:@"iPad3,4"]) return @"iPad 4 (WiFi)"; if ([deviceModel isEqualToString:@"iPad3,5"]) return @"iPad 4"; if ([deviceModel isEqualToString:@"iPad3,6"]) return @"iPad 4 (GSM+CDMA)"; if ([deviceModel isEqualToString:@"iPad4,1"]) return @"iPad Air (WiFi)"; if ([deviceModel isEqualToString:@"iPad4,2"]) return @"iPad Air (Cellular)"; if ([deviceModel isEqualToString:@"iPad4,4"]) return @"iPad Mini 2 (WiFi)"; if ([deviceModel isEqualToString:@"iPad4,5"]) return @"iPad Mini 2 (Cellular)"; if ([deviceModel isEqualToString:@"iPad4,6"]) return @"iPad Mini 2"; if ([deviceModel isEqualToString:@"iPad4,7"]) return @"iPad Mini 3"; if ([deviceModel isEqualToString:@"iPad4,8"]) return @"iPad Mini 3"; if ([deviceModel isEqualToString:@"iPad4,9"]) return @"iPad Mini 3"; if ([deviceModel isEqualToString:@"iPad5,1"]) return @"iPad Mini 4 (WiFi)"; if ([deviceModel isEqualToString:@"iPad5,2"]) return @"iPad Mini 4 (LTE)"; if ([deviceModel isEqualToString:@"iPad5,3"]) return @"iPad Air 2"; if ([deviceModel isEqualToString:@"iPad5,4"]) return @"iPad Air 2"; if ([deviceModel isEqualToString:@"iPad6,3"]) return @"iPad Pro 9.7"; if ([deviceModel isEqualToString:@"iPad6,4"]) return @"iPad Pro 9.7"; if ([deviceModel isEqualToString:@"iPad6,7"]) return @"iPad Pro 12.9"; if ([deviceModel isEqualToString:@"iPad6,8"]) return @"iPad Pro 12.9"; if ([deviceModel isEqualToString:@"AppleTV2,1"]) return @"Apple TV 2"; if ([deviceModel isEqualToString:@"AppleTV3,1"]) return @"Apple TV 3"; if ([deviceModel isEqualToString:@"AppleTV3,2"]) return @"Apple TV 3"; if ([deviceModel isEqualToString:@"AppleTV5,3"]) return @"Apple TV 4"; if ([deviceModel isEqualToString:@"i386"]) return @"Simulator"; if ([deviceModel isEqualToString:@"x86_64"]) return @"Simulator"; return deviceModel; } + (NSString *)fetchTimestamp{ NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0]; // 获取当前时间0秒后的时间 NSTimeInterval time = [date timeIntervalSince1970]*1000;// *1000 是精确到毫秒(13位),不乘就是精确到秒(10位) return [NSString stringWithFormat:@"%.0f", time]; } + (NSString *)fetchAppVersion { NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"]; return app_Version; } + (NSString *)fetchApiVer{ NSString * apiVer = @"1"; return apiVer; } + (NSString *)fetchClientType{ NSString * clientType = @"iOS"; return clientType; } + (NSString *)fetchMD5Sha1Sign:(NSDictionary *)info { NSString * signStr = [self fetchSignStr:info]; NSString * key = [[self sha1WithString:[self fetchClientType]] uppercaseString]; signStr = [signStr stringByAppendingFormat:@"&key=%@",key]; NSString * signComp = [ [self MD5String:signStr] uppercaseString] ; return signComp; } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" + (NSString *)MD5String:(NSString *)signStr { const char *cstr = [signStr UTF8String]; unsigned char result[16]; CC_MD5(cstr, (CC_LONG)strlen(cstr), result); return [NSString stringWithFormat: @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15] ]; } #pragma clang diagnostic pop + (NSString *)sha1WithString:(NSString *)string { NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; return [self sha1WithData:data]; } + (NSString *)sha1WithData:(NSData *)data { unsigned char *digest = NULL; // Malloc a buffer to hold hash. digest = malloc(CC_SHA1_DIGEST_LENGTH * sizeof(unsigned char)); memset(digest, 0x0, CC_SHA1_DIGEST_LENGTH); CC_SHA1(data.bytes, (CC_LONG)data.length, digest); NSString *result = [self sha1WithDigest:digest]; if (digest) { free(digest); } return result; } + (NSString *)sha1WithDigest:(const unsigned char *)digest { if (!digest) { return nil; } NSMutableString *result = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * sizeof(unsigned char)]; for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) { [result appendFormat:@"%02x",digest[i]]; } return result; } + (NSString *)fetchSignStr:(NSDictionary *)info { NSString * signStr = @""; NSArray*sortedKeys=[[info allKeys]sortedArrayUsingSelector:@selector(compare:)]; for(NSString * key in sortedKeys){ if ([key isEqualToString:@"client"]) { continue; } id value = [info objectForKey:key] ; if ([key isEqualToString:@"cont"] && [value isKindOfClass:[NSString class]] && [value length] == 0) { continue; } NSString * valueStr = @""; if ([value isKindOfClass:[NSArray class]] ) { valueStr = [self stringWithArray:value]; valueStr = [valueStr stringByAppendingString:@"}"]; }else if ([value isKindOfClass:[NSDictionary class]]){ valueStr = [NSString stringWithFormat:@"%@}",[self stringWithDict:value]]; }else if ([value isKindOfClass:[NSString class]]){ valueStr = value; } NSString * tempKeyV = [NSString stringWithFormat:@"%@=%@&",key,valueStr]; signStr = [signStr stringByAppendingFormat:@"%@",tempKeyV]; } if (signStr.length >0) { signStr = [signStr substringToIndex:signStr.length-1]; } return signStr; } + (NSString*)stringWithArray:(NSArray*)array { NSString*str =@"["; for(id obj in array) { if([obj isKindOfClass:[NSDictionary class]]) { str = [self stringWithDict:obj]; str = [str stringByAppendingFormat:@"}"]; }else if([obj isKindOfClass:[NSArray class]]) { str = [self stringWithArray:obj]; str = [str stringByAppendingFormat:@"]"]; } if([str length] !=1) { str = [str stringByAppendingString:@","]; } } return str; } + (NSString*)stringWithDict:(NSDictionary*)dict{ NSArray*keys = [dict allKeys]; NSArray*sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1,id obj2) { return[obj1 compare:obj2 options:NSNumericSearch]; }]; NSString*str =@"{"; for(NSString*categoryId in sortedArray) { id value = [dict objectForKey:categoryId]; if([value isKindOfClass:[NSDictionary class]]) { value = [self stringWithDict:value]; value = [NSString stringWithFormat:@"%@}",value]; } if([str length] !=1) { str = [str stringByAppendingString:@","]; } str = [str stringByAppendingFormat:@"\"%@\":\"%@\"",categoryId,value]; } return str; } @end