一、介绍:

现在的消费越来越方便,直接带个手机用各种三方的支付平台进行支付就行,例如微信、支付宝。现在正好我所做的项目中用到了微信支付,今天就来整理一下。

二、准备:

1、去微信官方开发者平台注册开发者账号:https://open.weixin.qq.com

2、然后登陆开发平台:

3、给项目对应的Bundle ID创建应用程序(默认有登陆和分享功能,当然需要花300块钱申请支付功能,一般公司会购买,完成这些操作就是等待审核了,一般一到两个星期就搞定了)

4、审核通过,可以看到如下显示:会生成AppID(很重要,开发时会用到,用来注册微信支付时使用的)

5、选择APP支付方式,参看文档进行集成

6、下载资源包:(一般都是最新的版本,需要在Xocde8.0上编译,我在后面使用的是1.7.1版,在Xcode7.3.1上编译)

7、参考APP端开发步骤,配置属性

(1)我下载的是1.7.1版本,最好手动把SDK拖入到项目中,很简单,主要有四个文件:libWeChatSDK.a静态包、WechatAuthSDK.h、WXApi.h、WXApiObject.h

(2)设置plist网络请求字段(iOS9.0以上需要设置)

(3)添加依赖库后编译,Build success

(4)项目设置APPID.

商户在微信开放平台申请开发APP应用后,微信开放平台会生成APP的唯一标识APPID。在Xcode中打开项目,设置项目属性中的URL Schemes为您的APPID。如图:

(5)进入项目,写代码,注册APPID

商户APP工程中引入微信lib库和头文件,调用API前,需要先向微信注册您的APPID,代码如下:

  1. [WXApi registerApp:@"wxd930xxxxxxxxx" withDescription:@"wxchatpay"]; //注册微信的AppID

(6)商户服务器生成支付订单,先调用【统一下单API】生成预付单,获取到prepay_id后将参数再次签名传输给APP发起支付,给出的参数很多,就不全部截图了。

(7)随机字符串和签名都必须按照微信所给出的算法生成,而且参数都是以xml格式放入到请求正文里

a.随机字符串算法:我们推荐生成随机数算法如下:调用随机数函数生成,将得到的值转换为字符串。

  1. #pragma mark - 产生随机字符串
  2. //生成随机数算法 ,随机字符串,不长于32位
  3. //微信支付API接口协议中包含字段nonce_str,主要保证签名不可预测。
  4. //我们推荐生成随机数算法如下:调用随机数函数生成,将得到的值转换为字符串。
  5. + (NSString *)generateTradeNO {
  6.  
  7. static int kNumber = ;
  8.  
  9. NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  10.  
  11. NSMutableString *resultStr = [[NSMutableString alloc] init];
  12.  
  13. // srand函数是初始化随机数的种子,为接下来的rand函数调用做准备。
  14. // time(0)函数返回某一特定时间的小数值。
  15. // 这条语句的意思就是初始化随机数种子,time函数是为了提高随机的质量(也就是减少重复)而使用的。
  16.  
  17. // srand(time(0)) 就是给这个算法一个启动种子,也就是算法的随机种子数,有这个数以后才可以产生随机数,用1970.1.1至今的秒数,初始化随机数种子。
  18. // Srand是种下随机种子数,你每回种下的种子不一样,用Rand得到的随机数就不一样。为了每回种下一个不一样的种子,所以就选用Time(0),Time(0)是得到当前时时间值(因为每时每刻时间是不一样的了)。
  19.  
  20. srand((unsigned int)time());
  21.  
  22. for (int i = ; i < kNumber; i++) {
  23.  
  24. unsigned index = rand() % [sourceStr length];
  25.  
  26. NSString *oneStr = [sourceStr substringWithRange:NSMakeRange(index, )];
  27.  
  28. [resultStr appendString:oneStr];
  29. }
  30. return resultStr;
  31. }

