记一次个人开发者如何让H5婚礼请帖在微信里「体面」的流转!

【记一次个人开发者如何让H5婚礼请帖在微信里「体面」的流转!】我的公众号原文地址

?? 很关键的前提 ??
??个人开发者使用wx-jssdk的权限受限??(无转发给好友、分享朋友圈等权限),可先去「设置与开发-接口权限」查看权限详情。
?♂?文末是我说的「体面」??
公众号设置 记一次个人开发者如何让H5婚礼请帖在微信里「体面」的流转!
文章图片

记一次个人开发者如何让H5婚礼请帖在微信里「体面」的流转!
文章图片

服务端代码
(基于Koa2开发,省略服务器搭建代码,仅提供关键步骤代码)
1.编写「服务器配置-服务器地址(URL)」所需要的接口地址
https://yourserver.com/api/ch...
let sha1 = require("sha1"); /** * 微信公众号-指定服务器地址-验证接口 * @param {*} ctx */ checkToken: async (ctx) => { const { signature, timestamp, nonce, echostr } = ctx.query; //ctx.query获取请求中携带的参数 let { token } = wxconfig; //将Token,timestamp,nonce按字典排序,排序后链接成一个字符串 let str = [token, timestamp, nonce].sort().join(""); //使用sha1模块进行sha1加密 let sha1Str = sha1(str); //判断加密后的字符串与请求中signature是否相等 if (sha1Str === signature) { ctx.body = echostr; } else { ctx.body = "Token check failed."; } };

这一步OK之后,在「微信公众号后台就能成功开启服务器了」。接下来就是编写H5在微信里调用wx-jssdk相关功能所需要的授权过程。其实主要就是拿到wxconfig所需要的一些必要参数。
编写wx.config所需数据的接口
https://yourserver.com/api/wx...需授权网站的url
生成wxconfig数据的大致流程:获取access_token,通过access_token获取jsapi_ticket;然后拼接access_tokenjsapi_ticketnoncestrtimestamp要授权的页面的url生成签名signature,最终将appIdtimestampnonceStrsignature返回给前端,前端调用wx.config进行注册,成功后就可以在wx.ready中调用相关js接口了。
wxConfig.js文件代码
!!!这里部分代码借鉴来的,懒得改了大致流程都是这样!
const sha1 = require("sha1"); const request = require("request"); const { wxconfig } = require("./wxConfig"); // 为了应对缓存压力,不要每次刷新token,访问量高会带来很大问题 // 因为获取access_token的接口,一天最多调用2000次,每次有效期是两个小时 let CACHE = { ticket: "", ticketTimeout: 0, //ticket过期时间 ticketTime: 0, //获取ticket时间accessToken: "", accessTokenTimeout: 0, //token过期时间 accessTokenTime: 0, //获取token时间 }; class wxModel { /** * 刷新access_token */ static async refreshAccessToken() { return new Promise((resolve, reject) => { const tokenUrl = `${wxconfig.getAccessTokenUrl}?grant_type=client_credential&appid=${wxconfig.appId}&secret=${wxconfig.appSecret}`; request(tokenUrl, (error, response, body) => { if (typeof body === "string") { try { body = JSON.parse(body); } catch (e) { body = { errcode: "-1000", body, }; } }if (body && (!body.errcode || body.errcode == 0)) { CACHE.accessToken = body.access_token; CACHE.accessTokenTimeout = body.expires_in * 500; CACHE.accessTokenTime = new Date(); resolve(CACHE.accessToken); } else if (body) { reject(body.errmsg); } else { reject("未知异常"); } }); }); }/** * 刷新ticket * @param {*} access_token * @param {*} callback */ static async refreshJsapiTicket(access_token) { // Jsapi_ticket return new Promise((resolve, reject) => { let ticketUrl = `${wxconfig.getJsapiTicketUrl}?access_token=${access_token}&type=jsapi`; request(ticketUrl, function (err, response, content) { content = JSON.parse(content); if (content && (content.errcode == 0 || !content.errcode)) { CACHE.ticket = content.ticket; CACHE.ticketTimeout = content.expires_in * 500; CACHE.accessTokenTime = new Date(); resolve(CACHE.ticket); // ticket } else if (content) { reject(content.errmsg); } else { reject("未知异常"); } }); }); }/** * 获取wxconfig * @param {*} url * @returns */ static async geneWxConfig(url) { // 获取access_token let access_token = CACHE.accessToken; let ticket = CACHE.ticket; if ( !access_token || new Date() - CACHE.accessTokenTime > CACHE.accessTokenTimeout ) { access_token = await this.refreshAccessToken(); ticket = await this.refreshJsapiTicket(access_token); }let nonceStr = this.createNonceStr(); let timestamp = this.createTimestamp(); let signature = this.createSign({ jsapi_ticket: ticket, nonceStr, timestamp, url, }); return { appId: wxconfig.appId, access_token, ticket, timestamp, nonceStr, signature, }; }/** * 随机字符串 */ static createNonceStr() { return Math.random().toString(36).substr(2, 15); } /** * 时间戳 */ static createTimestamp() { return parseInt(new Date().getTime() / 1000).toString(); }/** * 生成签名 * ?? 只对url#前面部分加密 * ?? noncestr全部小写 * @param {*} config */ static createSign(config) { let ret = { jsapi_ticket: config.jsapi_ticket, nonceStr: config.nonceStr, timestamp: config.timestamp, url: config.url, }; let url = ret.url.split("#")[0]; let string = `jsapi_ticket=${ret.jsapi_ticket}&noncestr=${ret.nonceStr}×tamp=${ret.timestamp}&url=${url}`; let shaObjs = sha1(string); return shaObjs; } }module.exports = wxModel;

wxConfig.js文件内容
const wxconfig = { appId: "wx9xxxxxxx", appSecret: "xxxxxxxxxxxxxxxxxxxxx", token: "hxxxt", //公众号后台自行配置的tokengetAccessTokenUrl: "https://api.weixin.qq.com/cgi-bin/token", getJsapiTicketUrl: "https://api.weixin.qq.com/cgi-bin/ticket/getticket", }; module.exports = { wxconfig, };

前端代码 1.引入wx-jssdk
let jssdkUri = `${window.location.protocol}//res.wx.qq.com/open/js/jweixin-1.6.0.js`; loadJs() { return new Promise((resolve, reject) => { if (window.wx) { return resolve(window.wx); }let script = document.createElement("script"); script.type = "text/javascript"; script.src = https://www.it610.com/article/this.jssdkUri; window.document.getElementsByTagName("head")[0].appendChild(script); script.onload = () => { resolve(window.wx); }; script.onerror = reject; }); }

2.请求 /api/wxconfig 接口,拿到必要数据后调用 wx.config
let url = window.location.href; let data = https://www.it610.com/article/await this.getWxconfig(url); wx.config({ debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: data.appId, // 必填,公众号的唯一标识 timestamp: data.timestamp, // 必填,生成签名的时间戳 nonceStr: data.nonceStr, // 必填,生成签名的随机串 signature: data.signature, // 必填,签名 jsApiList: ["hideMenuItems", "updateAppMessageShareData", "updateTimelineShareData", ], // 必填,需要使用的JS接口列表 });

3.在wx.ready中编写「分享、转发」和其它业务需要的方法
share({ title, desc, link, imgUrl }) { this.shareData = https://www.it610.com/article/{ title, desc, link, imgUrl }; if (!this.isReady) { console.error("wx jssdk is not ready."); return; } wx.ready(() => { wx.updateAppMessageShareData({ title, desc, link, imgUrl, // 分享图标 success: (res) => {}, fail: (err) => this.onError(err), }); wx.updateTimelineShareData({ title, link, imgUrl, // 分享图标 success: (res) => {}, fail: (err) => this.onError(err), }); }); }hideMenu() { if (!this.isReady) { console.error("wx jssdk is not ready."); return; }wx.ready(() => { wx.hideMenuItems({ menuList: [ "menuItem:share:appMessage", "menuItem:share:timeline", "menuItem:share:qq", "menuItem:share:weiboApp", "menuItem:share:QZone", "menuItem:copyUrl", ], }); }); }

如何让H5在微信里活的「体面」! 最后想说一下,作为一个个人开发者无法调用wx.updateAppMessageShareDatawx.updateTimelineShareData等一些接口,我是怎么利用有限的功能让我的H5网页尽量「体面」的吧!
既然不能分享,那干脆干掉微信点击右上角功能按钮后弹出来的「转发给朋友」和「分享到朋友圈」,甚至干掉「复制链接」功能菜单。
这样尽量减少转发出去只剩下裸露的难看的url链接的情况发生。
(请看对比图)
记一次个人开发者如何让H5婚礼请帖在微信里「体面」的流转!
文章图片

记一次个人开发者如何让H5婚礼请帖在微信里「体面」的流转!
文章图片

至于如何传播这个H5网页?给H5生成一个二维码,贴在一张好看的图片上,转发给朋友吧哈哈哈!
顺便附上一个Amazing的免费在线 二维码生成网站

    推荐阅读