Vue+Koa使用微信分享等功能

接入微信JSSDK流程图

image.png

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,进入他的控制台购买一台免费的服务器


image.png

image.png
image.png

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启动内网映射,启动方法见他的文档

当上面两步做完之后,我们打开测试号页面

image.png

2-3、编写缓存文件

在util文件夹中创建cache.js文件

为什么要用缓存?


image.png
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;
})

以上工作都做完我们可以尝试访问


image.png

结束服务端内容

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、测试代码的可用性

扫描测试号页面的二维码进入测试公众号里面

image.png

然后我们进行访问Vue的访问域名 记住该地址一定是你在测试号配置的js安全域名的地址然后我们分享

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343