ios 微信支付集成

1. 准备

微信平台分为微信公众平台和微信开放平台,公众平台是运营微信公众号的管理系统,开放平台主要针对app、网站开发,提供登录、分享、支付等功能。

注册开放平台之后,新建应用,填写应用信息(Android、iOS等信息),创建之后需要等待审核(这个审核很快的,几个小时就通过了)。

然后是为该应用申请支付功能,要注意个人是无法申请的,具体可参考微信支付申请条件和资格。这里牵涉到一系列公司资质的审核和费用支付,需要几个工作日的时间

完成之后可以获取到appid(微信开放平台为应用生成的唯一识别码)、商户id、商户secretKey。对于app端来说只用到appid,商户id最好通过接口从server获取,商户secretKey是用来签名的,一般只有server能用到。

2. 支付流程

先上一个开放平台给出的流程图:

支付流程.png

这个图很实用很详细很清晰,但一开始看可能会觉得复杂。其实对开发者来说,比较关心的流程是:

app向server发起支付请求

server收到请求后向微信后台调用统一下单API,获得预付单信息

server生成带签名的客户端支付信息并返回给app

用户确认支付,app调起微信客户端进行支付

app获得支付结果后向server查询最终结果并显示

流程了解之后,了解下需要定义的接口和前后端的具体工作:

新接口:

app向server发起请求,获得签名后的app支付信息

app支付之后向server查询支付结果(微信回调的结果不可信,必须以server的结果为准)

app需要做的:

项目接入微信支付sdk

向server请求支付信息

用支付信息调起微信客户端,然后支付

收到微信回调之后向server查询支付结果

根据支付结果展示页面

server需要做的:

收到app端支付请求后调用统一下单API向微信后台获取预支付信息

将app端需要的支付信息签名之后返回给app

接收微信后台回调信息(支付结果),以供app查询

3. iOS开发

开发文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1

下载并运行demo

其实把demo看明白了,直接运用到自己的app里,也不是不可以的

设置项目

在Xcode中,projectName-->Info-->URL Types 添加appid。设置之后才能实现应用间跳转

urltypes.png

导入sdk

sdk.png

如果使用了pod,直接在Podfile中添加pod 'WechatOpenSDK' 然后执行 pod update即可。如果没有使用pod,在添加了sdk文件包之后,需要在pojectName-->General-->Linked Frameworks and Libraries 中添加相应内容

libs.png

代码

AppDelegate.m

didFinishLaunchingWithOptions方法中

[WXApi registerApp:@"wx000999888777"];//注册appid

openUrl、handleOpenURL方法

- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {

return[WXApi handleOpenURL:url delegate:[PaymentManager sharedManager]];}