b.签名生成算法查看链接:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3

也可以模拟签名生成接口,作为一次性测试使用:https://pay.weixin.qq.com/wiki/tools/signverify/,需要填写对应的字段参数,点击生成即可:如图

c、填写参数,使用AFN,进行统一下单,最终的所有的参数统一为xml,不是json,格式如下:

d、返回发送下单请求后的反馈结果:

 

统一下单代码:

  1. // 交易类型
  2. #define TRADE_TYPE @"APP"
  3.  
  4. // 交易结果通知网站此处用于测试,随意填写,正式使用时填写正确网站
  5. #define NOTIFY_URL @"http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php"
  6.  
  7. // 交易价格1表示0.01元,10表示0.1元
  8. #define PRICE @"1"
  9.  
  10. #pragma mark 客户端操作/ 实际操作由服务端操作
  11.  
  12. // 随机字符串变量 这里最好使用和安卓端一致的生成逻辑
  13. NSString *tradeNO = [self generateTradeNO];
  14.  
  15. // 设备IP地址,请在wifi环境下测试,否则获取的ip地址为error,正确格式应该是8.8.8.8
  16. //NSString *addressIP = [self fetchIPAddress];
  17. NSString *addressIP = [[IPToolManager sharedManager] currentIpAddress];
  18.  
  19. // 随机产生订单号用于测试,正式使用请换成你从自己服务器获取的订单号
  20. NSString *orderno = [NSString stringWithFormat:@"%ld",time()];
  21.  
  22. // 获取SIGN签名
  23. DataMD5 *data = [[DataMD5 alloc] initWithAppid:WX_APPID mch_id:MCH_ID nonce_str:tradeNO partner_id:WX_PartnerKey body:@"充值" out_trade_no:orderno total_fee:PRICE spbill_create_ip:addressIP notify_url:NOTIFY_URL trade_type:TRADE_TYPE];
  24.  
  25. // 转换成XML字符串,这里知识形似XML,实际并不是正确的XML格式,需要使用AF方法进行转义
  26. NSString *string = [[data dic] XMLString];
  27.  
  28. AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
  29. // 这里传入的XML字符串只是形似XML,但不是正确是XML格式,需要使用AF方法进行转义
  30. session.responseSerializer = [[AFHTTPResponseSerializer alloc] init];
  31. [session.requestSerializer setValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
  32. [session.requestSerializer setValue:WXUNIFIEDORDERURL forHTTPHeaderField:@"SOAPAction"];
  33. [session.requestSerializer setQueryStringSerializationWithBlock:^NSString *(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error) {
  34. return string;
  35. }];
  36. [session POST:WXUNIFIEDORDERURL parameters:string progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
  37.  
  38. // 输出XML数据
  39. NSString *responseString = [[NSString alloc] initWithData:responseObject
  40. encoding:NSUTF8StringEncoding] ;
  41. // 将微信返回的xml数据解析转义成字典
  42. NSDictionary *dic = [NSDictionary dictionaryWithXMLString:responseString];
  43.  
  44. // 判断返回的许可
  45. if ([[dic objectForKey:@"result_code"] isEqualToString:@"SUCCESS"]
  46. &&[[dic objectForKey:@"return_code"] isEqualToString:@"SUCCESS"] ) {
  47. //这里面调起支付 (就是下面的第8步)
  48. //............pay code.......
  49. }
  50. } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
  51. NSLog(@"%@",error);
  52. }];

