iOS开发--微信和支付宝网页支付(过审, 支付宝支付成功可回跳)

前言

以前接入微信和支付宝的支付, 采用的是导入对应的SDK, 调用和返回都是由SDK内部处理, 这一点从操作和集成角度而言, 安全和方便. 但是局限性也是有的:

  1. 苹果限制虚拟类型的商品等必须使用内购, 也就是说 支付宝和微信的三方支付存在很多的局限性,这个虽然是为用户的账户资金安全考虑, 但是就目前的国内实际情况而言, 这是一个麻烦(和谐一下)
  2. 在一定程度上增加了包体积的大小
  3. 增加了审核的成本

那么, 问题来了, 有没有更简单的方案呢, 答案当然是有的.

网页支付

微信和支付宝的网页支付营运而生…
优点:

  1. 采用网页支付, 空间上不需要在项目中导入SDK增加体积
  2. WEB一站式解决支付问题
  3. 可以更好地应对审核(和谐一下)

缺点:(学习使我快乐, 忽略吧)

  1. H5或者网页的对接经验
  2. 增加了学习的成本
  3. 需要单独处理支付宝和微信的链接

应用场景:

目前我遇到的大部分是活动网页.

正文

这边文章目的是使用网页支付, 更好的适配审核, 所以, 有舍有得, 我们不去看缺点, 毕竟, 就过审而言, 这点不算什么…

进入正题, 网页支付, 就是使用WKWebView打开网页, 由网页调用支付宝or微信的网页的SDK, 这部分由前端同学(甩锅中…)完成, 我们这边通过WK的代理获取当前请求的网络连接,判断是不是需要openURL到微信或者支付宝.

1. 设置URL Scheme

这个相当于你App的铭牌, 别的App想要跳转到你的App的时候, 就需要知道你App的铭牌,一个App可以设置多个.

2. AppDelegate( 这一步 看大家需求操作吧 )

设置进入前台(跳转回来) 处理服务器需要刷新的网页

3.1 - 微信网页支付

大致流程:

  1. 获取当前请求的链接,判断你是不是微信的
  2. 保存连接中的参数名为redirect_url的对应数据为appWillBecomeActiveWebReloadUrlString,
  3. 替换redirect_url = “自定App的URLScheme” 用于,
  4. 替换完后, 重新请求连接,
  5. 跳转,
  6. 支付完成, 返回app(能返回是因为第3步)
  7. 在AppDelegate的程序进入前台的代理方法中处理当前网页刷新之前保存的appWillBecomeActiveWebReloadUrlString(至于这个保存的appWillBecomeActiveWebReloadUrlString的链接地址内容是啥,就看你们前端如何处理了).
// 判断非返回或者刷新
if (!(navigationAction.navigationType == WKNavigationType.backForward || navigationAction.navigationType == WKNavigationType.reload)) {
// 微信判断
    let pre_string = "https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb"
    if request.url?.absoluteString.hasPrefix(pre_string) ?? false {
        
        let par = WebPayTool.params(of: navigationAction.request.url)
        let params: NSMutableDictionary = NSMutableDictionary(dictionary:par);
        
        if var allKeys = params.allKeys as? [String] {
        	// openWebResult.webpaye.com这个是你自定义的你的App的名牌
        	//  ://app_paycallback/ 是你回调后判断的类型 这个部分自定义, 逻辑自定义        
            let app_name = "openWebResult.webpaye.com://app_paycallback/"
            
            let return_new_value = WebPayTool.urlDecodedString(app_name);
            let returnKey = "redirect_url"
			// 判断连接中是不是有redirect_url 参数, 添加或者更换为上面自定义的 app_name
            if (allKeys.contains { (item: String) -> Bool in
                return item == returnKey
            }) {
                // 有对应的回调地址
                let return_old_value = params[returnKey] as? String
                let isOpenOther = return_old_value == return_new_value
                if !isOpenOther {
                    // 保存回调地址 这个是自己服务器的参数,也就是支付或者回来后, 网页需要刷新的页面
                    self.appWillBecomeActiveWebReloadUrlString = WebPayTool.urlDecodedString(return_old_value ?? "")
                    params[returnKey] = return_new_value;
                    allKeys.append(returnKey);
                    var newURLStr = NSString(format: "%@", pre_string)
                    for key in allKeys {
                        if let value = params[key] {
                            newURLStr = NSString(format: "%@", newURLStr).urlAddCompnent(forValue: value as! String, key: key) as NSString
                        }
                    }
                    // 重新组织好新的连接, 重新请求
                    if let newUrl = URL(string: newURLStr as String) {
                        decisionHandler(.cancel)
                        var newRequest = URLRequest.init(url: newUrl)
                        newRequest.allHTTPHeaderFields = request.allHTTPHeaderFields;
                        webView.load(newRequest)
                        
                        return;
                    }
                }
            }
        }
    }
}

