项目场景:
甲方项目主程序是uniapp开发的,兼容ios、安卓、微信小程序三个端的一套代码,我司做了项目中的一个服务,但因为嵌入问题和代码权限问题,最终选择使用H5嵌入uniapp中。做这个H5遇到了不少的问题,大部分的精力都是在验证H5有没有实现某种功能的权限。
一、H5 分享小程序
需求: A小程序的H5中有一个分享产品的这么一个动作,点击分享产品,可以分享到微信群里,供用户购买;但是货主是甲方uniapp开发的项目,用户点击微信群里分享出来的链接,直接跳转到用户的B小程序里接订单;大致流程:A小程序里的H5页面,分享出去一个链接,用户点击这个链接需要跳转到B小程序,并做之后一些列的接单操作;所以分享出去的这个链接应该是去往B小程序的一个链接;
微信其实是不允许这么做的,因为可能存在恶意引流问题;况且小程序内嵌的H5,不支持分享本页面以及分享小程序卡片功能,更不要说来实现分享一个别的小程序了;
所以有两种方法来解决这个问题:
1.1、不借助原生小程序,可满足小程序ios和安卓
如果不借助原生小程序的话,仅仅依靠H5做分享,只能通过分享文字,以及短连接来生成分享码,类似于一条短信,复制好短信,短信里包含一个地址,这个地址就是B小程序的短连接即可。但是短链接只允许某一个用户使用,一个地址只允许1个用户被访问,所以这个分享出来的卡片无法被多个人点击。
copyContent(params, type = 'input') {
const { param1 } = params
value = `您有一笔新的订单,` + `点击查看详情👉${location.origin}/sms?type=wxUrl&p1=${params1}`;
const input = document.createElement(type);
input.setAttribute('readonly', 'readonly'); // 设置为只读, 防止在 ios 下拉起键盘
// input.setAttribute('value', value); // textarea 不能用此方式赋值, 否则无法复制内容
input.value = value;
document.body.appendChild(input);
input.setSelectionRange(0, 9999); // 防止 ios 下没有全选内容而无法复制
input.select();
document.execCommand('copy');
document.body.removeChild(input);
this.$toast.success("复制成功,快去转发吧!");
}
代码说明:
1、通过点击按钮触发 copyContent 函数,给用户在剪贴板中自动放入一段文字:您有一笔新的订单,点击查看详情👉https://xxx.xxx.com/sms?type=wxUrl&p1=123456。用户点击链接,跳转到项目的一个中转页面,这个页面的逻辑就是获取到路径上的参数,通过参数使用上方图片中的方法生成微信小程序的URL Link并做自动跳转即可。
2、这样,地址https://xxx.xxx.com/sms?type=wxUrl&p1=123456 就可以被多个人点击,每次生成不同的URL Link,从而实现了一个地址可供多人使用。
3、每天生成 URL Scheme 和 URL Link 总数量上限为50万。所以如果用户量大的话,最好在https://xxx.xxx.com/sms页面使用本地存储localStorage存储已经生成过的地址,来防止同一个用户多次点击同一个地址而浪费地址生成次数。
4、可以兼容小程序,安卓,ios;注意H5无法自动调用微信好友列表。
1.2、借助原生小程序:不考虑安卓和ios
跳转到原生小程序页面后,使用wx.navigateToMiniProgram直接跳转到B小程序即可,然后将B小程序的当前页面分享出去,就可以让用户点击分享的卡片链接进行接下来的动作啦。
方案说明:
1、需要借助原生小程序做小程序跳转;
2、分享出去的内容就是卡片形式的,用户体验感比较好;
3、分享出去的卡片也没有次数限制。
H5 支付
微信小程序中的H5不支持直接调用微信支付,所以需要小程序去帮助做微信支付。将所有参数处理好,通过 uni.redirectTo 跳转到小程序支付逻辑页面,切记处理参数的时候,一定要通过encodeURIComponent来进行编译,因为微信支付中的参数有特殊字符,如果不编译,则可能出现字符串丢失,导致无法唤起微信支付;
代码如下:
// H5 代码逻辑
let obj = {
appId: encodeURIComponent(params.appId),
timeStamp: encodeURIComponent(params.timeStamp),
nonceStr: encodeURIComponent(params.nonceStr),
package: encodeURIComponent(params.package),
signType: encodeURIComponent(params.signType),
paySign: encodeURIComponent(params.paySign)
};
let callbackPage = this.$route.fullPath;// 该参数是当用户支付完成后。继续跳转到之前的H5页面
let params = `appId=${obj.appId}&timeStamp=${obj.timeStamp}&nonceStr=${obj.nonceStr}&package=${obj.package}&signType=${obj.signType}&paySign=${obj.paySign}&cbpage=${encodeURIComponent(callbackPage)}`;
uni.redirectTo({
url: `/wxpaying?${params}`
});
// 微信小程序原生代码
async onLoad(opt) {
let _this = this;
try {
// 微信小程序
wx.requestPayment({
timeStamp: decodeURIComponent(opt.timeStamp),
nonceStr: decodeURIComponent(opt.nonceStr),
package: decodeURIComponent(opt.package),
signType: decodeURIComponent(opt.signType),
paySign: decodeURIComponent(opt.paySign),
success: function (res) {
// console.log('success:' + JSON.stringify(res));
_this.callbackPage(opt.cbpage + encodeURIComponent('&payStatus=success')); // 这里是H5传过来的回调页面,支付完成跳转回去
},
fail: function (err) {
// console.log('fail:' + JSON.stringify(err));
_this.callbackPage(opt.cbpage + encodeURIComponent('&payStatus=error')); // 这里是H5传过来的回调页面,支付完成跳转回去
}
});
} catch (e) {
// 支付失败,提示并跳转回撮合页面
uni.showToast({
title: '微信调用支付失败,请联系管理员!',
duration: 2000
});
setTimeout(() => {
uni.redirectTo({ url: '/index' });
}, 2000);
}
}
二、H5与原声交互
H5中的bindMessage函数并不是实时交互的,是在特定的时机触发,所以原生与H5交互无法做到立马触发。参考地址
三、微信小程序短连接在不同环境点击打开的小程序版本不同
生成URL Link 方法中,如果想测试对应的版本,切记不要再微信中去点击生成的链接,因为从微信打开的小程序,永远是线上正式版小程序,不会跳转到开发版和体验版的,需要将链接复制到其他app中或者直接在手机浏览器中打开即可跳转对应版本的小程序。
总结
小程序的 webView 权限少的可怜,如果官网中没有提及某一些权限和方法,则H5一定无法实现该方法,请换一种思路去开发。大家开发的时候慎用H5,不要把太重的功能放在H5上去实现!