在vue項目中引入jssdk所遇到的各種問題


由於在最近的項目中,需要用到掃一掃二維碼簽到的功能,在純H5的頁面中要實現這個是不太可能的,所以考慮用jssdk或者混合開發,由於沒有微信公眾號和混合開發的經驗,混合開發不太現實,公司沒有考慮這個,而jssdk有其他公眾號平台的公司配合,所以就看看技術上能不能實現。

技術上要考慮的就是,能不能在項目中引入jssdk,然后當用戶在微信端打開的時候,就能夠通過jssdk來調用微信的掃一掃功能。

由於公司和公眾號平台公司還沒談好,首先用微信公眾號測試平台來做一下測試,開始漫長的填坑之路。

首先,jssdk是需要后台配合的,后台我用nodejs寫,用的是express框架,先引用微信提供的一個三方庫,wechat來通過微信的接口配置信息驗證,端口號只支持80端口的

var express = require('express')
var app = express()
var wechat = require('wechat')

app.get('/weixin', wechat('wechat',function (req, res, next) { 
    console.log('true');
}));

var server = app.listen(80,function () {
  var host = server.address().address
  var port = server.address().port

  console.log('服務已啟動在http://%s:%s',host,port)
})

  

其中url是我自己把內網端口地址映射到公網上的地址。token是自己在后台約定好的。

如果服務啟動起來,端口映射也成功了,點擊提交就會提示配置成功,否則會提示有錯誤。

接下來需要開始獲取access_token和 jsapi_ticket 來進行簽名

access_token需要APPID和appsecret來獲取,通過"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+APPID+"&secret="+appsecret地址來獲得,其中APPID和appsecret是你自己公眾號里面提供的

獲取到access_token以后,通過'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='+JSON.parse(result).access_token+'&type=jsapi'地址來獲取jsapi_ticket,JSON.parseresult是"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+APPID+"&secret="+appsecret這個地址中獲取的的返回信息。

通常情況下,access_token需要緩存,因為access_token一天只能請求2000次。但本次只是測試用,就沒有將它緩存起來了

具體代碼:

var sign = require('./sign')

app.post('/test/getSignature', function (req, res) {
  var token = 'wechat',
  appsecret = 'xxxxxxxxxxxxxxx', //你申請的
  APPID ='xxxxxxxxxxxxxx',//你申請的id
  url = 'http://www.baidu.com',  //JS接口安全域名 參與簽名用的
  Res = res;
//發送https get請求 獲取 access_token;
if(!access_token){
  https.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+APPID+"&secret="+appsecret, function(res) {  
        var datas = [];  
        var size = 0;
        res.on('data', function (data) {  
            datas.push(data);  
            size += data.length;
        });  
        res.on("end", function () {  
            var buff = Buffer.concat(datas, size);  
            var result = buff.toString();
            access_token = JSON.parse(result).access_token
            console.log(JSON.parse(result).access_token);
      // 獲取 jsapi_ticket //異步嵌套是不合理的 不推薦這樣 使用promise
      https.get('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='+JSON.parse(result).access_token+'&type=jsapi',function(res){
          var datas = [];  
            var size = 0;
            res.on('data', function (data) {  
                datas.push(data);  
                size += data.length;
            });  
          res.on('end',function(){
          var buff = Buffer.concat(datas, size);  
          var result = buff.toString()
          console.log(JSON.parse(result).ticket);
          var config = sign(JSON.parse(result).ticket,url);//當前要調用js-sdk的url
            config.appId = APPID;
            console.log(config);
            Res.json(config);
         });

            }).on('error',function(e){
              console.log("Got error: " + e.message); 
            })
            
            
        });  
    
  }).on('error', function(e) { 
      console.log("Got error: " + e.message); 
  });
} else {
  https.get('https://api.weixin.qq.com/cgi-bin/ticket/getticket? 
  access_token='+ access_token +'&type=jsapi',function(res){
          var datas = [];  
            var size = 0;
            res.on('data', function (data) {  
                datas.push(data);  
                size += data.length;
            });  
          res.on('end',function(){
          var buff = Buffer.concat(datas, size);  
          var result = buff.toString()
          console.log(JSON.parse(result).ticket);
          var config = sign(JSON.parse(result).ticket,url);//當前要調用js-sdk的url
            config.appId = APPID;
            console.log(config);
            Res.json(config);
         });

            })
  }

});

其中sign是一個簽名的函數文件,里面自動生成nonceStrtimestamp字段,然后通過簽名生成signature,

有一個重要的問題,url地址,如果url沒有后面的path,需要補上'/',也就是說,如果你js的安全域名是http://www.abc.com,你需要寫的是http://www.abc.com/,我在這兒一直被坑了很久

時間戳需要精確到秒,而不是毫秒,

url需要包含?后面的但不包含#后面的內容

具體代碼如下:

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;
};


var sign = function (jsapi_ticket, url) {
  var ret = {
    jsapi_ticket: jsapi_ticket,
    nonceStr: createNonceStr(),
    timestamp: createTimestamp(),
    url: url
  };
  var string = raw(ret);
      jsSHA = require('jssha');
      shaObj = new jsSHA(string, 'TEXT');
  ret.signature = shaObj.getHash('SHA-1', 'HEX');

  return ret;
};

module.exports = sign;

 

 到此,后台獲取前端需要的wx.config的所有字段完成。

然后前端開始請求后台的接口,需要注意的是,前端的地址需要添加到安全域名中,為此我映射了第二個端口到公網

 

然后需要在vue項目中引入jssdk,微信為了方便用戶使用,將官方的jssdk發布到了npm上,有一個叫weixin-js-sdk的,但我們需要使用的不是這個,網上很多在vue中引用的是這個,但是這個是為commonjs發布的版本,只能通過require引入,很多人發現在vue中引入import wx from 'weixin-js-sdk',console.log(wx)會出現undefined,實際為了方便es6使用,官方發布了一個weixin-jsapi,這個才是我們能在vue中引用的jssdk。我也在這里被坑了很久。

然后拿到后台返回的配置參數,通過wx.config來驗證配置后,在wx.ready里面就可以調用jssdk提供的api了,具體代碼:

import wx from 'weixin-jsapi'
export default {
  data () {
    return {
      videoSrc: ''
    }
  },
  mounted () {
    http.POST('/xxxx/xxxxxxxxx').then((data) => {
      console.log(wx)
      wx.config({
        debug: true,
        appId: data.appId, // 必填,公眾號的唯一標識
        timestamp: data.timestamp, // 必填,生成簽名的時間戳,精確到秒
        nonceStr: data.nonceStr, // 必填,生成簽名的隨機串
        signature: data.signature, // 必填,簽名
        jsApiList: ['scanQRCode']
      })
    }).catch(() => {
      alert('failed')
    })
  },
  methods: {
    handleQR () {
      wx.ready(() => {
        console.log('ininin')
        wx.scanQRCode({
          needResult: 1, // 默認為0,掃描結果由微信處理,1則直接返回掃描結果,
          scanType: ["qrCode","barCode"], // 可以指定掃二維碼還是一維碼,默認二者都有
          success: function (res) {
            var result = res.resultStr; // 當needResult 為 1 時,掃碼返回的結果
          }
        });
      })
    }
  }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM