JXPayServer.m 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. //
  2. // JXPayServer.m
  3. // shiku_im
  4. //
  5. // Created by p on 2019/7/16.
  6. // Copyright © 2019 Reese. All rights reserved.
  7. //
  8. #import "JXPayServer.h"
  9. #import "MD5Util.h"
  10. #import "AESUtil.h"
  11. @interface JXPayServer()
  12. @property (nonatomic, copy) NSString *action;
  13. @property (nonatomic, weak) id toView;
  14. @property (nonatomic, copy) NSString *payPassword;
  15. @property (nonatomic, copy) NSString *code;
  16. @property (nonatomic, copy) NSString *codeId;
  17. @property (nonatomic, assign) long time;
  18. @property (nonatomic, strong) NSMutableArray *param;
  19. @property (nonatomic, assign) NSInteger verifyNum;
  20. @end
  21. @implementation JXPayServer
  22. +(instancetype)sharedManager {
  23. static dispatch_once_t onceToken;
  24. static JXPayServer *instance;
  25. dispatch_once(&onceToken, ^{
  26. instance = [[JXPayServer alloc] init];
  27. });
  28. return instance;
  29. }
  30. - (instancetype)init {
  31. if ([super init]) {
  32. }
  33. return self;
  34. }
  35. - (void)payServerWithAction:(NSString *)action param:(NSMutableArray *)param payPassword:(NSString *)payPassword time:(long)time toView:(id)toView{
  36. self.action = action;
  37. self.toView = toView;
  38. self.payPassword = payPassword;
  39. self.time = time;
  40. self.param = param;
  41. // 参数salt为随机UUID字符串,确保每次的mac都不同
  42. NSString* s = [NSUUID UUID].UUIDString;
  43. s = [[s stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString];
  44. NSString *salt = s;
  45. // 获取Mac值
  46. NSString *mac = [self getMacWithSalt:salt payPassword:payPassword];
  47. // 获取临时密码
  48. [g_server transactionGetCodeWithSalt:salt mac:mac toView:self];
  49. }
  50. // 获取mac值
  51. - (NSString *)getMacWithSalt:(NSString *)salt payPassword:(NSString *)payPassword {
  52. NSMutableString *str = [NSMutableString string];
  53. [str appendString:APIKEY];
  54. [str appendString:g_myself.userId];
  55. [str appendString:g_server.access_token];
  56. [str appendString:salt];
  57. NSData *aesData = [AESUtil encryptAESData:[g_myself.userId dataUsingEncoding:NSUTF8StringEncoding] key:[MD5Util getMD5DataWithString:payPassword]];
  58. NSData *macData = [g_securityUtil getHMACMD5:[str dataUsingEncoding:NSUTF8StringEncoding] key:[[MD5Util getMD5StringWithData:aesData] dataUsingEncoding:NSUTF8StringEncoding]];
  59. NSString *mac = [macData base64EncodedStringWithOptions:0];
  60. return mac;
  61. }
  62. - (NSString *)getParamStringWithParamDic:(NSMutableArray *)param time:(long)time payPassword:(NSString *)payPassword code:(NSString *)code {
  63. NSMutableString *str1 = [NSMutableString string];
  64. [str1 appendString:APIKEY];
  65. [str1 appendString:g_myself.userId];
  66. [str1 appendString:g_server.access_token];
  67. NSMutableString *str2 = [NSMutableString string];
  68. NSMutableDictionary *dict = [NSMutableDictionary dictionary];
  69. NSString *key;
  70. for (NSInteger i = 0; i < param.count; i ++) {
  71. if (i % 2 == 0) {
  72. key = param[i];
  73. }else {
  74. [str2 appendString:param[i]];
  75. [dict setObject:param[i] forKey:key];
  76. }
  77. }
  78. [dict setObject:[NSNumber numberWithLong:time] forKey:@"time"];
  79. NSMutableString *str3 = [NSMutableString string];
  80. [str3 appendString:[NSString stringWithFormat:@"%ld",time]];
  81. NSData *aesData = [AESUtil encryptAESData:[g_myself.userId dataUsingEncoding:NSUTF8StringEncoding] key:[MD5Util getMD5DataWithString:payPassword]];
  82. NSString *aesMd5Str = [MD5Util getMD5StringWithData:aesData];
  83. [str3 appendString:aesMd5Str];
  84. NSMutableString *str = [NSMutableString string];
  85. [str appendString:str1];
  86. [str appendString:str2];
  87. [str appendString:str3];
  88. if (!g_securityUtil.privateKeyRef) {
  89. NSData *privateAesData = [[NSData alloc] initWithBase64EncodedString:g_securityUtil.privateAesStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
  90. NSData *privateData = [AESUtil decryptAESData:privateAesData key:[MD5Util getMD5DataWithString:payPassword]];
  91. NSString *privateBase64 = [privateData base64EncodedStringWithOptions:0];
  92. g_securityUtil.privateKeyRef = [g_securityUtil getRSAKeyWithBase64Str:privateBase64 isPrivateKey:YES];
  93. // 如果私钥解密失败,重新获取code、清除本地私钥、重新获取私钥
  94. if (!g_securityUtil.privateKeyRef) {
  95. if (self.verifyNum > 5) {
  96. self.verifyNum = 0;
  97. [JXMyTools showTipView:@"code解密失败"];
  98. return nil;
  99. }
  100. g_securityUtil.privateAesStr = @"";
  101. // 参数salt为随机UUID字符串,确保每次的mac都不同
  102. NSString* s = [NSUUID UUID].UUIDString;
  103. s = [[s stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString];
  104. NSString *salt = s;
  105. // 获取Mac值
  106. NSString *mac = [self getMacWithSalt:salt payPassword:payPassword];
  107. // 获取临时密码
  108. [g_server transactionGetCodeWithSalt:salt mac:mac toView:self];
  109. self.verifyNum ++;
  110. return nil;
  111. }
  112. }
  113. NSData *codeData = [[NSData alloc] initWithBase64EncodedString:code options:NSDataBase64DecodingIgnoreUnknownCharacters];
  114. NSData *deCodeData = [g_securityUtil decryptMessageRSA:codeData];
  115. // 如果code解密失败,重新获取code、清除本地私钥、重新获取私钥
  116. if (!deCodeData) {
  117. if (self.verifyNum > 5) {
  118. self.verifyNum = 0;
  119. [JXMyTools showTipView:@"code解密失败"];
  120. return nil;
  121. }
  122. g_securityUtil.privateAesStr = @"";
  123. // 参数salt为随机UUID字符串,确保每次的mac都不同
  124. NSString* s = [NSUUID UUID].UUIDString;
  125. s = [[s stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString];
  126. NSString *salt = s;
  127. // 获取Mac值
  128. NSString *mac = [self getMacWithSalt:salt payPassword:payPassword];
  129. // 获取临时密码
  130. [g_server transactionGetCodeWithSalt:salt mac:mac toView:self];
  131. self.verifyNum ++;
  132. return nil;
  133. }
  134. NSString *deCodeBase = [deCodeData base64EncodedStringWithOptions:0];
  135. // NSData *macData = [g_securityUtil getHMACMD5:[str dataUsingEncoding:NSUTF8StringEncoding] key:deCodeData];
  136. // NSString *mac = [macData base64EncodedStringWithOptions:0];
  137. NSString *mac = [g_securityUtil getSignWithRSA:str withPriKey:g_securityUtil.privateKeyRef];
  138. [dict setObject:mac forKey:@"mac"];
  139. SBJsonWriter * OderJsonwriter = [SBJsonWriter new];
  140. NSString * jsonString = [OderJsonwriter stringWithObject:dict];
  141. NSData *aesJsonData = [AESUtil encryptAESData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] key:deCodeData];
  142. return [aesJsonData base64EncodedStringWithOptions:0];
  143. }
  144. // 获取二维码付款哈希值
  145. - (NSData *)getQRCodeHash {
  146. long time = (long)[[NSDate date] timeIntervalSince1970];
  147. time = (time *1000 + g_server.timeDifference)/1000; // 秒
  148. time = time / 60; //精确到分钟
  149. NSData *randByte = [self getDataWithInt:g_payServer.randNum];
  150. NSData *da = [randByte subdataWithRange:NSMakeRange(randByte.length - 1, 1)];
  151. Byte bRand[1];
  152. [da getBytes:bRand length:sizeof(bRand)];
  153. int rand = bRand[0];
  154. NSMutableString *value = [NSMutableString string];
  155. [value appendString:APIKEY];
  156. [value appendString:g_myself.userId];
  157. [value appendString:[NSString stringWithFormat:@"%d", rand]];
  158. [value appendString:[NSString stringWithFormat:@"%ld", time]];
  159. NSData *qrKey = [g_default objectForKey:kMyQRKey];
  160. NSData *macData = [g_securityUtil getHMACMD5:[value dataUsingEncoding:NSUTF8StringEncoding] key:qrKey];
  161. return macData;
  162. }
  163. // 获取opt算法
  164. - (unsigned int)getQRCodeOpt {
  165. g_payServer.randNum ++;
  166. NSData *hash = [self getQRCodeHash];
  167. NSData *randByte = [self getDataWithInt:g_payServer.randNum];
  168. NSData *da = [randByte subdataWithRange:NSMakeRange(randByte.length - 1, 1)];
  169. NSMutableData *optData = [NSMutableData data];
  170. NSData *hashSubData = [hash subdataWithRange:NSMakeRange(0, 3)];
  171. [optData appendData:hashSubData];
  172. [optData appendData:da];
  173. unsigned int opt;
  174. [optData getBytes:&opt length:sizeof(opt)];
  175. return opt;
  176. }
  177. // 获取qrCode
  178. - (NSString *) getQrCode {
  179. unsigned int opt = [self getQRCodeOpt];
  180. NSInteger userId = [g_myself.userId integerValue];
  181. long long num = userId << 32;
  182. long long qrCode = num + opt;
  183. NSMutableString *qrCodeStr = [NSMutableString stringWithFormat:@"%lld", qrCode];
  184. while (qrCodeStr.length < 19) {
  185. [qrCodeStr insertString:@"0" atIndex:0];
  186. }
  187. return qrCodeStr;
  188. }
  189. - (NSData *) getDataWithInt:(int)num {
  190. Byte b1=num & 0xff;
  191. Byte b2=(num>>8) & 0xff;
  192. Byte b3=(num>>16) & 0xff;
  193. Byte b4=(num>>24) & 0xff;
  194. Byte byte[] = {b4,b3,b2,b1};
  195. NSData *adddata = [NSData dataWithBytes:byte length:sizeof(byte)];
  196. return adddata;
  197. }
  198. #pragma mark - 服务器返回数据
  199. -(void) didServerResultSucces:(JXConnection*)aDownload dict:(NSDictionary*)dict array:(NSArray*)array1{
  200. if( [aDownload.action isEqualToString:act_TransactionGetCode] ){
  201. // 如果没有code 说明服务器上没有上传公私钥
  202. if (!dict) {
  203. // 获取公钥和私钥
  204. [g_securityUtil generateKeyPairRSA];
  205. // 获取通用公钥base64
  206. NSString *publicKeyStr = [g_securityUtil getRSAPublicKeyAsBase64ForJavaServer];
  207. // 获取私钥data
  208. NSData *privateKeyData = [g_securityUtil getKeyBitsFromKey:g_securityUtil.privateKeyRef];
  209. // 私钥aes加密
  210. NSData *privateAesData = [AESUtil encryptAESData:privateKeyData key:[MD5Util getMD5DataWithString:self.payPassword]];
  211. NSString *privateAes = [privateAesData base64EncodedStringWithOptions:0];
  212. // 保存全局aes加密后的私钥
  213. g_securityUtil.privateAesStr = privateAes;
  214. // 公钥转换为data
  215. NSData *publicKeyData = [[NSData alloc] initWithBase64EncodedString:publicKeyStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
  216. // mac验签(拼接私钥+公钥)
  217. NSMutableData *data = [NSMutableData data];
  218. [data appendData:privateAesData];
  219. [data appendData:publicKeyData];
  220. // Mac值key
  221. NSData *aesData = [AESUtil encryptAESData:[g_myself.userId dataUsingEncoding:NSUTF8StringEncoding] key:[MD5Util getMD5DataWithString:self.payPassword]];
  222. NSString *key = [MD5Util getMD5StringWithData:aesData];
  223. // 获取Mac值
  224. NSData *macData = [g_securityUtil getHMACMD5:data key:[key dataUsingEncoding:NSUTF8StringEncoding]];
  225. NSString *mac = [macData base64EncodedStringWithOptions:0];
  226. // 上传公钥和私钥 -- Mac验签
  227. [g_server authkeysUploadPayKeyWithPrivateKey:privateAes publicKey:publicKeyStr mac:mac toView:self];
  228. }else { // 如果获取到code
  229. self.code = dict[@"code"];
  230. self.codeId = dict[@"codeId"];
  231. if (!g_securityUtil.privateAesStr || g_securityUtil.privateAesStr.length <= 0) {
  232. // 如果本地没有私钥 去服务器获取已上传的私钥
  233. [g_server authkeysGetPayPrivateKey:self];
  234. }else {
  235. // 如果本地有私钥,调用支付通用接口
  236. NSString *data = [self getParamStringWithParamDic:self.param time:self.time payPassword:self.payPassword code:dict[@"code"]];
  237. if (data) {
  238. if ([self.action isEqualToString:act_payGetQrKey]) {
  239. [g_server payCommonWithAction:self.action code:self.code codeId:self.codeId param:self.param time:self.time payPassword:self.payPassword data:data toView:self];
  240. }else {
  241. [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];
  242. }
  243. }
  244. }
  245. }
  246. }
  247. if ([aDownload.action isEqualToString:act_AuthkeysUploadPayKey]) {
  248. // 上传私钥公私钥成功后重新获取code
  249. NSString* s = [NSUUID UUID].UUIDString;
  250. s = [[s stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString];
  251. NSString *salt = s;
  252. NSString *mac = [self getMacWithSalt:salt payPassword:self.payPassword];
  253. [g_server transactionGetCodeWithSalt:salt mac:mac toView:self];
  254. }
  255. if ([aDownload.action isEqualToString:act_AuthkeysGetPayPrivateKey]) {
  256. // 从服务器获取公私钥成功后调用支付通用接口
  257. g_securityUtil.privateAesStr = dict[@"privateKey"];
  258. NSString *data = [self getParamStringWithParamDic:self.param time:self.time payPassword:self.payPassword code:self.code];
  259. if (data) {
  260. if ([self.action isEqualToString:act_payGetQrKey]) {
  261. [g_server payCommonWithAction:self.action code:self.code codeId:self.codeId param:self.param time:self.time payPassword:self.payPassword data:data toView:self];
  262. }else {
  263. [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];
  264. }
  265. }
  266. }
  267. if ([aDownload.action isEqualToString:act_payGetQrKey]) {
  268. NSData *codeData = [[NSData alloc] initWithBase64EncodedString:self.code options:NSDataBase64DecodingIgnoreUnknownCharacters];
  269. codeData = [g_securityUtil decryptMessageRSA:codeData withPrivateKey:g_securityUtil.privateKeyRef];
  270. NSString *dataStr = [dict objectForKey:@"data"];
  271. NSData *data = [[NSData alloc] initWithBase64EncodedString:dataStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
  272. NSData *qrKey = [AESUtil decryptAESData:data key:codeData];
  273. [g_default setObject:qrKey forKey:kMyQRKey];
  274. if( [self.toView respondsToSelector:@selector(didServerResultSucces:dict:array:)] )
  275. [self.toView didServerResultSucces:aDownload dict:nil array:nil];
  276. }
  277. }
  278. -(int) didServerResultFailed:(JXConnection*)aDownload dict:(NSDictionary*)dict{
  279. int n = show_error;
  280. if ([self.toView respondsToSelector:@selector(didServerResultFailed:dict:)]) {
  281. n = [self.toView didServerResultFailed:aDownload dict:dict];
  282. }
  283. return n;
  284. }
  285. -(int) didServerConnectError:(JXConnection*)aDownload error:(NSError *)error{//error为空时,代表超时
  286. int n = show_error;
  287. if ([self.toView respondsToSelector:@selector(didServerConnectError:error:)]) {
  288. n = [self.toView didServerConnectError:aDownload error:error];
  289. }
  290. return n;
  291. }
  292. -(void) didServerConnectStart:(JXConnection*)aDownload{
  293. }
  294. @end