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地址

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
支付宝沙箱环境是用于模拟支付宝正式环境的测试环境,可以进行支付宝支付的测试。本文将介绍如何使用Spring Boot实现支付宝沙箱支付前后端案例。 1. 创建Spring Boot项目 使用IDEA或Eclipse创建一个新的Spring Boot项目,并添加以下依赖: ``` <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.9.5.ALL</version> </dependency> ``` 2. 配置支付宝沙箱环境 在支付宝开放平台注册并创建应用后,进入沙箱环境,获取沙箱环境的AppID、RSA私钥和公钥,并将其配置到项目中。 ``` #支付宝沙箱环境配置 alipay.gateway=https://openapi.alipaydev.com/gateway.do alipay.app-id=应用ID alipay.private-key=应用私钥 alipay.public-key=支付宝公钥 ``` 3. 创建支付宝支付接口 创建一个支付宝支付接口,用于生成支付宝支付的请求参数。 ``` @RestController public class AlipayController { @Autowired private AlipayProperties alipayProperties; @GetMapping("/alipay") public String alipay(HttpServletRequest request, HttpServletResponse response) throws Exception { //实例化客户端 AlipayClient alipayClient = new DefaultAlipayClient(alipayProperties.getGateway(), alipayProperties.getAppId(), alipayProperties.getPrivateKey(), "json", "utf-8", alipayProperties.getPublicKey(), "RSA2"); //创建API对应的request AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); //在公共参数中设置回和通知地址 alipayRequest.setReturnUrl(alipayProperties.getReturnUrl()); alipayRequest.setNotifyUrl(alipayProperties.getNotifyUrl()); //填充业务参数 alipayRequest.setBizContent("{\"out_trade_no\":\"" + 1 + "\"," + "\"total_amount\":\"" + 0.01 + "\"," + "\"subject\":\"" + "测试商品" + "\"," + "\"body\":\"" + "测试商品详情" + "\"," + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); //调用SDK生成表单 String form = alipayClient.pageExecute(alipayRequest).getBody(); //直接将完整的表单html输出到页面 response.setContentType("text/html;charset=utf-8"); response.getWriter().write(form); response.getWriter().flush(); response.getWriter().close(); return null; } } ``` 4. 创建支付宝回调接口 创建一个支付宝回调接口,用于接收支付宝支付的异步通知。 ``` @RestController public class AlipayNotifyController { @PostMapping("/notify") public String notify(HttpServletRequest request) throws Exception { //获取支付宝POST过来反馈信息 Map<String, String> params = new HashMap<String, String>(); Map<String, String[]> requestParams = request.getParameterMap(); for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) { String name = iter.next(); String[] values = requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } //乱码解决,这段代码在出现乱码时使用 valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); params.put(name, valueStr); } //调用SDK验证签名 boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayProperties.getPublicKey(), "utf-8", "RSA2"); if (signVerified) { //验证成功,处理业务逻辑 return "success"; } else { //验证失败 return "fail"; } } } ``` 5. 创建支付宝前端页面 创建一个支付宝前端页面,用于调用支付宝支付的接口。 ``` <html> <head> <meta charset="UTF-8"> <title>支付宝沙箱支付</title> </head> <body> <div> <button onclick="alipay()">支付宝支付</button> </div> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <script> function alipay() { $.get("/alipay", function (data) { $("body").html(data); }) } </script> </body> </html> ``` 6. 测试支付宝沙箱支付 启动Spring Boot项目,访问支付宝前端页面,点击“支付宝支付”按钮,跳转支付宝支付页面,输入支付宝账号和密码进行支付支付成功后,会触发支付宝回调接口中的逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值