热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Swift与H5交互:跳转拦截完成支付功能

Swift与H5交互:跳转拦截完成支付功能-这是我参与更文挑战的第7天,活动详情查看:[更文挑战]与H5交互不得不说的事最近上班一直都在和公司的其他项目的人员忙活App原生(双

这是我参与更文挑战的第7天,活动详情查看: [更文挑战]

与H5交互不得不说的事

最近上班一直都在和公司的其他项目的人员忙活App原生(双端)与H5交互的事情,因为遇到了需求方非常质疑的态度(主要是感觉方案不可行),导致需要进行验证与尝试。

虽然,在原生与H5的交互上,我基本都了解情况,不过在此机会也记录一下,就当存档的吧。

后面再遇到这类问题,给自己抑或掘友们一点点启发与思路。

今天说先说一个业务需求。

App内嵌H5页面进行支付

事情大概是这样的,我们团队的前端做了一个Web页面,是一个商城类型,有支付功能,可以进行微信和支付宝支付。

这个Web页面在浏览器中支付跳转,不管是跳转到微信支付或者是支付宝支付都是好好的,但集成到移动端App里面的WebView后,就不生效了。

前端的同事感到疑惑后找到了我,寻求如何在App端跳转微信或者支付宝进行支付的方案。

我直接就下了结论:App什么都不做,这明摆着不能的呀?虽然H5大部分时间都能都为所欲为,但这类Web页面在App中需要进行跳转,必须在App端进行跳转拦截与处理呀。

说到这里,必须上代码来演示了。

在iOS中WKWebKit中的WebView有一个代理属性WKNavigationDelegate,其中有这样一个代理方法:

/// 根据WebView对于即将跳转的HTTP请求头信息和相关信息来决定是否跳转
///
/// - Parameters:
///   - webView: 实现该代理的webview
///   - navigationAction: 当前navigation
///   - decisionHandler: 是否跳转block
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    decisionHandler(.allow)
}

这里面,一个非常重要的参数,navigationAction,我们来看看它的类WKNavigationAction里面有哪些属性:

@available(iOS 8.0, *)
open class WKNavigationAction : NSObject {

    
    /** @abstract The frame requesting the navigation.
     */
    @NSCopying open var sourceFrame: WKFrameInfo { get }

    
    /** @abstract The target frame, or nil if this is a new window navigation.
     */
    @NSCopying open var targetFrame: WKFrameInfo? { get }

    
    /** @abstract The type of action that triggered the navigation.
     @discussion The value is one of the constants of the enumerated type WKNavigationType.
     */
    open var navigationType: WKNavigationType { get }

    
    /** @abstract The navigation's request.
     */
    open var request: URLRequest { get }

    
    /** @abstract A value indicating whether the web content used a download attribute to indicate that this should be downloaded.
    */
    @available(iOS 14.5, *)
    open var shouldPerformDownload: Bool { get }
}

注意看其中有一个属性是open var request: URLRequest { get }通过这个属性,我们可以获取到需要跳转的URL的内容,针对我们跳转微信支付或者支付宝支付,我们只用判断request中的scheme和url字符串就可以了。

而这方面支付宝的官方文档中就给出了明确的例子:

App通过监听alipays://或者alipay:// 开头的路由来唤醒支付宝。

支付宝文档

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    __weak APWebViewController* wself = self;
    NSString * reqUrl = navigationAction.request.URL.absoluteString;
    if ([reqUrl hasPrefix:@"alipays://"] || [reqUrl hasPrefix:@"alipay://"]) {
        // NOTE: 跳转支付宝App
        BOOL bSucc = [[UIApplication sharedApplication]openURL:navigationAction.request.URL];
 
        // NOTE: 如果跳转失败,则跳转itune下载支付宝App
        if (!bSucc) {
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示"
                                                           message:@"未检测到支付宝客户端,请安装后重试。"
                                                          delegate:wself
                                                 cancelButtonTitle:@"立即安装"
                                                 otherButtonTitles:nil];
            [alert show];
        }
        
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    
    decisionHandler(WKNavigationActionPolicyAllow);
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    // NOTE: 跳转itune下载支付宝App
    NSString* urlStr = @"https://itunes.apple.com/cn/app/zhi-fu-bao-qian-bao-yu-e-bao/id333206289?mt=8";
    NSURL *downloadUrl = [NSURL URLWithString:urlStr];
    [[UIApplication sharedApplication]openURL:downloadUrl];
}

而微信文档中明确说明了不建议App调用H5支付,见下图:

虽然微信文档不建议,但通过支付宝给出的代码,完全可以照抄,通过判断url中是否包含weixin://来进行跳转。

其实这类拦截跳转到最后,都会调用UIApplication.shared的一个函数:

open func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey : Any] = [:], completionHandler completion: ((Bool) -> Void)? = nil)

这个函数可以认为是一个系统级路由方法,可以在iOS系统层面进行App的切换。

结论

App通过WebView加载H5页面,进行支付功能是可行的,同时App端(双端)都需要进行WebView的跳转拦截,通过系统级路由去跳转到微信或者支付宝完成支付。

通过H5调用其他功能,比如打电话,也可以通过在上面所示的代理方法中判断是否包含tel://来进行处理。

微信支付不建议App调用H5支付,我个人认为是处于安全考虑,因为可能涉及恶意重定向拦截的request的url,导致指向其他订单,出现支付的异常扣款的情况。

明日继续

明天会继续更新原生调用js,和js调用原生的分析与例子。大家加油!


推荐阅读
author-avatar
PLDLYY
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有