前言
支付分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.代码实现
具体步骤见代码注释
@interface HJH5WebPayManager()@property (nonatomic,strong) UIWebView *payWebview; @property (nonatomic,strong) void(^sendPayResult)(HJH5SendWebPayResult); @end @implementation HJH5WebPayManager +(instancetype)sharedInstance{ static dispatch_once_t once ; static HJH5WebPayManager *_instace = nil; dispatch_once(&once, ^{ _instace = [[self alloc] init]; }); return _instace; } -(void)loadWebPayTransitionPage:(NSString *)html handleBlock:(void (^)(HJH5SendWebPayResult))handle{ NSMutableURLRequest *request = nil; if ([html hasPrefix:@"https://wx.tenpay.com"]) { //微信安全域名 NSString *wxScheme = @""; NSString *referer = [NSString stringWithFormat:@"%@://",wxScheme]; //将redirect_url替换成scheme,微信支付完毕才能跳回APP,否则会打开Safari浏览器(因为redirect_url一般为一个HTTP的地址) NSRange range = [html rangeOfString:@"redirect_url="]; NSString *reqUrl; if (range.length>0) { reqUrl = [html substringToIndex:range.location+range.length]; reqUrl = [reqUrl stringByAppendingString:referer]; }else{ reqUrl = [html stringByAppendingString:[NSString stringWithFormat:@"&redirect_url=%@",referer]]; } request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:reqUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; //设置授权域名,伪造Referer头,因为微信中间页会检验Referer头,并且Referer对应的值需要包含安全域名 [request setValue:referer forHTTPHeaderField:@"Referer"]; if (self.payWebview) { [self.payWebview removeFromSuperview]; self.payWebview = nil; } self.payWebview = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 0.1, 0.1)]; self.sendPayResult = handle; [[UIApplication sharedApplication].keyWindow addSubview:self.payWebview]; self.payWebview.delegate = self; [self.payWebview loadRequest:request]; }else if ([html hasPrefix:@"