123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- //
- // JXPayServer.m
- // shiku_im
- //
- // Created by p on 2019/7/16.
- // Copyright © 2019 Reese. All rights reserved.
- //
- #import "JXPayServer.h"
- #import "MD5Util.h"
- #import "AESUtil.h"
- @interface JXPayServer()
- @property (nonatomic, copy) NSString *action;
- @property (nonatomic, weak) id toView;
- @property (nonatomic, copy) NSString *payPassword;
- @property (nonatomic, copy) NSString *code;
- @property (nonatomic, copy) NSString *codeId;
- @property (nonatomic, assign) long time;
- @property (nonatomic, strong) NSMutableArray *param;
- @property (nonatomic, assign) NSInteger verifyNum;
- @end
- @implementation JXPayServer
- +(instancetype)sharedManager {
- static dispatch_once_t onceToken;
- static JXPayServer *instance;
- dispatch_once(&onceToken, ^{
- instance = [[JXPayServer alloc] init];
- });
- return instance;
- }
- - (instancetype)init {
- if ([super init]) {
- }
- return self;
- }
- - (void)payServerWithAction:(NSString *)action param:(NSMutableArray *)param payPassword:(NSString *)payPassword time:(long)time toView:(id)toView{
-
- self.action = action;
- self.toView = toView;
- self.payPassword = payPassword;
- self.time = time;
- self.param = param;
- // 参数salt为随机UUID字符串,确保每次的mac都不同
- NSString* s = [NSUUID UUID].UUIDString;
- s = [[s stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString];
- NSString *salt = s;
- // 获取Mac值
- NSString *mac = [self getMacWithSalt:salt payPassword:payPassword];
- // 获取临时密码
- [g_server transactionGetCodeWithSalt:salt mac:mac toView:self];
- }
- // 获取mac值
- - (NSString *)getMacWithSalt:(NSString *)salt payPassword:(NSString *)payPassword {
-
- NSMutableString *str = [NSMutableString string];
- [str appendString:APIKEY];
- [str appendString:g_myself.userId];
- [str appendString:g_server.access_token];
- [str appendString:salt];
-
- NSData *aesData = [AESUtil encryptAESData:[g_myself.userId dataUsingEncoding:NSUTF8StringEncoding] key:[MD5Util getMD5DataWithString:payPassword]];
-
- NSData *macData = [g_securityUtil getHMACMD5:[str dataUsingEncoding:NSUTF8StringEncoding] key:[[MD5Util getMD5StringWithData:aesData] dataUsingEncoding:NSUTF8StringEncoding]];
- NSString *mac = [macData base64EncodedStringWithOptions:0];
- return mac;
- }
- - (NSString *)getParamStringWithParamDic:(NSMutableArray *)param time:(long)time payPassword:(NSString *)payPassword code:(NSString *)code {
-
- NSMutableString *str1 = [NSMutableString string];
- [str1 appendString:APIKEY];
- [str1 appendString:g_myself.userId];
- [str1 appendString:g_server.access_token];
-
- NSMutableString *str2 = [NSMutableString string];
-
- NSMutableDictionary *dict = [NSMutableDictionary dictionary];
- NSString *key;
- for (NSInteger i = 0; i < param.count; i ++) {
-
- if (i % 2 == 0) {
- key = param[i];
- }else {
- [str2 appendString:param[i]];
- [dict setObject:param[i] forKey:key];
- }
-
- }
-
- [dict setObject:[NSNumber numberWithLong:time] forKey:@"time"];
-
- NSMutableString *str3 = [NSMutableString string];
- [str3 appendString:[NSString stringWithFormat:@"%ld",time]];
- NSData *aesData = [AESUtil encryptAESData:[g_myself.userId dataUsingEncoding:NSUTF8StringEncoding] key:[MD5Util getMD5DataWithString:payPassword]];
- NSString *aesMd5Str = [MD5Util getMD5StringWithData:aesData];
- [str3 appendString:aesMd5Str];
-
- NSMutableString *str = [NSMutableString string];
- [str appendString:str1];
- [str appendString:str2];
- [str appendString:str3];
-
- if (!g_securityUtil.privateKeyRef) {
-
- NSData *privateAesData = [[NSData alloc] initWithBase64EncodedString:g_securityUtil.privateAesStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
- NSData *privateData = [AESUtil decryptAESData:privateAesData key:[MD5Util getMD5DataWithString:payPassword]];
- NSString *privateBase64 = [privateData base64EncodedStringWithOptions:0];
- g_securityUtil.privateKeyRef = [g_securityUtil getRSAKeyWithBase64Str:privateBase64 isPrivateKey:YES];
-
- // 如果私钥解密失败,重新获取code、清除本地私钥、重新获取私钥
- if (!g_securityUtil.privateKeyRef) {
-
- if (self.verifyNum > 5) {
- self.verifyNum = 0;
- [JXMyTools showTipView:@"code解密失败"];
- return nil;
- }
-
- g_securityUtil.privateAesStr = @"";
-
- // 参数salt为随机UUID字符串,确保每次的mac都不同
- NSString* s = [NSUUID UUID].UUIDString;
- s = [[s stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString];
- NSString *salt = s;
- // 获取Mac值
- NSString *mac = [self getMacWithSalt:salt payPassword:payPassword];
- // 获取临时密码
- [g_server transactionGetCodeWithSalt:salt mac:mac toView:self];
-
- self.verifyNum ++;
-
- return nil;
- }
- }
-
- NSData *codeData = [[NSData alloc] initWithBase64EncodedString:code options:NSDataBase64DecodingIgnoreUnknownCharacters];
- NSData *deCodeData = [g_securityUtil decryptMessageRSA:codeData];
-
- // 如果code解密失败,重新获取code、清除本地私钥、重新获取私钥
- if (!deCodeData) {
-
- if (self.verifyNum > 5) {
- self.verifyNum = 0;
- [JXMyTools showTipView:@"code解密失败"];
- return nil;
- }
-
- g_securityUtil.privateAesStr = @"";
-
- // 参数salt为随机UUID字符串,确保每次的mac都不同
- NSString* s = [NSUUID UUID].UUIDString;
- s = [[s stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString];
- NSString *salt = s;
- // 获取Mac值
- NSString *mac = [self getMacWithSalt:salt payPassword:payPassword];
- // 获取临时密码
- [g_server transactionGetCodeWithSalt:salt mac:mac toView:self];
-
- self.verifyNum ++;
-
- return nil;
- }
-
- NSString *deCodeBase = [deCodeData base64EncodedStringWithOptions:0];
-
- // NSData *macData = [g_securityUtil getHMACMD5:[str dataUsingEncoding:NSUTF8StringEncoding] key:deCodeData];
- // NSString *mac = [macData base64EncodedStringWithOptions:0];
-
- NSString *mac = [g_securityUtil getSignWithRSA:str withPriKey:g_securityUtil.privateKeyRef];
-
- [dict setObject:mac forKey:@"mac"];
-
- SBJsonWriter * OderJsonwriter = [SBJsonWriter new];
- NSString * jsonString = [OderJsonwriter stringWithObject:dict];
-
- NSData *aesJsonData = [AESUtil encryptAESData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] key:deCodeData];
- return [aesJsonData base64EncodedStringWithOptions:0];
- }
- // 获取二维码付款哈希值
- - (NSData *)getQRCodeHash {
-
-
- long time = (long)[[NSDate date] timeIntervalSince1970];
- time = (time *1000 + g_server.timeDifference)/1000; // 秒
- time = time / 60; //精确到分钟
-
-
- NSData *randByte = [self getDataWithInt:g_payServer.randNum];
-
- NSData *da = [randByte subdataWithRange:NSMakeRange(randByte.length - 1, 1)];
- Byte bRand[1];
- [da getBytes:bRand length:sizeof(bRand)];
- int rand = bRand[0];
- NSMutableString *value = [NSMutableString string];
- [value appendString:APIKEY];
- [value appendString:g_myself.userId];
- [value appendString:[NSString stringWithFormat:@"%d", rand]];
- [value appendString:[NSString stringWithFormat:@"%ld", time]];
-
- NSData *qrKey = [g_default objectForKey:kMyQRKey];
- NSData *macData = [g_securityUtil getHMACMD5:[value dataUsingEncoding:NSUTF8StringEncoding] key:qrKey];
-
- return macData;
- }
- // 获取opt算法
- - (unsigned int)getQRCodeOpt {
-
- g_payServer.randNum ++;
-
-
- NSData *hash = [self getQRCodeHash];
-
-
- NSData *randByte = [self getDataWithInt:g_payServer.randNum];
-
- NSData *da = [randByte subdataWithRange:NSMakeRange(randByte.length - 1, 1)];
-
- NSMutableData *optData = [NSMutableData data];
- NSData *hashSubData = [hash subdataWithRange:NSMakeRange(0, 3)];
- [optData appendData:hashSubData];
- [optData appendData:da];
-
- unsigned int opt;
- [optData getBytes:&opt length:sizeof(opt)];
-
- return opt;
- }
- // 获取qrCode
- - (NSString *) getQrCode {
-
-
- unsigned int opt = [self getQRCodeOpt];
-
- NSInteger userId = [g_myself.userId integerValue];
- long long num = userId << 32;
-
- long long qrCode = num + opt;
-
- NSMutableString *qrCodeStr = [NSMutableString stringWithFormat:@"%lld", qrCode];
-
- while (qrCodeStr.length < 19) {
- [qrCodeStr insertString:@"0" atIndex:0];
- }
-
- return qrCodeStr;
- }
- - (NSData *) getDataWithInt:(int)num {
- Byte b1=num & 0xff;
- Byte b2=(num>>8) & 0xff;
- Byte b3=(num>>16) & 0xff;
- Byte b4=(num>>24) & 0xff;
- Byte byte[] = {b4,b3,b2,b1};
- NSData *adddata = [NSData dataWithBytes:byte length:sizeof(byte)];
-
- return adddata;
- }
- #pragma mark - 服务器返回数据
- -(void) didServerResultSucces:(JXConnection*)aDownload dict:(NSDictionary*)dict array:(NSArray*)array1{
- if( [aDownload.action isEqualToString:act_TransactionGetCode] ){
-
- // 如果没有code 说明服务器上没有上传公私钥
- if (!dict) {
- // 获取公钥和私钥
- [g_securityUtil generateKeyPairRSA];
- // 获取通用公钥base64
- NSString *publicKeyStr = [g_securityUtil getRSAPublicKeyAsBase64ForJavaServer];
- // 获取私钥data
- NSData *privateKeyData = [g_securityUtil getKeyBitsFromKey:g_securityUtil.privateKeyRef];
- // 私钥aes加密
- NSData *privateAesData = [AESUtil encryptAESData:privateKeyData key:[MD5Util getMD5DataWithString:self.payPassword]];
- NSString *privateAes = [privateAesData base64EncodedStringWithOptions:0];
- // 保存全局aes加密后的私钥
- g_securityUtil.privateAesStr = privateAes;
-
- // 公钥转换为data
- NSData *publicKeyData = [[NSData alloc] initWithBase64EncodedString:publicKeyStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
-
- // mac验签(拼接私钥+公钥)
- NSMutableData *data = [NSMutableData data];
- [data appendData:privateAesData];
- [data appendData:publicKeyData];
-
- // Mac值key
- NSData *aesData = [AESUtil encryptAESData:[g_myself.userId dataUsingEncoding:NSUTF8StringEncoding] key:[MD5Util getMD5DataWithString:self.payPassword]];
- NSString *key = [MD5Util getMD5StringWithData:aesData];
- // 获取Mac值
- NSData *macData = [g_securityUtil getHMACMD5:data key:[key dataUsingEncoding:NSUTF8StringEncoding]];
- NSString *mac = [macData base64EncodedStringWithOptions:0];
- // 上传公钥和私钥 -- Mac验签
- [g_server authkeysUploadPayKeyWithPrivateKey:privateAes publicKey:publicKeyStr mac:mac toView:self];
- }else { // 如果获取到code
- self.code = dict[@"code"];
- self.codeId = dict[@"codeId"];
- if (!g_securityUtil.privateAesStr || g_securityUtil.privateAesStr.length <= 0) {
- // 如果本地没有私钥 去服务器获取已上传的私钥
- [g_server authkeysGetPayPrivateKey:self];
- }else {
- // 如果本地有私钥,调用支付通用接口
- NSString *data = [self getParamStringWithParamDic:self.param time:self.time payPassword:self.payPassword code:dict[@"code"]];
- if (data) {
- if ([self.action isEqualToString:act_payGetQrKey]) {
-
- [g_server payCommonWithAction:self.action code:self.code codeId:self.codeId param:self.param time:self.time payPassword:self.payPassword data:data toView:self];
- }else {
-
- [g_server payCommonWithAction:self.action code:self.code codeId:self.codeId param:self.param time:self.time payPassword:self.payPassword data:data toView:self.toView];
- }
- }
- }
- }
- }
-
- if ([aDownload.action isEqualToString:act_AuthkeysUploadPayKey]) {
-
- // 上传私钥公私钥成功后重新获取code
- NSString* s = [NSUUID UUID].UUIDString;
- s = [[s stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString];
- NSString *salt = s;
- NSString *mac = [self getMacWithSalt:salt payPassword:self.payPassword];
-
- [g_server transactionGetCodeWithSalt:salt mac:mac toView:self];
- }
-
- if ([aDownload.action isEqualToString:act_AuthkeysGetPayPrivateKey]) {
-
- // 从服务器获取公私钥成功后调用支付通用接口
- g_securityUtil.privateAesStr = dict[@"privateKey"];
- NSString *data = [self getParamStringWithParamDic:self.param time:self.time payPassword:self.payPassword code:self.code];
- if (data) {
- if ([self.action isEqualToString:act_payGetQrKey]) {
-
- [g_server payCommonWithAction:self.action code:self.code codeId:self.codeId param:self.param time:self.time payPassword:self.payPassword data:data toView:self];
- }else {
-
- [g_server payCommonWithAction:self.action code:self.code codeId:self.codeId param:self.param time:self.time payPassword:self.payPassword data:data toView:self.toView];
- }
- }
- }
-
-
- if ([aDownload.action isEqualToString:act_payGetQrKey]) {
-
- NSData *codeData = [[NSData alloc] initWithBase64EncodedString:self.code options:NSDataBase64DecodingIgnoreUnknownCharacters];
- codeData = [g_securityUtil decryptMessageRSA:codeData withPrivateKey:g_securityUtil.privateKeyRef];
-
- NSString *dataStr = [dict objectForKey:@"data"];
- NSData *data = [[NSData alloc] initWithBase64EncodedString:dataStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
- NSData *qrKey = [AESUtil decryptAESData:data key:codeData];
- [g_default setObject:qrKey forKey:kMyQRKey];
- if( [self.toView respondsToSelector:@selector(didServerResultSucces:dict:array:)] )
- [self.toView didServerResultSucces:aDownload dict:nil array:nil];
- }
- }
- -(int) didServerResultFailed:(JXConnection*)aDownload dict:(NSDictionary*)dict{
- int n = show_error;
- if ([self.toView respondsToSelector:@selector(didServerResultFailed:dict:)]) {
-
- n = [self.toView didServerResultFailed:aDownload dict:dict];
- }
-
- return n;
- }
- -(int) didServerConnectError:(JXConnection*)aDownload error:(NSError *)error{//error为空时,代表超时
- int n = show_error;
- if ([self.toView respondsToSelector:@selector(didServerConnectError:error:)]) {
- n = [self.toView didServerConnectError:aDownload error:error];
- }
-
- return n;
- }
- -(void) didServerConnectStart:(JXConnection*)aDownload{
- }
- @end
|