iOS实现H5支付(微信、支付宝)原生封装
前言
支付分APP支付、H5支付、扫码支付等。app支付一般在app中使用,并且需要集成相应的支付SDK,H5支付多用于网页。如果你的APP不想集成支付SDK,又想实现支付功能,你可以在项目中使用H5支付。本文主要讲述如何将H5支付封装成一个原生可调用的组件。
1.H5支付流程
注:以下为网页H5支付流程,原生调用需要修改部分流程
1.1微信支付
- 统一下单,获取微信中间页地址mweb_url
- 页面重定向到微信中间页
- 微信中间页发起支付请求
- safari浏览器拦截支付请求打开微信APP开始支付(如果在app中,需要在shouldStartLoadWithRequest:方法里面拦截支付请求,并打开微信)
微信中间页重新向到redirect_url
1.2支付宝支付
- 发起网页支付请求,H5为一个form表单提交。
- 页面重定向到支付宝收银台页面
- 发起APP支付请求,并且开始倒计时,如果打开支付宝超时页面跳转到网页支付界面,如果唤起支付宝,倒计时结束。
- 支付完毕页面跳转到return_url页面,需用户手动触发。
2.原生封装思路
新开一个webView加载支付中间页,拦截中间页支付请求并唤起支付,然后关闭webView流程结束。
webView需要加到window(或者当前控制器的view上),并设置一个大小(肉眼不可见就行)。因为使用wkwebview时,webView不显示的情况下,H5请求会被挂起,会导致支付宝页面不能唤起支付请求。
3.代码实现
具体步骤见代码注释
@interfaceHJH5WebPayManager()@property(nonatomic,strong)UIWebView*payWebview; @property(nonatomic,strong)void(^sendPayResult)(HJH5SendWebPayResult); @end @implementationHJH5WebPayManager +(instancetype)sharedInstance{ staticdispatch_once_tonce; staticHJH5WebPayManager*_instace=nil; dispatch_once(&once,^{ _instace=[[selfalloc]init]; }); return_instace; } -(void)loadWebPayTransitionPage:(NSString*)htmlhandleBlock:(void(^)(HJH5SendWebPayResult))handle{ NSMutableURLRequest*request=nil; if([htmlhasPrefix:@"https://wx.tenpay.com"]){ //微信安全域名 NSString*wxScheme=@""; NSString*referer=[NSStringstringWithFormat:@"%@://",wxScheme]; //将redirect_url替换成scheme,微信支付完毕才能跳回APP,否则会打开Safari浏览器(因为redirect_url一般为一个HTTP的地址) NSRangerange=[htmlrangeOfString:@"redirect_url="]; NSString*reqUrl; if(range.length>0){ reqUrl=[htmlsubstringToIndex:range.location+range.length]; reqUrl=[reqUrlstringByAppendingString:referer]; }else{ reqUrl=[htmlstringByAppendingString:[NSStringstringWithFormat:@"&redirect_url=%@",referer]]; } request=[NSMutableURLRequestrequestWithURL:[NSURLURLWithString:reqUrl]cachePolicy:NSURLRequestUseProtocolCachePolicytimeoutInterval:60.0]; //设置授权域名,伪造Referer头,因为微信中间页会检验Referer头,并且Referer对应的值需要包含安全域名 [requestsetValue:refererforHTTPHeaderField:@"Referer"]; if(self.payWebview){ [self.payWebviewremoveFromSuperview]; self.payWebview=nil; } self.payWebview=[[UIWebViewalloc]initWithFrame:CGRectMake(0,0,0.1,0.1)]; self.sendPayResult=handle; [[UIApplicationsharedApplication].keyWindowaddSubview:self.payWebview]; self.payWebview.delegate=self; [self.payWebviewloadRequest:request]; }elseif([htmlhasPrefix:@"