欧阳铁柱
欧阳铁柱
  • 发布:2020-07-30 23:35
  • 更新:2020-07-30 23:46
  • 阅读:5322

iOS wkwebview h5拉起支付宝支付方案

分类:uni-app

经研究,使用wkwebview时,h5页面无法拉起部分支付宝支付,新版h5支付可以打开,旧版不行,应该是alipay://私有协议无法打开,这个情况下思路是拦截alipay协议,通过plus.runtime.openURL实现打开;这个思路没问题,实操的时候有个bug,那就是overrideUrlLoading拦截无法拦截非https http ftp外的链接,导致无法获知支付宝的alipay私有协议具体内容,业务无法实现。

特别说明:新版支付宝h5链接直接打开可以调起支付宝,旧版不行,本方案仅适用于旧版支付宝H5。

重点:支付宝的js代码,有一个全局变量window._data,里面保存了调用支付宝需要的参数,invokeAlipayData,使用该参数,拼接支付宝协议可实现支付宝调用

最终思路:wkwebview调用支付宝H5,overrideUrlLoading拦截所有链接,通过注入一个js,获取到invokeAlipayData,通过window.location.href进行跳转,由拦截器进行处理,拦截器得到三种链接:1.经过注入js处理的带有支付宝参数的链接(处理);2.支付宝自有H5继续支付链接(忽略);3.支付成功回调链接(处理)

示例代码如下(仅提供思路,具体业务请自行完善)

<template>  
    <view></view>  
</template>  

<script>  
    var wv;//计划创建的webview  
    var currentWebview  
    export default {  
        data() {  
            return {  
                oid:''  

            }  
        },  

        onLoad(op) {    
            wv = plus.webview.create("","custom-webview",{  
                        plusrequire:"none", //禁止远程网页使用plus的API,有些使用mui制作的网页可能会监听plus.key,造成关闭页面混乱,可以通过这种方式禁止  
                  'uni-app': 'none', //不加载uni-app渲染层框架,避免样式冲突  
                        top:uni.getSystemInfoSync().statusBarHeight+44 //放置在titleNView下方。如果还想在webview上方加个地址栏的什么的,可以继续降低TOP值  
            })  
            currentWebview = this.$scope.$getAppWebview();   

            this.oid = op.oid  

            this.takePayemnt()  
        },  
        onShow(){  

        },  
        onReady(){  

        },  
        methods: {  

            /*发起支付宝支付*/  
            takePayemnt(){  
                let params ={}  
                params['oid'] = this.oid  
                params['way'] = 1  
                let that = this  
                this.fetch.post("***", params , true)//我司接口,获取支付宝的支付form  
                 .then(res => {  

                     wv.loadData(res.result)//加载后端返回的form片段  
                    currentWebview.append(wv);  
                    setTimeout(()=>{  
                        /*关键代码:注入js,点击按钮时获取window._data.data.invokeAlipayData数据,跳转到指定链接拦截(私有协议无法拦截),该数据可拉起支付宝支付*/  
                        wv.evalJS('$(document).on("click", "a", function(event){window.location.href="https://fuckyou.com?params="+JSON.stringify(window._data.data.invokeAlipayData);});');  

                        let sb =  currentWebview.children()[0]   
                        // 监听拦截,拦截所有页面跳转  
                        sb.overrideUrlLoading({mode: 'reject',match:''}, function(e) {  
                            console.log('reject url: ' + e.url);   

                            /*检查拦截的url是否注入的js跳转链接,是的话通过plus.runtime.openURL打开该链接*/  
                            if(e.url.search("fuckyou") != -1){  
                                let params = e.url.substring(28)  
                                let url = 'alipay://alipayclient/?' + params  
                                plus.runtime.openURL(url, function(res) {    
                                                   console.log(res);    
                                });   

                            }else{  
                                /*非注入js引导链接,一般为支付成功的跳转*/  
                                let oid = that.getQueryVariable('out_trade_no',e.url)  
                                if(oid){  
                                    uni.redirectTo({  
                                        url:'alipaySuccess?out_trade_no='+oid  
                                    })  
                                }  

                            }  
                        });  

                    },500)  

                 }).catch(function (error) {  

                });  
            },  
            getQueryVariable(variable,url)  
            {  
                   var query = url.substring(1);  
                   var vars = query.split("&");  
                   for (var i=0;i<vars.length;i++) {  
                           var pair = vars[i].split("=");  
                           if(pair[0] == variable){return pair[1];}  
                   }  
                   return(false);  
            }  
        }  
    }  
</script>  
<style lang="scss" scoped>  
    .page-view{  
        min-height: 100vh;  
    }  
    .result{  
        text-align: center;  
        padding-top:150rpx;  

    }  
    .tips{  
        font-weight: bold;  
        font-size: 40rpx;  
        margin:100rpx 0;  
    }  
    .btn{  
        margin:50rpx 80rpx;  
    }  
</style>  
1 关注 分享
蝶小蝶

要回复文章请先登录注册

欧阳铁柱

欧阳铁柱 (作者)

如果能拿到新版支付宝H5支付的账号,无需考虑这些问题,新版支付已经兼容
2020-07-30 23:46
欧阳铁柱

欧阳铁柱 (作者)

备注:该方法需要考虑注入js执行的稳定性,通过别的方法拿到invokeAlipayData也是可行的
2020-07-30 23:44