小程序用webview内嵌h5页面,实现分享、微信支付功能 。h5传参跳转web-view 微信小程序
前几天公司头目给了我个任务 ,用小程序的web view组件来嵌入h5页面 还要实现小程序右上角的分享功能 ,最重要的是调用微信支付(小程序中不能使用之前在浏览器中配置的支付功能,只能调用小程序专属的api进行支付。) 接到到这个任务,内心还是很开心的,因为…我爱学习啊啊啊。话不多说,进入正题。
web-view:承载网页的容器。会自动铺满整个小程序页面,个人类型的小程序暂不支持使用 它有三个比较重要的属性 src bindmessage bindload 。
web view详情链接
先说说整体思路吧 小程序只要有三个页面就够了
1.小程序启动时默认打开的页面
2.小程序点击右上角分享 的页面
3.webview嵌入的h5页面 当发起支付时会跳转到wxpay页面 ,调用微信支付
乍一看挺简单的 实际也不是太难,只是当时爬的坑比较多 结尾的时候会总结坑点。
实现步骤:
- 先在web view里引入H5页面 此步骤比较简单
- 引入页面后实现右上角点击分享功能 (提示:web view 不支持分享朋友圈)
具体实现步骤:
1.利用web view 将h5嵌入小程序
//index.vue页面
// 注意: @message 事件是uniapp中的web-viwe 小程序用的是 bindmessage
<web-view src="https://www.baidu.com/" @message="handlePostMessage"></web-view>
- 这个步骤比较简单 @message/ bindmessage 属性的是用来接收h5传递过来的参数 分享时候会用到 下面会讲
2.小程序点击右上角分享
要实现分享功能需先了解 以下内容
-
onShareAppMessage(Object object)
监听用户点击页面内转发按钮(button 组件 open-type=“share”)或右上角菜单“转发”按钮的行为,并自定义转发内容。
注意:只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮 -
web-view 是一个 web 浏览器组件,可以用来承载网页的容器,会自动铺满整个页面 里面有个属性
@message 网页向应用 postMessage 时,会在特定时机(后退、组件销毁、分享)触发并收到消息。
注意:@message 是uniapp中web-viwe的属性 小程序用的是 bindmessage (当时没注意在这卡了一个小时)
在index.vue里面加如下代码
// 用户点击右上角分享 res.webViewUrl是跳转时携带的参数
onShareAppMessage: function(res) {
//console.log(res)里面会有个 res.webViewUrl 指的是当前所在页面的网址
return {
// path --必打开分享时跳转到的页面 默认是当前页面,必须是以‘/’开头的完整路径
// title -- 设置转发时的标题 默认是小程序的名称
// imageUrl -- 设置转发时的图片 不传入 imageUrl 则使用默认截图。
path: '/pages/share/share?url=' + encodeURIComponent(res.webViewUrl)
};
},
在share.vue中添加如下代码
<web-view :src="h5url" @message="handlePostMessage"></web-view>
script添加以下代码
//接收参数 onShareAppMessage 中path 传过来的参数
onLoad: function(e) {
this.h5url = decodeURIComponent(e.url)
}
以上步骤解释:
说白了就是小程序需要从index页面 跳到了share页面 , index用到了 onShareAppMessage 来进行页面的跳转 , share用onLond 接收参数并赋值给自己页面的web-view
- index中的web view是打开小程序首次引入的页面,用户点击右上角分享 后通过onShareAppMessage里面的 path路径跳入到 share.vue页面。
- share.vue 用onLond 接收参数 把接收到的参数(网址)放入到 share.vue 里web-viw组件中的 src属性下 然后点击右上角分享功能就实现了。
- 用到了encodeURIComponent /decodeURIComponent 是防止传参时遇见特殊字符会乱码问题
以上步骤未用到H5 给小程序传参 如需使用H5传递参数实现分享还需在H5添加以下代码
//思路:先判断环境 再执行 wx.miniProgram.postMessage();
var ua = navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i)=="micromessenger") {
//ios的ua中无miniProgram,但都有MicroMessenger(表示是微信浏览器)
wx.miniProgram.getEnv((res)=>{
if (res.miniprogram) {
wx.miniProgram.postMessage({ data: data });
}else{
alert('在微信内,但是不在小程序内')
return false;
}
})
}else{
console.log('在微信外')
}
3.在小程序中调用微信支付功能
调用微信支付原因上面已经做过解释 想要实现功能之前的先搞懂小程序支付流程 小程序支付流程
H5调起微信支付时 用wx.miniProgram.navigateTo 设置跳到 wxpay页面
wxpay.vue页面
<template>
//h5调起微信支付时会跳到 wxpay页面
</template>
<script>
export default {
data() {
return {};
},
created() {},
methods: {
// 生命周期函数--监听页面卸载
onUnload :function() {} //支付完成后 手机左滑时会出现很尴尬的事 相信你会用到这个生命周期 原理不解释了 写了几个小时没精力了
//生命周期函数--监听页面加载
onLoad: function(option) {
if (option) {
//option 有H5页面传递过来的数据
this.setLoading(option);
} else {
wx.navigateBack();
}
// console.log(option);
},
setLoading: function(option) {
var that = this;
// 调用登录接口获取openid
wx.login({
success: function(res) {
// 成功会返回: {errMsg: "login:ok", code: " 获取用户OpenID的ticket"}
that.getOpenId(res.code, option);
// console.log(res);
}
});
},
getOpenId: function(jsCode, option) {
var that = this;
var params = {}; //这里就是调接口拼凑要给后端提供的参数
params.key = option.key,
params.pay_sn = option.pay_sn,
params.password = option.password,
params.rcd_pay = option.rcb_pay,
params.pd_pay = option.pd_pay,
params.integral = option.integral,
params.payment_code = option.payment_code,
params.payment_jscode = jsCode, //把获取到的code传给后端 (必须)到时候退款也会涉及到
wx.request({
url: 'https://www.xxx.com/mobile' + '/index.php?act=member_payment&op=wxa_pay', //引入的https地址
method: 'post',
header: {
'content-type': 'application/x-www-form-urlencoded' // 默认值
},
data: params, //传递的参数 后端会返回一部分 你这里只需要吧 获取用户OpenID的ticket"
success: function(res) {
that.getPrePayId(res.data.datas);
},
fail: function(res) {
console.log(res);
wx.showModal({ title: '网络超时', content: '刷新重试', showCancel: !1 });
}
});
},
getPrePayId: function(res) {
var that = this;
wx.requestPayment({
//成功之后,调用小程序微信支付
timeStamp: res.timeStamp,
nonceStr: res.nonceStr,
package: res.package,
signType: res.signType,
paySign: res.paySign,
success: function(res) {
wx.showToast({
title: '支付成功',
icon: 'success',
duration: 1650
}),
console.log('支付成功');
},
fail: function() {
wx.showToast({
title: '支付失败',
icon: 'clear',
duration: 1650
}),
console.log('支付失败');
}
});
}
}
};
</script>
H5代码
// 小程序支付函数
mini_program_pay = function (queryParam ) {
var ua = navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i)=="micromessenger") {
//ios的ua中无miniProgram,但都有MicroMessenger(表示是微信浏览器)
wx.miniProgram.getEnv((res)=>{
if (res.miniprogram) {
console.log('在小程序内')
wx.miniProgram.navigateTo({
url: "/pages/wxpay/wxpay?"+queryParam //小程序的支付地址,queryParam是需要传递的商品id等数据
});
return false;
}else{
console.log('在微信内,但是不在小程序内')
return false;
}
})
}else{
console.log('在微信外')
return false;
}
};
写的时间太长了 有些晕 简短的说下重点步骤吧 ! 注释其实说的挺多的,比较详细
H5要在使用wx.miniProgram.navigateTo 携带参数 跳转到小程序的wxpay页面 跳转需要引入js-sdk才可以跳转 去官网查下最新版本 不然可能会不成功
- H5传递过来的参数 wxpay还是用onload接收 (后端需要什么数据 在H5页面搜集好 直接传递过去就行了)
- 然后wx.login() 获取的code 一定要传递给后端 , 会涉支付及退款问题
其实支付这块稍微复杂一些 但前端做的事情比较少 , 后端复杂一些.。前端只需要去H5搜集参数传给小程序,小程序在wx.login()获取到code 然后再调接口拼接数据,最后wx.requestPayment 直接拉起微信支付就好了
写到这微信支付也就告一段落了 ~~~
在总结一下 遇到的各种问题吧 !
- 微信开发者工具会有缓存 调试的时候多清清!有时候实现不了功能可能是缓存问题
- 微信开发者工具调试时可以出现跳转, 而真机调试不能实现时 也可尝试清缓存, 也可以尝试运行在浏览器端 如果 浏览器出现页面无限跳转 一定是H5D端 判断是否是微信环境出了问题
- 如果在扫描体验版进入小程序时 页面不加载 点击左上角的小房子图标会刷新 说明体验版二维码不对 仔细查看指定路径
- 如果页面不跳转或者是接受不到参数 仔细耐心多看文档.
- index中的 src末尾得加.html 不然体验版会出现一些小问题.
- wx.requestPayment 拼接参数时得按一定的顺序
- 还有些想起来在补充吧 我该去吃饭了 ~~
就这三个功能折磨我的时间挺长的 ! 爬了无数的坑 终于实现了 (我引入的H5页面还是用JQuery+template模板写的 )所以当时遇到的问题比较多 快自闭了 希望你们能顺利一些吧!
如果后期有精力后期再补充爬过的坑。我也是站在了巨人的肩膀上 所以再次感谢一下 大佬的文章
以上有很多地方都是借鉴 这位大佬的 再次感谢 ~~
初识前端 ,希望能与各位同仁多多交流讨论。
https://www.cnblogs.com/wangvv/p/13646057.html