补充一点,当微信分享完成后,出现了非二次分享问题,现象是,测试有时候点了分享,可以正常显示自定义分享内容,有时候又不行,这边要注意,我们测试的网络环境差,因此可能会出现跟我们不同的现象。
究其原因,是执行顺序的问题
我们的组件逻辑和微信分享函数的执行是异步进行的,哪个先执行完时间上不确定。
所以我们的分享函数必须先行执行,才能最大程度的保障在react组件挂载完成前成功初始化!否则,没有完成初始化,该分享函数不执行,微信的wx相关函数也就没有触发的可能,error不会走到,success也不会走到!
当然,这么做也不是每次都能成功出现自定义的分享内容,有时候仍旧是默认的,这个博主感觉无解。。。
1、cdn 与 本地下载的js包的问题
当我在index.html中引入以下本地wx对象的文件,在使用wx对象时,报错,无法找到这个wx对象
<script src="../utils/jweixin.js" type="text/javascript"></script>
之后,我在官方文档上找到了cdn地址,换成了cdn地址就可以了。。。
<script src="https://res2.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
2、接第1点来说,http与https是不同的,当我们的dns域名地址是https协议,那么如果使用了http不安全协议的包,就会在console控制台报错,导致文件引入执行失效,例如
<script src="http://res2.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
3、微信自定义分享的内容不生效,还是默认采用原先的默认分享标题和图标
大概率是配置写错了
4、微信自定义分享是需要一个测试公众号的,没有申请好的公众号,微信是不会让你调他们的接口的,有一个测试公众号,关注它就可以了,关注它只是为了获得调用wx接口的权限
5、微信第一次分享自定义内容一切正常,但是从分享的地方点击该链接进行第二次分享时,发现自定义分享失效了,变成了原本默认的分享标题和图标
因为微信会默认为每一个二次分享的window.location.href地址加上以下字符串的
?from=timeline&isappinstalled=0 或 ?from=singlemessage&isappinstalled=0
正常的字符串
https://xxx.xxx.com:8443/oss-smkh-h5/#/openAccount?params=YWNjb3VudG5vPWdoXzllODUwODU3NDZjZSZicmFuY2g9MjQwMCZzc2NvZGU9NzAyMDc3JnNzbmFtZT3osKLnuqImdGVtcGxhdGU9MTA1MA==
被强行加塞以上字符串后,完整的链接如下
https://xxx.xxx.com:8443/oss-smkh-h5/?from=timeline&isappinstalled=0#/openAccount?params=YWNjb3VudG5vPWdoXzllODUwODU3NDZjZSZicmFuY2g9MjQwMCZzc2NvZGU9NzAyMDc3JnNzbmFtZT3osKLnuqImdGVtcGxhdGU9MTA1MA==
而且微信是有签名检验的,从而导致微信签名不通过,微信自定义分享功能将失效,将保持默认分享样子。。。
解决办法就是,在组件componentDidMount加上如下语句,替换掉强行加塞的字符串:
componentDidMount = async () => {
//在微信中打开
if (this.state.isWx) {
Toast.info('请用浏览器打开', 2);
// 微信分享封装函数 这个函数如果在componentDidMount执行,会导致用户在微信初始化未完成时就进行分享,自定义分享不执行,保留原本的默认分享,因此这边建议方在index.html中或者路由渲染组件之前,请注意,如果不是在微信平台下,我们引进全局的wx对象会报错!
weChatShare(
'https://xxxx-test-1258285289.cos.ap-guangzhou.myqcloud.com/ops/2019-12/1576823922427-c67d7ed1d44c475eb365c36c3f9fea2f.png',
'炼金术App开户',
'欢迎使用炼金术App',
); // 只能在测试环境中测,白名单只能包含开发环境或测试环境中的一个,为了方便测试人员测试,规定开放测试环境
// 检测路径 然后重定向(替换掉微信强制加上的字符串,重新进入页面才能生效)
// 如果不这么做,由于微信分享的路径会默认加上?from=timeline&isappinstalled=0 或 ?from=singlemessage&isappinstalled=0 从而导致微信签名不通过,微信自定义分享功能将失效,保持默认分享
let newUrl = window.location.href;
if (newUrl.indexOf('from=singlemessage') > -1 || newUrl.indexOf('from=timeline') > -1) {
let str = newUrl.split('#');
let tempStr = str.join().split('?');
newUrl = tempStr[0] + '#/openAccount?' + tempStr[2];
window.location.href = newUrl;
}
}
}
PS:请万分注意!!! 判断的时候一定要考虑到
?from=singlemessage // android真机上可以二次分享,且可以先分享到微信朋友圈,在点击朋友圈的分享进行二次分享。 而ios则只能进行转发给朋友,点击分享给朋友的链接进行的二次分享,无法先分享到微信朋友圈,在点击朋友圈的分享进行二次分享
?from=timeline // 这一句则可以完善ios的分享功能
好了,主要的要点讲完了,接下来贴完整代码片段:
weChatShare.js
/**
*
* @param {string} imgUrl 图片服务器路径
* @param {string} title 标题
* @param {string} desc 描述
*/
import envConfig from '../env';
export function weChatShare(imgUrl, title, desc) {
console.log('window.wx', window.wx);
// var newUrl = window.location.href.split('#')[0]; // newUrl = encodeURIComponent(newUrl);
var newUrl = window.location.href;
var oHttp = window.location.protocol;
var locHost = window.location.host;
// var oimgUrl = oHttp + '//' + locHost + imgUrl; // 测试
var oimgUrl = imgUrl; // 单独图片路径 其余两种会携带主机地址
// var oimgUrl =
// oHttp +
// '//' +
// locHost +
// '/fintech-oss-monthnews/monthly-page/images/pageImg/shareImg.jpg'; // 正式
console.log('地址错误?', oHttp + '******' + locHost + '******' + imgUrl);
console.log('图片地址', oimgUrl);
console.log('网址', newUrl);
var xhr = new XMLHttpRequest();
xhr.open('POST', ''.concat(envConfig.wechatHost, '/m/rest/wechat/getJssdkSignature'));
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send('url='.concat(newUrl));
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var data = JSON.parse(xhr.responseText);
console.log('微信config', data);
if (data.status === '1') {
var newAppID = data.data.appid;
var newTime = data.data.timestamp;
var newNonceStr = data.data.nonceStr;
var newSign = data.data.signature;
console.log(newAppID, newTime, newNonceStr, newSign, window.wx, newUrl); // alert(newUrl)
console.log('wx对象', window.wx);
window.wx.config({
debug: false,
appId: newAppID,
timestamp: newTime,
nonceStr: newNonceStr,
signature: newSign,
jsApiList: [
//调用了两个分享接口,分别是朋友圈和个人
'onMenuShareTimeline',
'onMenuShareAppMessage',
],
});
window.wx.ready(function() {
var obj = {
// title: "降税利好,市场走势何去何从", // 标题
// desc: "用政府收入的减法换来企业效益的加法和市场活力的乘法。", // 描述
title: title,
// 标题
desc: desc,
// 描述
link: newUrl,
// 分享的URL,必须和当前打开的网页的URL是一样的
imgUrl: oimgUrl, // 缩略图地址
};
window.wx.onMenuShareAppMessage({
title: obj.title,
desc: obj.desc,
link: obj.link,
imgUrl: obj.imgUrl,
success: function success() {
console.log('success'); // sensors.track("Share", {
// title: obj.title,
// ShareContent: obj.desc,
// ShareFrom: "增值税下降H5",
// ShareWay: "wechat"
// });
},
});
window.wx.onMenuShareTimeline({
title: obj.title,
desc: obj.desc,
link: obj.link,
imgUrl: obj.imgUrl,
success: function success() {
console.log('success'); // sensors.track("Share", {
// title: obj.title,
// ShareContent: obj.desc,
// ShareFrom: "增值税下降H5",
// ShareWay: "wechatTimeline"
// });
},
});
});
window.wx.error(function(res) {
console.log(res); // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
}
}
};
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="icon" href="favicon.ico" type="image/x-icon" />
<!-- <script src="../utils/jweixin.js" type="text/javascript"></script> -->
<script src="https://res2.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<!-- <script src="https://wechatfe.github.io/vconsole/lib/vconsole.min.js?v=3.2.0"></script>
<script>
var vConsole = new VConsole();
console.log('Hello world');
</script> -->
<title>在线开户</title>
</head>
<body>
<div id="root"></div>
</body>
<script type="text/javascript">
// 移动端适配
(function(doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth > 1024) {
docEl.style.fontSize = '12px';
} else {
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
window.wx = wx;
})(document, window);
var ua = navigator.userAgent;
var isAndroid = /Android/.test(ua);
// js 原生交互代码
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge);
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady',
function() {
callback(WebViewJavascriptBridge);
},
false
);
if (!isAndroid) {
if (window.WebViewJavascriptBridge) {
return callback(WebViewJavascriptBridge);
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback);
}
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() {
document.documentElement.removeChild(WVJBIframe);
}, 0);
}
}
}
function getAccessToken() {
if (isAndroid) {
try {
var data = CgwsH5JS.getAccessToken();
sessionStorage.setItem('userInfo', data);
} catch (e) {
console.log(e.message);
}
} else {
connectWebViewJavascriptBridge(function(bridge) {
bridge.callHandler('getAccessToken', 1, function(data) {
sessionStorage.setItem('userInfo', data);
console.log('getAccessToken:', data)
});
});
}
}
getAccessToken();
</script>
</html>