微信小程序webview内嵌H5支付

4,497 阅读1分钟

情景

H5网站webview的形式嵌入小程序,接微信支付。H5和小程序都是用uniapp开发的,以uniapp为例,使用原生开发的自动切换。

踩坑 - JSAPI支付

最开始想到的是接微信JSAPI支付,跳转支付页面的时候,加上公众号授权,获取code,换取openId,调起JSAPI支付。

成功 - 跳转到小程序支付

1.小程序承载H5的页面

  • 通过login获取用户code,换取openId
<template>
	<view class="content">
		<web-view :src="completePath"></web-view>
	</view>
</template>

<script>
    export default {
            data() {
                    return {
                            pagePath:'/pages/index/index',//默认的页面地址
                            webPath:'https://xxxxxx.com/h5/#' //授权的域名地址
                    }
            },
            onLoad(options) {
                    if(options?.pagePath){
                            this.pagePath = options.pagePath
                    }
                    this.loginGetCode()
            },
            methods: {
                    loginGetCode(){
                            uni.login({
                                    provider: 'weixin',
                                    success:(loginRes)=>{
                                            let code = loginRes.code
                                            this.pagePath = `${this.pagePath}?code=${code}`
                                    }
                            })
                    }
            },
            computed:{
                    completePath(){
                            return this.webPath + this.pagePath
                    }
            }
    }

2.H5首页

  • 通过wind.location属性获取小程序传过来的code
onShow() {
        if(uni.getStorageSync('isweixin')){ //在APP.vue文件就判断了是不是微信浏览器环境
                let code = this.getUrlParam("code")
                uni.setStorageSync('user_wx_code',code)
        }
},
methods: {
        /**
         * @param {Object} name
         * 获取小程序传入的参数:用户code
         */
        getUrlParam(name) {
          var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
          var rrr = window.location.href.split('?')[1]; //因为用的hash模式,没办法用search属性,
          // var rrr = window.location.search; //history模式(路由没有#),可以用search属性
          var r = rrr.match(reg);
          if (r != null) return unescape(r[2]);
          return null;
        },
}

3.H5收银台页面

  • 下单后拿code以及下单参数,请求后端Api,拿到支付需要的参数,跳转到小程序的支付页。(具体和后端商量看怎么配合) 注意参数package和paySign!!!
    weixinPay(){
        //微信环境,微信小程序支付
        let params = {
                xxx:xxxx, //其他下单参数
                code:this.code
        }
        api.orderPay(params).then((orderRes)=>{
                let {data} = orderRes
                this.weixinMiniProgramPay(data) 
        })
    },
    /**
     * 跳转到微信小程序支付
     */
    weixinMiniProgramPay(payDataStr){
            let payParams = `?nonceStr=${payDataStr.nonceStr}&package=${encodeURIComponent(payDataStr.package)}&paySign=${encodeURIComponent(payDataStr.paySign)}&signType=${payDataStr.signType}&timeStamp=${payDataStr.timeStamp}`
            jWeixin.miniProgram.navigateTo({
                    appId:'wx126ae2069f831xxx',
                    url:`/pages/pay/index${payParams}`,
                    envVersion:'develop',
                    success(res) {
                            console.log(res,'跳转成功') 
                    },
                    fail(res){
                            console.log(res,'跳转失败')
                    }
            })
    },

4.小程序支付页面

onLoad(options) {
        this.toMiniPay(options)
},
methods:{
        toMiniPay(data){
                uni.requestPayment({
                    timeStamp: data.timeStamp,
                        nonceStr: data.nonceStr,
                        package: decodeURIComponent(data.package),
                        signType: data.signType,
                        paySign: decodeURIComponent(data.paySign), 
                        success:(res)=>{
                            let pagePath="/pages/order/index" //H5指定的页面
                            uni.navigateTo({
                                    url:`/pages/index/index?pagePath=${pagePath}`
                            })
                            //支付成功,回去嵌入h5的页面,url指向H5支付成功对应的页面
                        },
                        fail: (res) => {
                               //支付失败,回去嵌入h5的页面,url指向H5支付失败对应的页面
                                console.log('fail:' + JSON.stringify(res));
                        }
                })
        }
}

6.H5引入微信JS SDK

<html lang="zh-CN">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>
        </title>
        <script>
            var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
            document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
        </script>
        <!-- 微信JS SDK -->
	<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
        <link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
    </head>
    <body>
        <noscript>
            <strong></strong>
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
    </body>
</html>

7.H5跳小程序传参数踩坑记录

  • package和paySign参数
package: "prepay_id=wx09160546182232dea6c853cfxxxxxxxxxx"
paySign: "NYBvV2dk//xxxxxxxxxxxxxxxxx+m80d35A=="
//都有特殊符号'=',需要encodeURIComponent编码一下,不编码在小程序支付页面拿到的参数就是:
package: "prepay_id"
paySign: "NYBvV2dk//xxxxxxxxxxxxxxxxx+m80d35A"