接入微信JSSDK流程图
1、准备工作
1-1、前端:Vue
1、npm i weixin-js-sdk -S //安装微信js-sdk
2、npm i axios -S //安装接口请求模块
1-2、后端:Koa
这里我们先规定Koa端口启动在8050上
后面内网映射需要使用该端口
1、npm i axios -S //安装接口请求模块用自带的http也行
2、npm i sha1 -D //安装加密模块
3、npm i node-cache -D //安装缓存模块
4、npm i koa-bodyparser koa-router koa
1-3、内网映射工具Ngrok
Ngrok地址PS:绝对不是打广告
,使用方法开官方文档
为什么要用内网映射?
因为我们目前是在本地开发,我们使用测试好进行开发
配置Ngrok,进入他的控制台购买一台免费的服务器
1-4、申请微信测试号
测试号申请地址
有的同学可能会问怎么配置?,别急我们写编写我们的Koa代码,我们这里会拿到测试号提供的
appId、appsecret
2、Koa服务端的编写
index.js
const koa = require('koa');
const app = new koa();
const routesr = require('./routes');
const bodyParser = require('koa-bodyparser');
app.use(bodyParser())
app.use(routesr.routes())
app.listen(8050,()=>{
console.log('server in port 8050')
})
创建util文件夹创建config.js
module.exports = {
token : "12qq",//我们刚刚微信测试号页面上准备填的token
appid : "*****",//微信测试号上的APPID
appsecret : "*****",//微信测试号上的appsecret
getAccessToken : "https://api.weixin.qq.com/cgi-bin/token",//这个是微信官方请求accesstoken地址
getjstick : "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token="//这个是官方获取tick地址
}
创建routes文件夹并且创建index.js路由文件
我们先写微信测试号的接口配置信息
const router = require('koa-router')();
const sha1 = require('sha1')
//接口信息配置访问的接口
//即微信测试页面的 接口配置信息
router.get('/appconfig',async ctx=>{
const token = config.token;
const signature = ctx.request.query.signature
const nonce = ctx.request.query.nonce
const timestamp = ctx.request.query.timestamp
const echostr = ctx.request.query.echostr
let str = [token, timestamp, nonce].sort().join('')
const sha = sha1(str)
ctx.body = sha === signature ? echostr + '' : 'failed'
})
2-2、配置测试号接口信息
1、启动koa服务
2、使用Ngrok启动内网映射,启动方法见他的文档
当上面两步做完之后,我们打开测试号页面
2-3、编写缓存文件
在util文件夹中创建cache.js文件
为什么要用缓存?
const NodeCache = require("node-cache");
const myCache = new NodeCache({
stdTTL: 7200, // 缓存过期时间
checkperiod: 120 // 定期检查时间
});
// 设置缓存
const setCache = async (key, value)=> {
// 设置缓存
let values = await myCache.set(key, value);
return values;
};
// 获取缓存
const getCache = async key => {
// 读取缓存
let result = await myCache.get(key);
return result;
};
module.exports = {
setCache,
getCache
}
2-4获取微信的access_token
在根路径下创建controller文件夹并且穿件getAccToken.js
// 获取 access_token
const config = require('../util/config'); // 配置数据
const axios = require('axios'); // 请求api
// (设置 | 获取)缓存方法
const cache = require('../config/cache');
module.exports = getAccessToken = async () => {
const fetchUrl = `${config.getAccessToken}?grant_type=client_credential&appid=${config.appid}&secret=${config.appsecret}`;
// console.log(fetchUrl, config);
var token = await cache.getCache('access_token');
if(token){
return {
"access_token" : token,
"from" : "cache"
};
}else{
let res = await axios.get(fetchUrl);
let data = res.data;
if(data.access_token){
cache.setCache('access_token', data.access_token)
}
return {
"access_token" : data.access_token,
"from" : "axios"
};
}
};
2-5获取微信的jstick
在根路径下创建controller文件夹并且穿件getJsTick.js
const axios = require('axios'); // 请求api
const config = require('../util/config'); // 配置数据
const cache = require('../util/cache');
module.exports = get_jsapi_ticket = async access_token => {
const fetchUrl = config.getjstick + access_token;
const cacheName = "jsapi_ticket";
var ticket = await cache.getCache(cacheName);
if(ticket){
return {
ticket: ticket,
from: 'cache'
}
}else{
var result = await axios.get(fetchUrl)
let data = result.data;
if(data.ticket){
cache.setCache(cacheName, data.ticket)
}
return {
"ticket" : data.ticket,
"from" : "axios"
};
}
}
2-6获取签名
在controller文件夹并且穿件setSign.js
const sha1 = require("sha1")
const config = require("../util/config")
var createNonceStr = function () {
return Math.random().toString(36).substr(2, 15);
};
var createTimestamp = function () {
return parseInt(new Date().getTime() / 1000) + '';
};
var raw = function (args) {
var keys = Object.keys(args);
keys = keys.sort()
var newArgs = {};
keys.forEach(function (key) {
newArgs[key.toLowerCase()] = args[key];
});
var string = '';
for (var k in newArgs) {
string += '&' + k + '=' + newArgs[k];
}
string = string.substr(1);
return string;
};
/**
* @synopsis 签名算法
*
* @param jsapi_ticket 用于签名的 jsapi_ticket
* @param url 用于签名的 url ,注意必须动态获取,不能 hardcode
*
* @returns
*/
var sign = function (jsapi_ticket, url) {
var ret = {
jsapi_ticket: jsapi_ticket,
nonceStr: createNonceStr(),
timestamp: createTimestamp(),
url: url
};
var string = raw(ret);
var shaObj = sha1(string);
ret.signature = shaObj;
ret.appId = config.appid;
return ret;
};
module.exports = sign;
2-7编写访问路由
当以上文件都完成之后我们就差最后一步,开启路由访问获取签名
我们在routes文件夹中的index继续编写
//加上
const accessToken = require('../controller/getAccToken.js');
const jsTick = require('../controller/getJsTick.js');
const setSign= require('../controller/setSign.js');
router.get('/get/sign',async ctx=>{
const params = {};
var token = await accessToken();
var tick = await jsTick(token.access_token);
params.url = ctx.query.url;//注意前端需要传url参数
params.ticket = tick;
var qm = await setSign(params.ticket.ticket,params.url);
ctx.body = qm;
})
以上工作都做完我们可以尝试访问
结束服务端内容
2-8测试签名算法是否正确
我们可以进行测试签名算法是否正确
进入微信公众平台接口调试工具
输入我们的参数即可
3、编写前端Vue代码
创建判断平台的工具文件
// ssr support
export const inBrowser = typeof window !== 'undefined'
export const ua = inBrowser && navigator.userAgent.toLowerCase()
export const isWeChatDevTools = ua && ua.match(/MicroMessenger/i) == "micromessenger";
export const isAndroid = ua && ua.indexOf('android') > 0
mounted(){
// 只要访问的是微信浏览器 我们就请求接口
if(isWeChatDevTools ) this._Share()
},
async _Share(){
let self = this;
let res = await axios.get("/api/get/sign?url="+location.href.split('#')[0])
if(res.data.Code != 0) return
let data = res.data.data;
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature, // 必填,签名
jsApiList: ["updateAppMessageShareData", "updateTimelineShareData"] // 必填,需要使用的JS接口列表
});
wx.ready(function() {
self.wxShareTimeline();
});
},
wxShareTimeline(){
//分享至朋友/QQ好友
wx.updateAppMessageShareData({
title: ShareConfig.title, // 分享标题
desc: ShareConfig.desc, // 分享描述
link: location.href.split('#')[0], // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: ShareConfig.imgUrl
})
//分享至QQ空间/朋友圈
wx.updateTimelineShareData({
title: ShareConfig.title, // 分享标题
desc: ShareConfig.desc, // 分享描述
imgUrl: ShareConfig.imgUrl
})
}
4、测试代码的可用性
扫描测试号页面的二维码进入测试公众号里面
然后我们进行访问Vue的访问域名 记住该地址一定是你在测试号配置的js安全域名的地址然后我们分享