天天看點

基于koa實作的微信JS-SDK調用Demo

前置準備

  • 一個測試公衆号
  • 一台伺服器(帶域名)

登入測試公衆号背景添加JS安全域名

基于koa實作的微信JS-SDK調用Demo

koa項目開發

微信JS-SDK權限驗證的簽名必須在伺服器端實作,簽名用的url必須是調用JS接口頁面的完整URL,是以這裡決定用koa來同時完成頁面渲染及生成簽名所需驗證配置。

項目依賴庫如下:

  • koa-router
  • request-promise
  • koa-views
  • koa-static
  • koa2-cors
  • memory-cache
  • sha1

下面介紹一下核心的簽名方法:

主要就是請求全局token後擷取jsapi_ticket來擷取簽名。

const config = require('./config');
async function sign(url) {
  let sig = {},
    noncestr = config.noncestr,
    timestamp = Math.floor(Date.now() / 1000), //精确到秒
    jsapi_ticket;
  if (cache.get('ticket')) {
    jsapi_ticket = cache.get('ticket');
    sig = {
      appId: config.appid,
      noncestr: noncestr,
      timestamp: timestamp,
      url: url,
      jsapi_ticket: jsapi_ticket,
      signature: sha1(
        'jsapi_ticket=' +
          jsapi_ticket +
          '&noncestr=' +
          noncestr +
          '&timestamp=' +
          timestamp +
          '&url=' +
          url
      ),
    };
  } else {
    // 擷取 token
    let tokenRes = await rp({
      uri:
        config.accessTokenUrl +
        '?grant_type=' +
        config.grant_type +
        '&appid=' +
        config.appid +
        '&secret=' +
        config.secret,
    });
    tokenRes = JSON.parse(tokenRes);

    // 擷取 ticket
    let ticketRes = await rp({
      uri:
        config.ticketUrl +
        '?access_token=' +
        tokenRes.access_token +
        '&type=jsapi',
    });
    var ticketMap = JSON.parse(ticketRes);
    // 加入緩存
    cache.put('ticket', ticketMap.ticket, config.cache_duration);
    sig = {
      appId: config.appid,
      noncestr: noncestr,
      timestamp: timestamp,
      url: url,
      jsapi_ticket: ticketMap.ticket,
      signature: sha1(
        'jsapi_ticket=' +
          ticketMap.ticket +
          '&noncestr=' +
          noncestr +
          '&timestamp=' +
          timestamp +
          '&url=' +
          url
      ),
    };
  }
  return sig;
}           

之後我們隻要在koa的router中定義一個路由去生成簽名就行了

router.get('/sig', async (ctx, next) => {
  try {
    //擷取目前url
    let url =
      ctx.request.protocol + '://' + ctx.request.host + ctx.request.originalUrl;
    if (ctx.query.url) {
      url = ctx.query.url;
    }
    ctx.data = await sign(url);
  } catch (e) {
    console.log(e);
  }
  await next();
});           

demo 頁面我們可以使用 koa-views 及 ejs 來渲染:

  • 頁面放到 views 目錄
  • 頁面需要引用的css及js可以放到 static 目錄下面

參考代碼如下:

const views = require('koa-views');
const static = require('koa-static');
app.use(static(path.join(__dirname, './static')));
app.use(
  views(path.join(__dirname, './views'), {
    extension: 'ejs',
  })
);           

views 目錄下建立頁面 index.ejs,寫入 sdk 調用前端 demo 頁面,主要内容如下:

  • 引入 jweixin-1.6.0.js 檔案
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>           
  • 通過config接口注入權限驗證配置
wx.config({
    debug: true, // 開啟調試模式,調用的所有api的傳回值會在用戶端alert出來,若要檢視傳入的參數,可以在pc端打開,參數資訊會通過log打出,僅在pc端時才會列印。
    appId: '', // 必填,公衆号的唯一辨別
    timestamp: , // 必填,生成簽名的時間戳
    nonceStr: '', // 必填,生成簽名的随機串
    signature: '',// 必填,簽名,見附錄1
    jsApiList: [] // 必填,需要使用的JS接口列
});           
  • ready接口處理成功驗證
wx.ready(function(){
    //config資訊驗證後會執行ready方法,所有接口調用都必須在config接口獲得結果之後,config是一個用戶端的異步操作,是以如果需要在頁面加載時就調用相關接口,則須把相關接口放在ready函數中調用來確定正确執行。對于使用者觸發時才調用的接口,則可以直接調用,不需要放在ready函數中。
});           
  • error接口處理失敗驗證
wx.error(function(res){
    //config資訊驗證失敗會執行error函數,如簽名過期導緻驗證失敗,具體錯誤資訊可以打開config的debug模式檢視,也可以在傳回的res參數中檢視,對于SPA可以在這裡更新簽名。
});           

完整頁面代碼參考位址(過長不便展示):

https://github.com/xuedingmiaojun/koa-demo/blob/master/wxgh-jssdk/views/index.ejs

至此我們就完成了一個簡易的koa版調用Demo了,下面我們來測試一下

Demo 本地調試

一般我們有内網穿透、代理劫持等幾種方法去進行本地調試,這裡我們使用一個比較常用的方法内網穿透(用你自己熟練的方法就好)來測試。

  1. 修改項目根目錄下的 config.js,換成自己公衆号的appid及secrect
  2. 在項目根目錄執行

    node app.js

    啟動服務後浏覽器打開如下位址 http://localhost:4000/ 即可看到 Demo 頁面
  3. 在前置準備中我們設定了一個JS接口安全域名,可以基于這個域名做穿透服務來通路我們本地koa項目,添加公網端口映射本地koa項目的端口(這裡的例子是4000),然後浏覽器通路JS接口安全域名即可看到 Demo 頁面
  4. 使用微信打開JS接口安全域名即可測試使用

項目代碼擷取:極客之路公衆号背景回複 koa-wx-js-sdk 即可擷取

視訊示範

以下是測試視訊位址,僅供參考

https://www.bilibili.com/video/BV1N64y1x78m

注意事項

  • 簽名用的noncestr和timestamp必須與wx.config中的nonceStr和timestamp相同。
  • 簽名用的url必須是調用JS接口頁面的完整URL。
  • 出于安全考慮,開發者必須在伺服器端實作簽名的邏輯。

參考資料

繼續閱讀