uniapp app端内嵌webview对接支付宝支付

//请求接口需要配置回调地址,回调地址用于跳转回APP指定地址
//app支付
const appRequestPayment = (orderInfo: string) => {
//
orderInfo里面返回的是form表单
uni.navigateTo({ url: 'webviewURL?one=' + encodeURIComponent(JSON.stringify(orderInfo)) })
}
<template>
    <view class="page">        
        <web-view :src="state.navUrl"></web-view>
    </view>
</template>
<script setup lang="ts">
    import {
        onLoad,
        onReady,
        onHide,
        onUnload,
        onBackPress,
    } from '@dcloudio/uni-app';
    import {
        reactive,
        getCurrentInstance,
    } from 'vue'
    const state : any = reactive({
        //需要在src目录下新建html目录以及html页面
        navUrl: '../../hybrid/html/xxx.html?data=',
        action: '',
        isShow: true,
        navHeight: 0,
    })
    onLoad((options : {
        one : string,
    }) => {        
        let data = JSON.parse(decodeURIComponent(options.one))
        //先把关键布局用特殊符号代替
        let htmlSplit = data.replace(/\?/g, "%3F")
        let htmlSplit3 = htmlSplit.replace(/\#/g, "%233")
        let sult = encodeURIComponent(JSON.stringify(htmlSplit3))
        state.navUrl += JSON.parse(decodeURIComponent(sult))
    })
    onReady(() => {
        // #ifdef APP-PLUS
        // vue2写法
        //     const currentWebview = this.$mp.page.$getAppWebview();
        // vue3写法
        /* 获取屏幕信息 */
        let pages = getCurrentPages();
        let page : any = pages[pages.length - 1];        
        setTimeout(() => {
            let currentWebview = page.$getAppWebview();
            var wv = currentWebview.children()[0];
            let url = '此处的地址拦截了跳转H5,并跳转到指定APP的地址'
            // wv.overrideUrlLoading({mode: 'allow',match: '.*alipay\.com/.*'},(e)=>{//允许阿里的地址跳转
            wv.overrideUrlLoading({
                // "reject"  表示满足match属性定义的提交时拦截url跳转并触发callback回调,不满足match属性定义的条件时不拦截url继续加载。
                // "allow"  表示满足match属性定义的条件时不拦截url继续加载,不满足match属性定义的条件时拦截url跳转并触发callback回调;
                mode: 'reject',
                match: `.*${url}\.com/.*`
            }, (e) => {
                //业务逻辑,可以查询订单状态,然后跳转支付结果页
            })
                //webview窗口布局
            global.$navHeight(res => {
                wv.setStyle({
                    top: 10,
                    // scalable: true 是否可以双指缩放
                })
            })
        }, 180)
    })
    onBackPress((e) => {
        // 强制不允许返回
        return true;
    })
</script>
<style scoped lang="scss">
    .page {
        width: 750rpx;
        margin: 0 auto;
    }
</style> 
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <mete http-equiv="contentType" content="textml;charst=utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>支付订单</title>
            <style>
                @keyframes show {
                    0% {
                        opacity: 0;
                    }

                    100% {
                        opacity: 1;
                    }
                }

                @keyframes hide {
                    0% {
                        opacity: 1;
                    }

                    100% {
                        opacity: 0;
                    }
                }

                .toast_box {
                    width: 100%;
                    position: absolute;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    justify-content: center;
                    display: none;
                }

                .toast_box p {
                    box-sizing: border-box;
                    padding: 10px 20px;
                    max-width: 72%;
                    width: max-content;
                    background: #000;
                    color: #FFF;
                    font-size: 16px;
                    text-align: center;
                    border-radius: 6px;
                    opacity: 0.8;
                }

                .zan-dialog-mask {
                    position: fixed;
                    top: 0;
                    left: 0;
                    right: 0;
                    bottom: 0;
                    z-index: 999;
                    background: rgba(0, 0, 0, 0.7);
                }

                .zan-dialog__container {
                    position: fixed;
                    left: 50%;
                    top: 50%;
                    transform: translate(-50%, -50%);
                    background: #f8f8f8;
                    transition: all 0.4s ease;
                    z-index: 9999;
                    border-radius: 20px;
                }

                .container {
                    position: relative;
                    width: 300px;
                    height: 250px;
                    border-radius: 20px;
                    margin: 0 auto;
                }

                .title {
                    font-size: 23px;
                    color: #333;
                    font-weight: bold;
                    text-align: center;
                    padding: 25px 0 0 0;
                    margin-bottom: 20px;
                }

                .concent {
                    font-size: 20px;
                    color: #333;
                    font-weight: bold;
                    text-align: center;
                }

                .btnFlex {
                    position: absolute;
                    bottom: 15px;
                    width: 100%;
                    display: flex;
                    align-items: center;
                }

                .resetPay {
                    font-size: 18px;
                    width: 50%;
                    height: 50px;
                    line-height: 50px;
                    text-align: center;
                    font-weight: bold;
                }

                .cancel {
                    font-size: 18px;
                    width: 50%;
                    height: 50px;
                    line-height: 50px;
                    text-align: center;
                    font-weight: bold;
                    color: #ff2f4e;
                }

                .hideStyle {
                    display: none;
                }

                .showStyle {
                    display: block;
                }
            </style>
    </head>
    <body>
        <div style="height:500px"></div>
        <div class="toast_box">
            <p id="toast"></p>
        </div>
        <div id='replace'></div>
        <div id="zan-dialog-mask" class="hideStyle">
            <div class="zan-dialog-mask hideStyle">
                <div class="zan-dialog__container">
                    <div class="container">
                        <div class="title">提示</div>
                        <div class="concent">
                            <div>订单支付未完成,</div>
                            <div>是否重新支付?</div>
                        </div>
                        <div class="btnFlex">
                            <div class="resetPay" onclick="resetPay()">重新支付</div>
                            <div class="cancel" onclick="cancel()">取消</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </body>
    <script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.3/index.js"></script>
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <script type="text/javascript">
        document.addEventListener('UniAppJSBridgeReady', function() {
            let plus=false;
            uni.postMessage({
                data: {
                    action: '',
                    payResult: 0
                }
            });
            uni.getEnv(function(res) {
                console.log('当前环境:' + JSON.stringify(res));
                if(res.plus){
                    // setTimeout(()=>{
                    //     uni.webView.reLaunch({
                    //         url:'/pages/componentsA/order/paymentResult'
                    //     })
                    // },500)
                }
            });
            //获取数据进行赋值
            getUrlParam()
            toast('正在跳转支付页面..', 1200)
            //获取元素 其实以下得看自身情况需求来做更改 但大体就是使用 window.location.search.substring(1)截取到凭借的参数 然后使用decodeURIComponent方法进行转译
            let replace = document.getElementById('replace')
            function getUrlParam() {
                // 取得url中?后面的字符
                let query = window.location.search.substring(1);
                // let pair, pairSplit, id, token,requestUrl,userTerminal;
                // 把参数按&拆分成数组3
                // let param_arr = query.split("=");
                //需要把特殊字符还原,不然webview会报错
                let param_arr = query.substring(5);
                let htmlSplit = param_arr.replace(/\%3F/g, "?")
                let htmlSplitSpace = htmlSplit.replace(/\%20/g, " ")
                let htmlSplitSpaceF = htmlSplitSpace.replace(/\%3C/g, "<")
                let htmlSplitSpaceFR = htmlSplitSpaceF.replace(/\%3E/g, ">")
                let htmlSplitSpaceFf = htmlSplitSpaceFR.replace(/\%22/g, '"')
                let htmlSplitSpaceFf3 = htmlSplitSpaceFf.replace(/\%233/g, '#')
                // let htmlSplitSpaceFfPay = htmlSplitSpaceFf3.replace(/\%E7%AB%8B%E5%8D%B3%E6%94%AF%E4%BB%98/g, '立即支付')
                setTimeout(() => {
                let divForm = document.getElementsByTagName('divform')
                if (divForm.length) {
                    document.body.removeChild(divForm[0])
                }
                const div = document.createElement('divform');
                div.innerHTML = htmlSplitSpaceFf3;
                    document.body.appendChild(div);
                    document.forms[0].setAttribute('target', '_blank')
                    document.forms[0].submit();
                }, 500)
            }        
            function toast(text, time) {
                var toast = document.getElementById('toast');
                var toast_box = document.getElementsByClassName('toast_box')[0];
                toast.innerHTML = text;
                toast_box.style.animation = 'show 1.5s'
                toast_box.style.display = 'flex';
                setTimeout(() => {
                    toast_box.style.animation = 'hide 1.5s'
                    setTimeout(() => {
                        toast_box.style.display = 'none';
                    }, 1400)
                }, time)
            }
        });
    </script>
</html>

如有疑问,请联系随笔作者,一起进步!!

posted @ 2023-05-08 11:16  晨曦_yuan小海  阅读(951)  评论(0)    收藏  举报