3.2 - 支付网页支付

大致流程:

  1. 获取当前请求的链接,判断你是不是支付宝的
  2. 保存连接中的参数名为redirect_url的对应数据为appWillBecomeActiveWebReloadUrlString,
  3. 获取当前请求的链接,判断是不是支付宝跳转的协议链接, 并且包含fromAppUrlScheme
  4. WebPayTool.handleWebUrl(urlString) 处理支付宝跳转的协议链接, 这里是最重要的,内容我放到的对应的方法中, 每个步骤都做了解释
  5. 跳转
  6. 支付完成, 返回app(能返回是因为第2步)
  7. 在AppDelegate的程序进入前台的代理方法中处理当前网页刷新之前保存的appWillBecomeActiveWebReloadUrlString(至于这个保存的appWillBecomeActiveWebReloadUrlString的链接地址内容是啥,就看你们前端如何处理了).
// 支付宝判断
if let url = request.url {
    let urlString = url.absoluteString
    
    if urlString.hasPrefix("https://openapi.alipay.com/gateway.do") {
        if let aliUrl = URL(string: urlString) {
            let returnReloadKey = "return_url"
            let par = WebPayTool.params(of: aliUrl)
            let params: NSMutableDictionary = NSMutableDictionary(dictionary:par);
            let return_old_value = params[returnReloadKey] as? String
            let redirct = WebPayTool.urlDecodedString(return_old_value ?? "")
            self.appWillBecomeActiveWebReloadUrlString = redirct
        }
    }
}

if let urlString = navigationAction.request.url?.absoluteString {
    if urlString.contains("alipay://") || urlString.contains("alipays://"){
        if urlString.contains("fromAppUrlScheme") {
            decisionHandler(.cancel)
            // 下面是重点, 这里面处理了支付宝支付的链接参数问题
            // 主要 是 你跳去了支付宝App 还可以调回来
            WebPayTool.handleWebUrl(urlString)
            return
        }
    }
}

支付宝的WebPayTool.handleWebUrl(urlString)

重点

修改fromAppUrlScheme的参数为自定义的App的URL Scheme

if ([url containsString:@"fromAppUrlScheme"]) {
	NSString *encodeUrl = [url stringByRemovingPercentEncoding];
	NSArray *urlParArry = [encodeUrl componentsSeparatedByString:@"?"];
	NSMutableDictionary *beSetParDic = [self dictionaryWithJsonString:urlParArry.lastObject];
	// 下面是重点 fromAppUrlScheme的设置, 是支付宝客户端回跳到你的App的参数,设置URL Scheme
	[beSetParDic setObject:@"你的App的自定义的URL Scheme" forKey:@"fromAppUrlScheme"];
	NSString *overJsonStr = [self dictionaryToJson:beSetParDic];
	NSString *overUrlStr = [NSString stringWithFormat:@"%@?%@",urlParArry.firstObject,overJsonStr];
	NSString *canUseEncodeUrl = [overUrlStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
	[[UIApplication sharedApplication] openURL:[NSURL URLWithString:canUseEncodeUrl]];
}

上面是有关支付宝和微信的网页支付的关键代码内容, 具体的需要根据自己的业务逻辑去做代码适配.

总结:

  1. 微信的网页支付主要是替换 redirect_url
  2. 支付宝的网页支付主要是替换fromAppUrlScheme
  3. 包含的回调地址redirect_url 这个是网页支付中, 你跳转回来后当前网页刷新的地址, 前端定义的, 根据实际情况处理.

最后
奉上Demo地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章