前言
一般来说,前端开发者只需要完成微信分享一的实现即可。但是总有些时候,前端开发需要做更多的事情 继微信分享(一),这次将用 egg 实现后端签名算法。
快速搭建环境
第一步: 配置开发环境 参考 egg 的官方文档,快速搭建一个 egg 环境
$ mkdir egg-example && cd egg-example
$ npm init egg --type=ts
$ npm i
$ npm run dev
配置 egg-chache (缓存), egg-view-nunjucks(模版引擎)。
第二部:配置 ngrok(内网穿透,让微信服务器访问获取设置安全域名) 搭建教程
验证服务器 token
// router.js
router.get("/api/wx", controller.api.wx.get);
// controller/api/wx.ts
const getSha1 = function(str) {
const sha1 = crypto.createHash('sha1'); // 定义加密方式:md5不可逆,此处的md5可以换成任意hash加密的方法名称;
sha1.update(str);
const res = sha1.digest('hex'); // 加密后的值d
return res;
};
//
export default class WxController extends Controller {
public async get() {
const { ctx } = this;
const { signature, timestamp, nonce, echostr } = ctx.query;
const token = 'wxjsdk';
const list = [ token, timestamp, nonce ];
list.sort();
const hashcode = getSha1(list.join(''));
if (signature === hashcode) {
ctx.body = echostr;
} else {
ctx.body = '';
}
}
}
具体分享页面请求获取 signature 算法
// controller/api/wx.ts
// 随机字符串
var createNonceStr = function () {
return Math.random().toString(36).substr(2, 15);
};
// 时间戳
var createTimestamp = function () {
return parseInt((new Date().getTime() / 1000).toString()).toString();
};
export default class WxController extends Controller {
// 内部函数
private async getSignature(){
// 从缓存中获取 token和jsticket 判断是否过期
const token = await this.app.cache.get('token');
const jsapiTicket = await this.app.cache.get('jsapiTicket');
if (token && jsapiTicket) {
return jsapiTicket;
} else {
// 分步获取token和jsticket
// apppid和appsecret从微信公众号后台设置里获取
const appid = 'your appid';
const appsecret = 'your appsecret';
const result = await this.app.curl(
`https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appid}&secret=${appsecret}`,
{
dataType: 'json',
},
);
if (result.data && result.data.access_token) {
const access_token = result.data.access_token;
await this.app.cache.set('token', access_token, 7200);
const jsapi = await this.app.curl(
`https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=${
access_token
}&type=jsapi`,
{
dataType: 'json',
},
);
if (jsapi.data && jsapi.data.errcode === 0) {
const ticket = jsapi.data.ticket
await this.app.cache.set('jsapiTicket', ticket, 7200);
return ticket
}
}
}
return false
}
// 接口请求控制
public async sg() {
const { ctx } = this;
const jsticket = await this.getSignature();
console.log(jsticket)
if (!jsticket) {
ctx.body = {
errmsg: '出错了',
};
}
const { url } = ctx.query;
const nonceStr = createNonceStr();
const timestamp = createTimestamp();
const str = `jsapi_ticket=${jsticket}&noncestr=${nonceStr}×tamp=${timestamp}&url=${url}`
const signature = getSha1(str);
ctx.body = {
appId: 'your appid',
timestamp,
nonceStr,
signature,
}
}
}
设置请求路由
// router.js
router.get("/api/wxsg", controller.api.wx.sg);
此上完成签名算法的接口请求 配合微信分享(一)中的前端代码,能够实现分享自定义
注意事项
一、设置接口配置信息的时候,微信服务器会主动访问自己的服务器(所以需要具备自己的服务器或者用 ngrok 配置内网穿透)完成验证 二、token 和 jsticket 都是 7200 秒的有效期且不能频繁访问获取,所以需要缓存存起来,需要用户配置相关策略 三、调试接口和网页可以使用微信开发者工具,具备更详细的 log 信息