- (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation {

return[WXApi handleOpenURL:url delegate:[PaymentManager sharedManager]];

}

//NOTE:9.0以后使用新API接口

- (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary *)options{

return[WXApi handleOpenURL:url delegate:[PaymentManager sharedManager]];

}

如果之前项目中使用了友盟等第三方框架,直接并排写就可以:

- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url{    [WXApi handleOpenURL:url delegate:[PaymentAction sharedPayment]];    [UMSocialSnsService handleOpenURL:url];returnYES;}

另外,这个地方的delegate也可以直接设置成nil,表示用当前AppDelegate作为微信支付的代理,这样一来支付回调写在AppDelegate.m中即可。

但不推荐这种做法,我是设置了PaymentManager作为代理,这是项目中专门管理支付的一个类,包括之前的支付宝支付。这也是微信demo中的做法。(支付宝是用block获取回调的,个人感觉代码更紧凑,不容易乱;微信是用的代理,刚开始看晕乎乎的)

PaymentManager

首先是遵守协议WXApiDelegate

然后在PayVC中通过接口获取支付信息

然后调起微信客户端:

- (void)weiXinPayWithDic:(NSDictionary *)wechatPayDic {   

     PayReq *req = [[PayReq alloc] init];   

     req.openID = [wechatPayDic objectForKey:@"appId"];   

     req.partnerId = [wechatPayDic objectForKey:@"partnerId"];  

      req.prepayId = [wechatPayDic objectForKey:@"prepayId"];  

      req.package= [wechatPayDic objectForKey:@"packages"];   

     req.nonceStr = [wechatPayDic objectForKey:@"nonceStr"];   

     req.timeStamp = [[wechatPayDic objectForKey:@"timesTamp"] intValue];

       req.sign = [wechatPayDic objectForKey:@"sign"];  

      [WXApi sendReq:req];

}

这里的数据wechatPayDic一定是server经过二次签名的

回调

// 微信支付返回结果回调

- (void)onResp:(BaseResp *)resp {if([resp isKindOfClass:[PayRespclass]]) {   

             PayResp *response = (PayResp *)resp;

if(_delegate && [_delegate respondsToSelector:@selector(managerDidRecvPaymentResponse:)]) {    

        [_delegate managerDidRecvPaymentResponse:response];      

  }  

  }}

当然前提是在PaymentManager.h中已经定义了代理:

@protocolWXApiManagerDelegate@required

- (void)managerDidRecvPaymentResponse:(PayResp *)response;@end@interfacePaymentManager:NSObject@property(nonatomic,assign)id delegate;

这个代理是用来处理回调结果,展示页面的,所以设置成PayVC控制器

处理回调结果

PayVC.m

遵守协议WXApiManagerDelegate

在viewDidLoad中设置[PaymentManager sharedManager].delegate = self;

- (void)managerDidRecvPaymentResponse:(PayResp *)response {switch(response.errCode) {

caseWXSuccess:                [selfcheckWechatPayResult];break;caseWXErrCodeUserCancel:          

      [[HintManager shareManager] showHint:@"中途取消"];break;default:{        

        [[HintManager shareManager]showHint:@"支付失败"];       

     }break;     

   }}

然后在checkWechatPayResult向server查询支付结果,刷新页面

哦了~~ 泼佛客特

4. 出现的问题

当然了,并不泼佛客特

系统版本大于等于iOS9的,调起微信客户端之后,可以直接点击状态栏左侧按钮返回,这时是不走回调方法的。

这样在支付成功之后,不走回调方法,就无法知道支付状态,当前页面无法给出提示。

解决方案是,在AppDelegate.m的applicationWillEnterForeground方法中,调用查询支付结果接口然后刷新当然页面。需要设置bool变量作为标志,否则每次应用进入前台都去查询,就不符合业务要求了。

进入微信支付页面之后,不做操作,切换到自己应用中,退出当前支付页面,然后再进入微信客户端点击支付或者取消,此时自己的应用会崩溃闪退

原因是退出页面后页面已经出栈被销毁,但wx回调时还是去调用其中的代理方法,就会出现野指针。

解决方法是,在页面的viewWillDisappear方法中加入[PaymentManager sharedManager].delegate = nil;。

5. 需要注意的点

一定设置好scheme,否则应用无法跳转

在调起微信支付使用的PayReq类,一定要用WXApi中自带的类,不要自己创建新类。我之前自己创建的类,定义了同样的变量,同样继承了BaseReq,然并卵,sendReq方法一直返回false

调起微信支付的数据,一定是server经过二次签名的,不要把调用统一下单API获取到的数据直接返给app

虽然类中的变量命名是驼峰式,但签名时的key值全部是小写的,签名时不要忘了后面加上商户key。

6. 签名

可能某些server端由于这样那样的原因不愿意做二次签名,app可以自己做。(不过因为签名需要用到secretKey,让app端做签名是有风险的)

下面是签名代码:

ios 微信支付集成_第1张图片
ios 微信支付集成_第2张图片


个人建议像微信支付、支付宝支付最后都由后台完成,提交相应的数据给后台,让后台生成订单并返回以下参数就可以了,这样微信就会异步通知后台  支付完成后返回APP  由APP直接向后台请求订单支付成功了没有, 这样可以保证支付不会出现一些小问题  


ios 微信支付集成_第3张图片

你可能感兴趣的:(ios 微信支付集成)