1.介绍
需求描述:app中的h5页面有两个按钮分别为分享给朋友,及分享到朋友圈,分享样式自定义。
方向:使用weixin-js-sdk。
结果:h5无法完成分享到给朋友圈,及分享到朋友圈,需app端配合建立微信桥。
原因:weixin-js-sdk的分享给朋友及分享到朋友圈作用仅为设置分享的内容,并没有分享的行为。需要在微信中点右上角的三个点手动分享。
2.weixin-js-sdk
了解了weixin-js-sdk在分享功能上能做什么之后,先看一下官方文档的使用步骤准备开始使用weixin-js-sdk编辑分享内容。
先看这么多,我们首先需要设置JS接口安全域名及对wx进行配置,个人认为对前端开发来讲,在开发过程中比较不容易弄的两个点就是步骤一及步骤三的配置。
原因:
- 步骤一:绑定JS接口安全域名的时候,需要域名通过ICP备案和将指定文件放入web服务器中。
- 步骤三:配置中的签名需要根据指定规则去进行加密且还有生成的时间及随机串等,一般应该后台同学来做。
解决:
- 步骤一:在没有域名时,可以采取使用测试微信公众号方式,利用内网穿透去进行设置JS安全域名,测试微信公众号的要求少一点。
- 步骤三:使用nodeJs模拟后台同学,根据文档去进行生成签名及随机串生成签名的时间戳等返回到前端。
3.开始动手前的准备工作
3.1 内网穿透
使用内网穿透可以获得临时域名,可以在微信中打开我们的页面方便测试,并设置JS接口安全域名,如有服务器及域名不需要内网穿透。
- ngrok.com 国外 注册既使用,但大部分网页在微信中因被举报无法打开。
- natapp.cn 国内 需实名认证,免费隧道慢,有收费隧道。
3.2 申请测试微信公众号
申请测号的目的是为了获得appID和appsecret生成标签,设置JS接口安全域名,如果没有服务器及域名,需要使用测试微信公众号。因为使用正式公众号需要在设置JS接口安全域名时,域名需通过ICP备案,及将指定文件放入web服务器中。
4. 根据文档一步一步来使用nodeJs生成签名 JS-SDK使用权限签名算法
文档中说要生成签名需要jsapi_ticket,它是公众号调用微信js接口的临时票据,要获得jsapi_ticket又需要access_token。
4.1.获取access_token
4.1.1接口调用请求说明
请求方式GET:
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
请求参数: APPID,APPSECRET,测试公众号中获取
4.1.2返回响应
{"access_token":"ACCESS_TOKEN","expires_in":7200}
说明:
access_token:获取到的凭证
expires_in: 有效时间
4.1.3 node请求获取access_token
// 使用axios进行get请求
const axios = require('axios');
const appId = '***';//微信测试公众号中获取
const secret = '***';//同上
/**
* @description 获取access_token
* @param url 网页的url,后续会用
*/
const getAccess_token = (url) => {
axios.get(`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appId}&secret=${secret}`).then(async (res) => {
const params = {
access_token: res.data.access_token,
url
}
if (res.data.access_token) {
await jsapi_ticket(params);// 暂时没有将数据存到全局缓存中,所以通过传参的方式。
}
console.log(res.data); //返回结果
}).catch(err => {
console.log('axios occurs ', err);
});
}
执行结果成功获取到access_token
获取到access_token后进行下一步操作,去获取jsapi_ticket,如返回非以上结果,请查询官网文档。
4.2 获取jsapi_ticket
4.2.1 文档
根据官网指导用第一步拿到的access_token后去获得jsapi_ticket。
4.2.1 请求地址
请求方式GET
地址: https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
ACCESS_TOKEN:为之前请求结果中的access_token
4.2.2返回响应
{
"errcode":0,
"errmsg":"ok",
"ticket":"xLdikRXVbTPdHSM05e5u5sUoXNKd841ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
"expires_in":7200
}
//ticket就是jsapi_ticket。其他参数不做过多解释。
4.2.3node中获取jsapi_ticket。
/**
*
* @description 获取jsapi_ticket
* @param access_token 暂时通过getAccess_token函数传入 正常应该在缓存中获取
* @param url 网页的url,后续会用
*/
const jsapi_ticket = async (params) => {
axios.get(`https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${params.access_token}&type=jsapi`).then(async res => {
const signParams = {
ticket: res.data.ticket,
url: params.url
}
await getSign(signParams);
console.log(res.data); // 返回的数据
}).catch(err => {
console.log('axios occurs ', err);
});
}
执行结果
获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。
4.3 签名算法
4.3.1文档
4.3.2 整理文档生成签名的步骤
从文档中得到我们需要的几个参数然后生成签名:
序号 | 参数 | 说明 | 1 | noncestr | 随机字符串 | 2 | 有效的jsapi_ticket | 从上述接口获得 | 3 | timestamp | 时间戳 | 4 | url | 当前网页的URL不包含#及其后面部分 | 5 | 排序 | 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序) | 6 | 拼接 | 使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1参数需小写 | 7 | 加密得到签名 | 对string1进行sha1算法加密 (js-sha1包提供的功能),得到signature |
---|
4.3.3 noncestr随机字符串
/**
* 生成签名的随机串
* @return {随机字符串}
*/
let createNonceStr = () => {
return Math.random().toString(36).substr(2, 15)
}
4.3.4有效的jsapi_ticket
官方建议存在全局缓存中,然后从缓存中读取,目前为了方便,用了偷懒的方式,通过传参数的方式进行获取。
4.3.5 timestamp 时间戳
/**
* 生成签名的时间戳
* @return {时间戳}
*/
let createTimestamp = () => {
return parseInt(new Date().getTime() / 1000) + ''
}
4.3.5 当前网页的URl
该参数通过前端传入
4.3.6 将所有待签名参数排序(字典序从小到大)
所有待签名参数有noncestr、jsapi_ticket、timestamp、url
/**
* 对参数对象进行字典排序
* @param {对象} args 签名所需参数对象
*/
let dictionarySort = (args) => {
var keys = Object.keys(args)
keys = keys.sort()
var newObjs = {}
keys.forEach(function (key) {
newObjs[key.toLowerCase()] = args[key]
})
return strJoin(newObjs)
}
4.3.7 拼接,将所有参数字典排序后拼接
/**
* 拼接
* @param {对象} obj 排序后的参数
*/
let strJoin = (obj) => {
var string = ''
for (var i in obj) {
string += '&' + i + '=' + obj[i]
}
string = string.substr(1)
return string
}
排序和拼接其实可以合并,也可以用一个偷懒的方式去做,手动拼接
let lazyMode = (ticket, noncestr, ts, url) => {
const str = 'jsapi_ticket=' + ticket + '&noncestr=' + noncestr + '×tamp='+ ts +'&url=' + url;
return str
}
4.3.8加密生成签名
// sha1加密
let sha1 = (str) => {
let shasum = crypto.createHash("sha1")
shasum.update(str)
str = shasum.digest("hex")
return str // 返回加密后的签名。
}
4.3.9 整理数据 返回到前端
/**
*
* @description 整理数据返回到前端
* @param params.url 当前网页
* @param params.ticket ticket
* @return {allData} 全部数据
* jsapi_ticket 生成的签名
* nonceStr 随机字符串
* timestamp 时间戳
* url 当前网页
* appId appid
* signature 签名
*/
let getSign = (params) => {
// 所有待排序的参数
const ret = {
jsapi_ticket: params.ticket,
nonceStr: createNonceStr(),
timestamp: createTimestamp(),
url: params.url
};
const string = dictionarySort(ret); // 将所有参数排序
ret.signature = sha1(string); // 对排序的参数加密
ret.appId = appId; // 增加appId 前端需要
allData = ret; // 用了一个全局变量存放了所有的数据
}
app.post('/sign', async (req, res) => {
await getAccess_token(req.body.url);
res.send({
code: 0,
data: {
...allData
}
})
});
app.listen(8888, () => console.log(`Example app listening on port ${8888}!`))
至此,node部分暂时结束,除了没做全局缓存。
5.前端部分
前端部分用的vue
created() {
// 调用接口,url为当前网页,这里路由用的history模式,所以暂时没有#号,没有做任何处理
this.testAction({url: window.location.href}).then((res) => {
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: res.appId, // 必填,公众号的唯一标识,填自己的!
timestamp: res.timestamp, // 必填,生成签名的时间戳,刚才接口拿到的数据
nonceStr: res.nonceStr, // 必填,生成签名的随机串
signature: res.signature, // 必填,签名,见附录1
jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline'] // 所需的weixin-js-api
});
wx.ready(function() {
wx.checkJsApi({
jsApiList: ['onMenuShareAppMessage'],
success: function(res: any) {}
});
});
wx.onMenuShareAppMessage({
title: '分享朋友',
desc: '分享朋友123',
link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: '', // 分享图标
success: function() {},
cancel: function() {}
});
wx.onMenuShareTimeline({
title: '分享到朋友圈', // 分享标题
link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: '', // 分享图标
success: function() {
// 用户点击了分享后执行的回调函数
}
});
});
}
至此,前端部分结束。可以根据业务需求修改编辑内容的位置。
在微信中打开网页进行测试,点击微信中的右上角三个点去分享。
总结
1.该版本node部分还需完善并没有做到全局缓存。每天的接口请求次数有限所以需要注意存放,建议放到数据库中。
2.H5的weixin-js-sdk没有分享动作的能力,只是编辑出去的内容,如果安卓及ios端有修改内容,那么H5端的数据会失效。
3.注意调用给后台传url时的#,及分享的链接域名要与设置的安全域名一致。
4.欢迎各位互相交流经验。后续有时间会完善缓存版本的node。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!