iOS实现H5支付(微信,支付宝)原生封装

  


  

  

支付分应用支付,H5支付,扫码支付等.app支付一般在应用中使用,并且需要集成相应的支付SDK, H5支付多用于网页。如果你的应用程序不想集成支付SDK,又想实现支付功能,你可以在项目中使用H5支付。本文主要讲述如何将H5支付封装成一个原生可调用的组件。

  


  

  

注:以下为网页H5支付流程,原生调用需要修改部分流程

  

<强> 1.1微信支付

  
      <李>统一下单,获取微信中间页地址mweb_url李   <李>页面重定向到微信中间页   <李>微信中间页发起支付请求李   <李> safari浏览器拦截支付请求打开微信应用程序开始支付(如果在应用中,需要在shouldStartLoadWithRequest:方法里面拦截支付请求,并打开微信)   
  

微信中间页重新向到redirect_url
  

  

<强> 1.2支付宝支付
  

  
      <李>发起网页支付请求,H5为一个表形式单提交。   <李>页面重定向到支付宝收银台页面李   <李>发起应用支付请求,并且开始倒计时,如果打开支付宝超时页面跳转到网页支付界面,如果唤起支付宝,倒计时结束。   <李>支付完毕页面跳转到return_url页面,需用户手动触发。   
  


  

  

新开一个webView加载支付中间页,拦截中间页支付请求并唤起支付,然后关闭webView流程结束。

  

webView需要加到窗口(或者当前控制器的视图上),并设置一个大小(肉眼不可见就行)。因为使用wkwebview时,webView不显示的情况下,H5请求会被挂起,会导致支付宝页面不能唤起支付请求。

  


  

  

具体步骤见代码注释

        @ interface HJH5WebPayManager () & lt; UIWebViewDelegate>      @ property(原子、强)UIWebView * payWebview;      @ property(原子、强)空(^ sendPayResult) (HJH5SendWebPayResult);      @end      @ implementation HJH5WebPayManager      + (instancetype) sharedInstance {   静态dispatch_once_t& redirect_url=% @”,推荐人]];   }   请求=[NSMutableURLRequest requestWithURL:(NSURL URLWithString reqUrl): cachePolicy: NSURLRequestUseProtocolCachePolicy timeoutInterval: 60.0);//设置授权域名,伪造引用页头,因为微信中间页会检验引用页头,并且推荐人对应的值需要包含安全域名   【请求setValue:推荐人forHTTPHeaderField: @“推荐人”);   如果(self.payWebview) {   (自我。payWebview removeFromSuperview];   自我。payWebview=零;   }   自我。payWebview=[[UIWebView alloc] initWithFrame: CGRectMake (0, 0, 0.1, 0.1)];   自我。sendPayResult=处理;   [[UIApplication sharedApplication]。keyWindow addSubview self.payWebview):;   self.payWebview.delegate=自我;   (自我。payWebview loadRequest:请求);   }else if ([html hasPrefix: @“& lt;形式”)){//如果是支付宝、html对应的应该是一段形式表单提交脚本,需要调用loadString方法加载   如果(self.payWebview) {   (自我。payWebview removeFromSuperview];   自我。payWebview=零;   }   自我。payWebview=[[UIWebView alloc] initWithFrame: CGRectMake (0, 0, 0.1, 0.1)];   自我。sendPayResult=处理;   [[UIApplication sharedApplication]。keyWindow addSubview self.payWebview):;   self.payWebview.delegate=自我;   NSString * payStr=html;   NSString * htmlString=[NSString stringWithFormat: @”htmlString: & lt; html>\ n”   “& lt; head>\ n”   “& lt;元name=\ "视窗\“内容=\ "初始=1.0,最大范围=1.0,user-scalable=没有\”/比;\ n”   “& lt;风格类型=\ "文本/css \”在\ n”   “身体{字体大小:16 px;} \ n”   “& lt;/style>\ n”   “& lt;/head>\ n”   “& lt; body>”   “% @”   “& lt;/body>”   “& lt;/html> payStr];   (自我。payWebview loadHTMLString: htmlString baseURL: nil);      其他}{//非法html,返回错误   处理(HJH5SendWebPayResultOther);   返回;   }//容错处理,20秒没唤起支付,当错误处理。   __weak typeof(自我)weakSelf=自我;   dispatch_after (dispatch_time (DISPATCH_TIME_NOW (int64_t) (20 * NSEC_PER_SEC)), dispatch_get_main_queue ()、^ {   如果(weakSelf.sendPayResult) {   weakSelf.sendPayResult (HJH5SendWebPayResultOther);   }   [weakSelf endPayment];   });   }         - (void) webView: (UIWebView *) webView用didFailLoadWithError来回叫:错误(NSError *) {//页面加载失败,返回错误   如果(self.sendPayResult) {   self.sendPayResult (HJH5SendWebPayResultLoadFail);   }   (自我endPayment);   }      (保龄球)webView:(UIWebView *) webView shouldStartLoadWithRequest: (NSURLRequest *)请求navigationType: (UIWebViewNavigationType) navigationType {   NSURL * url=request.URL;   NSString * newUrl=url.absoluteString;//拦截微信支付请求,并打开微信   如果([newUrl rangeOfString: @“weixin://wap/支付”)。位置!=NSNotFound) {//判断是否能打开微信   如果([[UIApplication sharedApplication] canOpenURL: url]) {   如果(@available (iOS 10.0 *)) {   [[UIApplication sharedApplication] openURL: url选项:@ {}completionHandler: nil);   其他}{   [[UIApplication sharedApplication] openURL: url];   }   如果(self.sendPayResult) {   self.sendPayResult (HJH5SendWebPayResultSuccess);   }   (自我endPayment);   其他}{   如果(self.sendPayResult) {   self.sendPayResult (HJH5SendWebPayResultSendFail);   }   (自我endPayment);   }   返回NO;   }else if ([newUrl rangeOfString: @“支付宝://alipayclient/& # 63;”)。位置!=NSNotFound) {//拦截支付宝支付请求,并且替换fromAppUrlScheme参数为当前应用的方案,实现支付完毕返回应用功能。   NSString * aliScheme=@”支付宝支付计划,支付完毕可通过计划返回到当前应用”;   newUrl=[HJStringHelper decodeURL newUrl):;   NSString * parameterString=[newUrl stringByReplacingOccurrencesOfString: @“支付宝://alipayclient/& # 63;“withString: @ ");   NSError *误差=零;   id dict=[NSJSONSerialization JSONObjectWithData:(parameterString dataUsingEncoding: NSUTF8StringEncoding]选项:NSJSONReadingMutableContainers错误:和错误);   如果错误(!){   如果([dict isKindOfClass:[称为unaryoperations类]]){   dict [@“fromAppUrlScheme”]=aliScheme;   NSData * jsonData=[NSJSONSerialization dataWithJSONObject: dict类型选项:NSJSONWritingPrettyPrinted错误:和错误);   如果错误(!){   parameterString=[HJStringHelper escapeURL: [[NSString alloc] initWithData: jsonData编码:NSUTF8StringEncoding]];   NSString * payUrl=[NSString stringWithFormat: @“支付宝://alipayclient/& # 63; % @”, parameterString);   设置(dispatch_get_main_queue ()、^ {//判断是否能打开支付宝   如果([[UIApplication sharedApplication] canOpenURL: [NSURL URLWithString: payUrl]]) {   如果(@available (iOS 10.0 *)) {   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null

iOS实现H5支付(微信,支付宝)原生封装