hyxlog

由于在最近的项目中,需要用到扫一扫二维码签到的功能,在纯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 时,扫码返回的结果
          }
        });
      })
    }
  }
}

 

分类:

技术点:

相关文章:

  • 2021-09-05
  • 2021-12-16
  • 2020-12-23
  • 2021-11-03
  • 2021-12-14
  • 2021-11-05
  • 2022-01-01
猜你喜欢
  • 2021-09-26
  • 2021-07-09
  • 2021-09-24
  • 2022-01-01
  • 2022-01-06
  • 2021-09-15
  • 2021-06-08
相关资源
相似解决方案