IOS中微信支、支付宝支付详解
1. 项目中遇到了微信支付和支付宝支付,现贡献详细代码,具体的参数在代码中都有详细的备注:
9 #import "ITMPay.h" 10 #import "WXApi.h" 11 #import <AlipaySDK/AlipaySDK.h> 12 #import "Order.h"// 13 #import "DataSigner.h"// 14 #import "XMLDictionary.h"//xml解析转换 15 #import "DataMD5.h"//MD5 加密 16 17 #pragma mark - 微信 18 #define WXAppId @"" //appId,申请微信账号时获取的 19 #define WXAppSecret @"" //appSecret 申请app账号时获取 20 #define WXShangHu @"" //申请成功后获取的商户号 21 #define WXMiYue @"" //申请成功后获取的商户密钥 22 23 #pragma mark - 支付宝 24 #define AliShanghuId @"" //申请成功后获取的商户ID 25 #define AliShanghuUser @"" //商户支付宝账号 26 #define AliShanghuMiyue @""//申请成功后获取的商户密钥(私钥) 27 28 @implementation ITMPay 29 30 +(void)payWithType:(OrderPayType)type andDic:(NSMutableDictionary *)dic{ 31 if (type == OrderPayTypeAliy) { 32 [self payWithAliPay:dic]; 33 }else if (type == OrderPayTypeWeixin){ 34 [self payWithWXWith:dic]; 35 } 36 } 37 38 #pragma mark - 39 #pragma mark 支付宝支付 40 /** 41 支付宝的支付步骤 42 * 1. 根据传入的字典获取生成相应的Order,生成[order description] 43 * 2. 根据私钥生成签名器:signer,并将生成的[order description]签名 44 * 3. 根据1、2中生成的结果,做为orderString 45 * 4. 将orderString,和appScheme(此处可以任意字符串)做为参数,调用[AlipaySDK defaultService] payOrder:fromScheme: callback 进行支付 46 */ 47 + (void)payWithAliPay:(NSMutableDictionary *)dic{ 48 NSString *partner = AliShanghuId; 49 NSString *seller = AliShanghuUser; 50 NSString *privateKey = AliShanghuMiyue; 51 52 Order *order = [[Order alloc] init]; 53 order.partner = partner; 54 order.seller = seller; 55 56 order.tradeNO = dic[@"order_id"]; //订单ID(由商家自行制定) 57 order.productName = dic[@"order_title"]; //商品标题 58 order.productDescription = dic[@"order_desc"]; //商品描述 59 order.amount = dic[@"order_price"]; //商品价格 60 61 order.service = @"mobile.securitypay.pay";//支付宝支付服务器名称 62 order.paymentType = @"1"; 63 order.inputCharset = @"utf-8"; 64 order.itBPay = @"30m"; 65 order.showUrl = @"m.alipay.com"; 66 67 NSString *appScheme = @"alisdkdemo"; 68 NSString *orderSpec = [order description]; 69 NSLog(@"orderSpec = %@",orderSpec); 70 71 //获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode 72 id<DataSigner> signer = CreateRSADataSigner(privateKey); 73 NSString *signedString = [signer signString:orderSpec]; 74 75 //将签名成功字符串格式化为订单字符串,请严格按照该格式 76 NSString *orderString = nil; 77 if (signedString != nil) { 78 orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"", 79 orderSpec, signedString, @"RSA"]; 80 81 [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) { 82 83 UIAlertView *aler = [[UIAlertView alloc]initWithTitle:@"提示" message:[resultDic[@"resultStatus"] isEqualToString:@"9000"]? @"交易成功":@"交易失败" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil]; 84 [aler show]; 85 }]; 86 87 } 88 } 89 /** 90 * 和支付宝支付相比,微信支付步骤要复杂些 91 * 1. 配置传入字典的各种参数 92 * 2. 将配置完的字典签名生成sign,并且将这个sign做为传入字典的sign值 93 * 3. 再次将这个dic转换成XML的格式 94 * 4. 将生成的XML格式的字符串做为参数访问微信接口 95 * 5. 将微信服务器返回值,做为sendReq的的Value 96 * 6. 将sendReq.sign进行MD5加密, 97 */ 98 99 #pragma mark 微信支付 100 + (void)payWithWXWith:(NSMutableDictionary *)dic{ 101 [dic setValue:WXAppId forKey:@"appid"]; //APPid 102 [dic setValue:WXShangHu forKey:@"mch_id"];//商户号Id 103 [dic setValue:@"APP" forKey:@"trade_type"];//交易类型 104 105 int value = arc4random(); 106 [dic setValue:[NSString stringWithFormat:@"%d",value] forKey:@"nonce_str"];//随机字符串 107 108 [dic setValue:@"http://10.2.10.122/itm_app/payReturnContrller/Paymentcompletion.htmls" forKey:@"notify_url"];//回调地址 109 110 [dic setValue:@"111.204.81.66" forKey:@"spbill_create_ip"];//终端IP 111 112 //获取签名 113 NSString *sign = [self signWithDic:dic]; 114 [dic setValue:sign forKey:@"sign"];//签名 115 NSString *xml = [dic XMLString];//把签名转成xml格式 116 [self httpWithXml:xml]; 117 } 118 119 #pragma mark - 120 #pragma mark 调用微信支付 121 + (void)httpWithXml:(NSString *)xml{ 122 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 123 124 //这里传入的xml字符串只是形似xml,但是不是正确是xml格式,需要使用af方法进行转义 125 manager.responseSerializer = [[AFHTTPResponseSerializer alloc] init]; 126 [manager.requestSerializer setValue:@"text/xml; charset=GBK" forHTTPHeaderField:@"Content-Type"]; 127 [manager.requestSerializer setValue:@"https://api.mch.weixin.qq.com/pay/unifiedorder" forHTTPHeaderField:@"SOAPAction"]; 128 129 [manager.requestSerializer setQueryStringSerializationWithBlock:^NSString *(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error) { 130 return xml; 131 }]; 132 //发起请求 133 [manager POST:@"https://api.mch.weixin.qq.com/pay/unifiedorder" parameters:xml success:^(AFHTTPRequestOperation *operation, id responseObject) { 134 NSString *responseString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding] ; 135 NSLog(@"responseString is %@",responseString); 136 //将微信返回的xml数据解析转义成字典 137 NSDictionary *dic = [NSDictionary dictionaryWithXMLString:responseString]; 138 //判断返回的许可 139 if ([[dic objectForKey:@"result_code"] isEqualToString:@"SUCCESS"] &&[[dic objectForKey:@"return_code"] isEqualToString:@"SUCCESS"] ) { 140 141 //发起微信支付,设置参数 142 PayReq *request = [[PayReq alloc] init]; 143 request.partnerId = [dic objectForKey:@"mch_id"]; 144 request.prepayId= [dic objectForKey:@"prepay_id"]; 145 request.package = @"Sign=WXPay"; 146 request.nonceStr= [dic objectForKey:@"nonce_str"]; 147 148 //将当前事件转化成时间戳 149 NSDate *datenow = [NSDate date]; 150 NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]]; 151 UInt32 timeStamp =[timeSp intValue]; 152 request.timeStamp= timeStamp; 153 154 //二次签名 155 DataMD5 *md5 = [[DataMD5 alloc] init]; 156 request.sign=[md5 createMD5SingForPay:WXAppId partnerid:request.partnerId prepayid:request.prepayId package:request.package noncestr:request.nonceStr timestamp:request.timeStamp]; 157 // 调用微信 158 [WXApi sendReq:request]; 159 160 }else{ 161 NSLog(@"参数不正确,请检查参数"); 162 } 163 164 } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 165 NSLog(@"error is %@",error); 166 }]; 167 168 } 169 #pragma mark 设置签名 170 + (NSString *)signWithDic:(NSDictionary *)dict{ 171 NSMutableString *contentString =[NSMutableString string]; 172 173 NSArray *keys = [dict allKeys]; 174 // 按字母顺序排序 175 NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 176 return [obj1 compare:obj2 options:NSNumericSearch]; 177 }]; 178 179 for (NSString *categoryId in sortedArray) { 180 if ( ![[dict objectForKey:categoryId] isEqualToString:@""] 181 && ![categoryId isEqualToString:@"sign"] 182 && ![categoryId isEqualToString:@"key"] 183 ) 184 { 185 [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]]; 186 } 187 188 } 189 // 添加key字段 190 [contentString appendFormat:@"key=%@",WXMiYue ]; 191 NSDLog(@"qianming:%@",contentString); 192 193 DataMD5 *md5Sign = [[DataMD5 alloc]initWithAppid:dict[@"appid"] mch_id:dict[@"mch_id"] nonce_str:dict[@"nonce_str"] partner_id:WXMiYue body:dict[@"body"] out_trade_no:dict[@"out_trade_no"] total_fee:dict[@"total_fee"] spbill_create_ip:dict[@"spbill_create_ip"] notify_url:dict[@"notify_url"] trade_type:dict[@"trade_type"]]; 194 NSString *md5Sign1 =[md5Sign getSignForMD5]; 195 196 return md5Sign1; 197 } 198 199 @end