(8)下单成功后,调起支付

  1. // 发起微信支付,设置参数
  2. PayReq *request = [[PayReq alloc] init];
  3. request.openID = [dic objectForKey:WXAPPID];
  4. request.partnerId = [dic objectForKey:WXMCHID];
  5. request.prepayId= [dic objectForKey:WXPREPAYID];
  6. request.package = @"Sign=WXPay";
  7. request.nonceStr= [dic objectForKey:WXNONCESTR];
  8.  
  9. // 将当前时间转化成时间戳
  10. NSDate *datenow = [NSDate date];
  11. NSString *timeSp = [NSString stringWithFormat:@"%ld", (long)[datenow timeIntervalSince1970]];
  12. UInt32 timeStamp =[timeSp intValue];
  13. request.timeStamp= timeStamp;
  14.  
  15. // 签名加密
  16. DataMD5 *md5 = [[DataMD5 alloc] init];
  17. request.sign=[md5 createMD5SingForPay:request.openID
  18. partnerid:request.partnerId
  19. prepayid:request.prepayId
  20. package:request.package
  21. noncestr:request.nonceStr
  22. timestamp:request.timeStamp];
  23.  
  24. // 调用微信
  25. [WXApi sendReq:request];

支付的接口参数和返回结果截图如下:

(9)设置支付代理,可以设置APPDelegate为代理,也可以自己创下创建单例工具类作为代理,处理支付回调结果。照微信SDK Sample,在类实现onResp函数,支付完成后,微信APP会返回到商户APP并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码,如果支付成功则去后台查询支付结果再展示用户实际支付结果。注意 一定不能以客户端返回作为用户支付的结果,应以服务器端的接收的支付通知或查询API返回的结果为准。代码示例如下:

  1. -(void)onResp:(BaseResp*)resp{
  2. if ([respisKindOfClass:[PayRespclass]]){
  3. PayResp*response=(PayResp*)resp;
  4. switch(response.errCode){
  5. caseWXSuccess
  6. //服务器端查询支付通知或查询API返回的结果再提示成功
  7. NSlog(@"支付成功");
  8. break;
  9. default
  10. NSlog(@"支付失败,retcode=%d",resp.errCode);
  11. break;
  12. }
  13. }
  14. }

好了,大致差不多就可以了,下面是我用真机测试的结果,测试宏定义设置的一分钱:点击绿色的微信支付按钮

 

(10)demo

本人demo地址如下(demo中需要在pch文件和info.plist文件设置appID等属性):https://github.com/xiayuanquan/WXChatPay

另外ip地址的获取也很重要,本人demo地址:https://github.com/xiayuanquan/IP_Test

借鉴的支付demo(demo中需要在pch文件和info.plist文件设置appID等属性):https://github.com/lyoniOS/WxPayDemo

参考博客地址:

http://www.jianshu.com/p/af8cbc9d51b0

http://blog.csdn.net/qq_22080737/article/details/51984801

