之前做一个新闻项目的详情页微信二次分享,开发阶段略显痛苦,google到的博客都是一半一半的,加之对微信公众号的配置不熟悉,绕了很多弯路,现在慢慢整理下来。
微信二次分享需要依赖公众号配置,这样在H5页面被分享出去之后,别人看到的就不只是一个简单的页面中包裹的标题加一个url,而是可以自定义title和内容以及图标的具有一定美观度的分享块。
1. 获取测试号相关信息
进入微信公众帐号测试号申请系统 (mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index)
只是为了测试这个文档转发,只需要获取「测试号信息」和配置「JS接口安全域名」
2.签名算法
有了上面的两个信息,就可以完成一个「签名算法」服务
// express 实现
app.use('/sdWxService', async function (req, res, next) {
const {url} = req.query;
const access_token = await axios.get(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${AppID}&secret=5397a76acffd10116413dbd741849c1c`).then(
(res) => {
const {access_token} = res.data;
return access_token;
});
const ticket = await axios.get(`https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${access_token}&type=jsapi`).then((res) => {
console.log(res.data)
return res.data.ticket;
});
let noncestr = uuidv4();
let jsapiTicket = ticket
let timestamp = moment().unix().toString()
// 此处noncestr为全部小写
let string = `jsapi_ticket=${jsapiTicket}&noncestr=${noncestr}×tamp=${timestamp}&url=${url}`
let signature = crypto.createHash('sha1').update(string).digest('hex')
res.json({
status: 200,
data: {
jsapiTicket,
appId: AppID,
timestamp,
nonceStr: noncestr, // 注意此处大小写
signature,
}
})
});
有几个常见问题需要记录下
- timestamp、 nonceStr 都必须是字符串
- 确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致
- 如果是正式的公众号,确保一定缓存access_token和jsapi_ticket(测试号就先不关心这个了)
- timestamp 是10位时间戳
- timestamp与用以签名中的timestamp一致
- url一定要注意:不进行URL 转义、签名用的url必须是调用JS接口页面的完整URL
- 确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。
- 前端需要用js获取当前页面除去'#'hash部分的链接(可用location.href.split('#')[0]获取,而且需要encodeURIComponent
- 注意:noncestr,在拼接signature原串时,这个key全部小写;但是前端在config中配置时,需要驼峰的nonceStr
- 对于最终产生的信息可以使用 微信 JS 接口签名校验工具 (mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign)
- 关于接口签名校验工具校验一致 但是仍然报 invalid signature 错误的,一定要认真检查上述的几个注意事项,还有developers.weixin.qq.com/doc/offiacc…
3. H5页面配置
首先页面要引入微信的sdk,有两种方式,这里也顺便贴一下:
方式一
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js />
方式二
npm install weixin-js-sdk
/* 使用CommonJs规范引入 */
const wx = require('weixin-js-sdk');
/* 使用ES6模块引入 */
import wx from 'weixin-js-sdk';
- H5分享模块代码
import wx from 'weixin-js-sdk';
import axios from 'axios';
import moment from 'moment';
import _ from 'lodash';
const url = encodeURIComponent(window.location.href);
const getSignature = () =>
axios
.get(
`http://192.168.0.106:4003/sdWxService?url=${url}`,
)
.then(res => res.data);
export default async function initWeChat() {
const {
signature,
nonceStr,
timestamp,
appId,
jsapiTicket,
} = await getSignature();
wx.config({
// debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId, // 必填,公众号的唯一标识
jsApiList: [
'checkJsApi',
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
],
nonceStr, // 必填,生成签名的随机串
signature, // 必填,签名
timestamp, // 必填,生成签名的时间戳
});
}
export const updateWeChatShareData = () => {
initWeChat();
// TODO:确认华安提供的图片连接
const wxShareData = {
title: '活动页面', // 分享标题
desc: '活动页面---111', // 分享描述
link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl:
'https://res.wx.qq.com/a/wx_fed/assets/res/OTE0YTAw.png', // 分享图标
};
wx.ready(() => {
// 需在用户点击分享按钮前就先调用
wx.updateAppMessageShareData(wxShareData);
wx.updateTimelineShareData(wxShareData);
wx.onMenuShareAppMessage(wxShareData);
wx.onMenuShareTimeline(wxShareData);
});
};
updateWeChatShareData();
最终分享的结果截图(微信开发者工具中调试截图),可以看出分享的title已经设置为H5模块中定义的title值。
还有一种情况是要禁止微信中页面的分享,参考下面代码段
这个方法好像有问题了,WeixinJSBridge.call会报错了,使用下面的方法
function onBridgeReady() {
window.WeixinJSBridge.call('hideOptionMenu');
}
if (typeof WeixinJSBridge === 'undefined') {
if (document.addEventListener) {
document.addEventListener(
'WeixinJSBridgeReady',
onBridgeReady,
false,
);
} else if (document.attachEvent) {
document.attachEvent(
'WeixinJSBridgeReady',
onBridgeReady,
);
document.attachEvent(
'onWeixinJSBridgeReady',
onBridgeReady,
);
}
} else {
onBridgeReady();
}
使用API提供的方法实现隐藏微信、朋友圈、QQ等分享,初始化时需要在wx.ready(() => {})的回调中实现
wx.hideMenuItems({
menuList: [
'menuItem:share:appMessage',
'menuItem:share:timeline',
'menuItem:share:qq',
'menuItem:share:weiboApp',
'menuItem:share:facebook',
'menuItem:share:QZone',
'menuItem:favorite',
], // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
});
也可以动态展示出来
wx.showMenuItems({
menuList: [
'menuItem:share:appMessage',
'menuItem:share:timeline',
'menuItem:share:qq',
'menuItem:share:weiboApp',
'menuItem:share:facebook',
'menuItem:share:QZone',
'menuItem:favorite',
], // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
});
wx.config中的jsApiList需要配置hideMenuItems和showMenuItems
欢迎扫码关注作者公众号