iOS微信APP支付V3版本源码
来源:互联网 发布:球球大作战小糖果软件 编辑:程序博客网 时间:2024/05/18 00:15
之前做微信APP支付的时候,发现微信APP支付版本升级 -----> 申请支付能力成功之后,不再提供APP_KEY这个参数。 去网上找了找demo,发现并没有现成的可以拿来用,只好自己去看微信官方提供的API, 不得不说,这文档给的真的是烂~ 源码在https://github.com/dawnBefore/WeChatPayV3
一. 调用统一下单API
统一下单API(见下图),这里就是要把所有要传的参数POST到红线标的URL去,然后微信会返回给你XML格式的数据,其中就包括我们要拿的prepay_id
1. 拿到签名sign
// 发送给微信的XML格式- (NSString *)genPackage:(NSMutableDictionary*)packageParams{ NSString *sign; NSMutableString *reqPars = [NSMutableString string]; // 生成签名 sign = [self genSign:packageParams]; // 生成xml格式的数据, 作为post给微信的数据 NSArray *keys = [packageParams allKeys]; [reqPars appendString:@"<xml>"]; for (NSString *categoryId in keys) { [reqPars appendFormat:@"<%@>%@</%@>" , categoryId, [packageParams objectForKey:categoryId],categoryId]; } [reqPars appendFormat:@"<sign>%@</sign></xml>", sign]; return [NSString stringWithString:reqPars];}
微信给出的必填的参数有十个(注意:sign这个参数是拿其他的参数通过微信的签名算法得到的,得到sign后加上其余的参数一起POST给上面的URL)
这里我是把其余的九个参数放在字典里,准备签名
NSMutableDictionary *packageParams = [NSMutableDictionary dictionary]; [packageParams setObject: WXAppId forKey:@"appid"]; //开放平台appid [packageParams setObject: WXPartnerId forKey:@"mch_id"]; //商户号 [packageParams setObject: noncestr forKey:@"nonce_str"]; //随机串 [packageParams setObject: orderType forKey:@"trade_type"]; //支付类型,固定为APP [packageParams setObject: orderName forKey:@"body"]; //订单描述,展示给用户 [packageParams setObject: orderNO forKey:@"out_trade_no"];//商户订单号 [packageParams setObject: orderPrice forKey:@"total_fee"]; //订单金额,单位为分 [packageParams setObject: [CommonUtil getIPAddress:YES] forKey:@"spbill_create_ip"];//发器支付的机器ip [packageParams setObject: @"http://weixin.qq.com" forKey:@"notify_url"]; //支付结果异步通知
下面是微信签名的算法
- (NSString *)genSign:(NSDictionary *)signParams{ // 排序, 因为微信规定 ---> 参数名ASCII码从小到大排序 NSArray *keys = [signParams allKeys]; NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { return [obj1 compare:obj2 options:NSNumericSearch]; }]; //生成 ---> 微信规定的签名格式 NSMutableString *sign = [NSMutableString string]; for (NSString *key in sortedKeys) { [sign appendString:key]; [sign appendString:@"="]; [sign appendString:[signParams objectForKey:key]]; [sign appendString:@"&"]; } NSString *signString = [[sign copy] substringWithRange:NSMakeRange(0, sign.length - 1)]; // 拼接API密钥 NSString *result = [NSString stringWithFormat:@"%@&key=%@", signString, WXAPIKey]; // 打印检查 NSLog(@"result = %@", result); // md5加密 NSString *signMD5 = [CommonUtil md5:result]; // 微信规定签名英文大写 signMD5 = signMD5.uppercaseString; // 打印检查 NSLog(@"signMD5 = %@", signMD5); return signMD5;}
2. 拿到签名后,将数据POST给微信,微信要求POST的数据为XML格式
// 发送给微信的XML格式数据- (NSString *)genPackage:(NSMutableDictionary*)packageParams{ NSString *sign; NSMutableString *reqPars = [NSMutableString string]; // 生成签名 sign = [self genSign:packageParams]; // 生成xml格式的数据, 作为post给微信的数据 NSArray *keys = [packageParams allKeys]; [reqPars appendString:@"<xml>"]; for (NSString *categoryId in keys) { [reqPars appendFormat:@"<%@>%@</%@>" , categoryId, [packageParams objectForKey:categoryId],categoryId]; } [reqPars appendFormat:@"<sign>%@</sign></xml>", sign]; return [NSString stringWithString:reqPars];}
3. 微信返回的数据也为XML格式,我这里用的GData解析,大家也可以各显神通,返回中的数据就有我们想要的prepay_id
// 获取prePayId- (NSString *)sendPrepay:(NSMutableDictionary *)prePayParams{ // 获取提交预支付的xml格式数据 NSString *send = [self genPackage:prePayParams]; // 打印检查, 格式应该是xml格式的字符串 NSLog(@"%@", send); // 转换成NSData NSData *data_send = [send dataUsingEncoding:NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:getPrePayIdUrl]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [request setHTTPBody:data_send]; NSError *error = nil; // 拿到data后, 用xml解析, 这里随便用什么方法解析 NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error]; if (!error) { // 1.根据data初始化一个GDataXMLDocument对象 GDataXMLDocument *document = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil]; // 2.拿出根节点 GDataXMLElement *rootElement = [document rootElement]; GDataXMLElement *return_code = [[rootElement elementsForName:@"return_code"] lastObject]; GDataXMLElement *return_msg = [[rootElement elementsForName:@"return_msg"] lastObject]; GDataXMLElement *result_code = [[rootElement elementsForName:@"result_code"] lastObject]; GDataXMLElement *prepay_id = [[rootElement elementsForName:@"prepay_id"] lastObject]; // 如果return_code和result_code都为SUCCESS, 则说明成功 NSLog(@"return_code---%@", [return_code stringValue]); // 返回信息,通常返回一些错误信息 NSLog(@"return_msg---%@", [return_msg stringValue]); NSLog(@"result_code---%@", [result_code stringValue]); // 拿到这个就成功一大半啦 NSLog(@"prepay_id---%@", [prepay_id stringValue]); return [prepay_id stringValue]; } else { return nil; }}
二. 拿到prepay_id后就完成了一大半了,接下来就再次签名调起微信支付就好了
if(prePayid){ NSString *timeStamp = [self genTimeStamp]; // 调起微信支付 PayReq *request = [[PayReq alloc] init]; request.partnerId = WXPartnerId; request.prepayId = prePayid; request.package = @"Sign=WXPay"; request.nonceStr = noncestr; request.timeStamp = [timeStamp intValue]; // 这里要注意key里的值一定要填对, 微信官方给的参数名是错误的,不是第二个字母大写 NSMutableDictionary *signParams = [NSMutableDictionary dictionary]; [signParams setObject: WXAppId forKey:@"appid"]; [signParams setObject: WXPartnerId forKey:@"partnerid"]; [signParams setObject: request.nonceStr forKey:@"noncestr"]; [signParams setObject: request.package forKey:@"package"]; [signParams setObject: timeStamp forKey:@"timestamp"]; [signParams setObject: request.prepayId forKey:@"prepayid"]; //生成签名 NSString *sign = [self genSign:signParams]; //添加签名 request.sign = sign; [WXApi sendReq:request]; } else{ NSLog(@"获取prePayId失败!"); }
附:这里有一些重要的参数大家可能不知道去哪拿, 比如:微信支付商户号(mch_id), API密钥(用于签名拼接在最后面),其实这些应该公司都给好的,大家也不必担心
微信支付商户号:这里有一些申请条件,贴出来给大家看看, 商户号就在申请成功后发给我们的邮件里
API密钥:同时在邮件里面给我们的还有 商户平台登录账号 和 商户平台登录密码 商户平台是另一个平台 这是网址 https://pay.weixin.qq.com/index.php/home/login?return_url=/
好了到这里就结束了,回调什么的按照自己公司的规则来,回调方法微信文档里也都给了,微博没看懂的可以直接下载看源码https://github.com/dawnBefore/WeChatPayV3 ,如果喜欢就随手给个星星吧
- iOS微信APP支付V3版本源码
- 微信支付v3版本之app支付
- V3版本微信支付
- 从零开始微信app支付v3-iOS版
- 微信支付 java 服务端demo (v3版本app支付 springMVC框架中)
- 微信支付 java 服务端demo (v3版本app支付 springMVC框架中)
- 微信支付 java 服务端demo (v3版本app支付 springMVC框架中)
- 微信支付 java 服务端demo (v3版本app支付 springMVC框架中)
- 微信支付 V3版本 错误总结
- iOS 微信V3.0支付小结
- 微信支付V3
- 微信支付V3版本JAVA版本js调用微信支付趟坑路线图
- 微信NATIVE动态支付(V3版本)
- 微信NATIVE静态支付(V3版本)
- 微信支付V3.x版本实例(上)
- 微信支付V3.x版本实例(下)
- 基于springMVC的微信支付(V3版本)
- java调用微信v3版本支付接口
- HDU 2502月之数(递推呀。。。)
- HTML+CSS基础篇(三)——CSS样式基础
- 宏与函数
- Eclipse中自动import包
- 一个数组实现两个栈
- iOS微信APP支付V3版本源码
- 探索推荐引擎内部的秘密,第 2 部分: 深入推荐引擎相关算法 - 协同过滤算法
- java线程一
- Android -- Looper.prepare()和Looper.loop() —深入版
- Java程序员应该具备的知识点
- hrbust 哈理工oj 网线【MST+Prim】
- 目标检测之LBP特征
- Java 进阶 之 抽象类与接口 比较(二)
- 寻找N个数中最大的K个数整理