iOS: 实现微信支付的更多相关文章

  1. 关于IOS调用微信支付jsapi不起作用的解决方法

    微信支付时,安卓机调用 jsapi可以支付,IOS就不行,点击立即支付,直接返回原立即支付页面,跟刷新页面差不多,解决方案很简单:两句话而已. 不得不说,微信支付坑太多了,我擦..... <sc ...

  2. iOS之微信支付

    前言:下面介绍微信支付的开发流程的细节,图文并茂,你可以按照我的随笔流程过一遍代码.包你也学会了微信支付.而且支付也是面试常问的内容. 正文: 1.首先在开始使用微信支付之前,有一些东西是开发者必须要 ...

  3. iOS - WXPay 微信支付

    1.微信支付申请 微信支付官方集成指引 微信支付官方集成指导视频 微信 APP 支付开发者文档 微信公众平台 微信开放平台 微信商户平台 1.1 微信 APP 支付申请步骤 APP 支付:APP 支付 ...

  4. IOS开发--微信支付

    前言:下面介绍微信支付的开发流程的细节,图文并茂,你可以按照我的随笔流程过一遍代码.包你也学会了微信支付.而且支付也是面试常问的内容. 正文: 1.首先在开始使用微信支付之前,有一些东西是开发者必须要 ...

  5. iOS开发微信支付

    现在基本所有的App都会接入支付宝支付以及微信支付,也有很多第三方提供给你 SDK帮你接入,但是这种涉及到支付的东西还是自己服务器搞来的好一些,其实搞懂了 逻辑非常的简单,下面直接给大家说说下基本流程 ...

  6. iOS 集成微信支付【转载】

    目前项目里有微信支付的需求,调研过一段时间后,发现其实并没有想象中的那么困难.如果你只是想实现该功能,一个方法足以,但是若你想深入了解实现原理.就需要花费更多的功夫了.目前我只清楚微信支付需要做签名, ...

  7. iOS集成微信支付

    微信支付的开发 前言:之前听说过微信支付有很多坑,其实没有想象的那么坑,整体感觉很容易上手,按照它的流程来不会有错!PS:官方的流程看的TMD烦,好啦,废话有点多,进入开发.(ps:每个微信的版本一直 ...

  8. iOS开发微信支付的介绍与实现

    1.前期准备 1) 到微信开放平台注册账号 需要登录邮箱验证 填写您的商户信息 2) 进入管理中心 --- 移动应用 --- 创建移动应用 --- 根据页面完善应用资料 3) 审核过后,通过应用详情页 ...

  9. iOS集成微信支付各种坑收录

    统一下单的参数要拼接成XML格式,使用AFN请求时要对参数转义,直接传入字典给AFN无法识别(这个接口微信demo中并没有提供示例) AFHTTPRequestOperationManager *ma ...

随机推荐

  1. mysql5.6安装

    mysql5.6安装 #卸载原有的mysqlyum remove mysql*ls /etc/my.cnf*mv /etc/my.cnf* /tmp/ #安装依赖包yum install make c ...

  2. Cdn加速

    http://www.bootcdn.cn/ http://cdn.code.baidu.com/ backbone <script src="https://cdn.bootcss. ...

  3. 以下是关于Controller的一些Hint

    在经过路由分发之后,实际的应用Controller接管用户的所有请求,并负责与用户数据的交互.CI中所有的应用控制器都应该是CI_Controller的子类(除非你扩展了CI的核心,那么你的Contr ...

  4. [转]禁用和启用链接(a元素|LinkButton)的js方法

    本文转自:http://www.cnblogs.com/beiguren/archive/2010/05/24/1742926.html 在Asp.net中,有时候需要禁用掉一个a链接元素. 在服务器 ...

  5. 【新产品发布】【EVC8001 磁耦隔离式 USB 转 RS-485】

    EVC8001 是 XiaomaGee 团队打造的精品级 USB 转 RS-485 隔离转换器,全部采用最优方案,每个细节均做到最优化.最佳化.亮点举不胜举: ==================== ...

  6. Scrum会议3(Beta版本)

    组名:天天向上 组长:王森 组员:张政.张金生.林莉.胡丽娜 代码地址:HTTPS:https://git.coding.net/jx8zjs/llk.git SSH:git@git.coding.n ...

  7. maven-surefire-plugin总结

    Maven通过Maven Surefire Plugin插件执行单元测试.(通过Maven Failsafe Plugin插件执行集成测试) 在pom.xml中配置JUnit,TestNG测试框架的依 ...

  8. Javascript 笔记与总结(2-11)暴力操作节点

    innerHTML 代表节点内的内容,能读能写 虽然不是 W3C 规定的标准,但是各浏览器都支持得很好 [例] <!DOCTYPE html> <html lang="en ...

  9. SnapKit代码约束

    let label = UILabel() label.frame = CGRectMake(, , , ) label.backgroundColor = UIColor.cyanColor() l ...

  10. Lazarus开发平台编译后的可执行程序的减肥方法

    1.在“工程”菜单下,单击“工程选项”,原始状态的界面为: 2.将界面中的两个选项修改为如下: 3.按“确定”按钮,即可 编译以后的可执行程序就将又原来的14m变为1.66m. 1.选择: Proje ...