欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

基于nodejs的微信JS-SDK简单应用实现

程序员文章站 2022-03-20 14:49:56
2015 是 hybrid app 崛起之年 ,web app 和 native app 各有其强大之处,也有着致命的缺点,人们一边追求native流畅的用户体验,一边同时...

2015 是 hybrid app 崛起之年 ,web app 和 native app 各有其强大之处,也有着致命的缺点,人们一边追求native流畅的用户体验,一边同时期望产品能够快速的迭代更新,hybrid 成为必然的趋势。

鹅厂一马当先,发布了业内震惊一时的 js-sdk , 这对于基于微信的h5开发者来说简直是如降甘露,从此开发者们告别了用箭头来提示右上角可以分享,并且随时可以使用微信的原生能力,微信变成了一个超级浏览器。

一、准备工作

1.在微信公众平台申请测试账号,并设置好好 js 接口安全域名 (注:域名必须可以外网访问)

2.查看

二、开始编码

使用微信 sdk 必须自己实现微信的签名算法。

大概需要4个步骤:

1.获取access_token;

2.根据access_token 获取jsapi_ticket

3. 根据 appid(公众号唯一id)、noncestr(随机字符串)、timestamp(时间戳)、url(当前页面完整url,不包括#aaa=bbb) 通过sha1算法签名

4.将信息返回给前端 , 设置wx.config。

由于获取access_token 和jsapi_ticket 的接口都有访问限制,所以明确指出需要第三方做缓存处理。此处我们缓存jsapi_ticket 就可以了。

/config/wechat.cfg.js

module.exports = {
  grant_type: 'client_credential',
  appid: 'xxxxxxxxxxxxxxx',
  secret: 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
  noncestr:'wm3wzytpz0wzccnw',
  accesstokenurl:'https://api.weixin.qq.com/cgi-bin/token',
  ticketurl:'https://api.weixin.qq.com/cgi-bin/ticket/getticket',
  cache_duration:1000*60*60*24 //缓存时长为24小时
}

最主要部分是签名:

signature.js

var request = require('request'),
  cache = require('memory-cache'),
  sha1 = require('sha1'),
  config = require('../config/wechat.cfg');

exports.sign = function (url,callback) {
  var noncestr = config.noncestr,
    timestamp = math.floor(date.now()/1000), //精确到秒
    jsapi_ticket;
  if(cache.get('ticket')){
    jsapi_ticket = cache.get('ticket');
    console.log('1' + 'jsapi_ticket=' + jsapi_ticket + '&noncestr=' + noncestr + '&timestamp=' + timestamp + '&url=' + url);
    callback({
      noncestr:noncestr,
      timestamp:timestamp,
      url:url,
      jsapi_ticket:jsapi_ticket,
      signature:sha1('jsapi_ticket=' + jsapi_ticket + '&noncestr=' + noncestr + '&timestamp=' + timestamp + '&url=' + url)
    });
  }else{
    request(config.accesstokenurl + '?grant_type=' + config.grant_type + '&appid=' + config.appid + '&secret=' + config.secret ,function(error, response, body){
      if (!error && response.statuscode == 200) {
        var tokenmap = json.parse(body);
        request(config.ticketurl + '?access_token=' + tokenmap.access_token + '&type=jsapi', function(error, resp, json){
          if (!error && response.statuscode == 200) {
            var ticketmap = json.parse(json);
            cache.put('ticket',ticketmap.ticket,config.cache_duration); //加入缓存
            console.log('jsapi_ticket=' + ticketmap.ticket + '&noncestr=' + noncestr + '&timestamp=' + timestamp + '&url=' + url);
            callback({
              noncestr:noncestr,
              timestamp:timestamp,
              url:url,
              jsapi_ticket:ticketmap.ticket,
              signature:sha1('jsapi_ticket=' + ticketmap.ticket + '&noncestr=' + noncestr + '&timestamp=' + timestamp + '&url=' + url)
            });
          }
        })
      }
    })
  }
}

由于只是简单的demo , 也就没有采用promise,而是采用的普通的回调。

客户端部分

document.getelementbyid('refresh').onclick = function(){location.reload();}

/**
 * 以下内容多摘自官方demo
 *
**/
wx.config({
  debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  appid: appid, // 必填,公众号的唯一标识
  timestamp: timestamp, // 必填,生成签名的时间戳
  noncestr: noncestr, // 必填,生成签名的随机串
  signature: signature,// 必填,签名,见附录1
  jsapilist: ['checkjsapi',
    'onmenusharetimeline',
    'onmenushareappmessage',
    'onmenushareqq',
    'onmenushareweibo',
    'hidemenuitems',
    'showmenuitems',
    'hideallnonbasemenuitem',
    'showallnonbasemenuitem',
    'translatevoice',
    'startrecord',
    'stoprecord',
    'onrecordend',
    'playvoice',
    'pausevoice',
    'stopvoice',
    'uploadvoice',
    'downloadvoice',
    'chooseimage',
    'previewimage',
    'uploadimage',
    'downloadimage',
    'getnetworktype',
    'openlocation',
    'getlocation',
    'hideoptionmenu',
    'showoptionmenu',
    'closewindow',
    'scanqrcode',
    'choosewxpay',
    'openproductspecificview',
    'addcard',
    'choosecard',
    'opencard'] // 必填,需要使用的js接口列表,
});

wx.ready(function(){
 // 1 判断当前版本是否支持指定 js 接口,支持批量判断
 document.queryselector('#checkjsapi').onclick = function () {
  wx.checkjsapi({
   jsapilist: [
    'getnetworktype',
    'previewimage'
   ],
   success: function (res) {
    alert(json.stringify(res));
   }
  });
 };

  // 2. 分享接口
 // 2.1 监听“分享给朋友”,按钮点击、自定义分享内容及分享结果接口
 document.queryselector('#onmenushareappmessage').onclick = function () {
  wx.onmenushareappmessage({
   title: '互联网之子',
   desc: '在长大的过程中,我才慢慢发现,我身边的所有事,别人跟我说的所有事,那些所谓本来如此,注定如此的事,它们其实没有非得如此,事情是可以改变的。更重要的是,有些事既然错了,那就该做出改变。',
   link: 'http://movie.douban.com/subject/25785114/',
   imgurl: 'http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg',
   trigger: function (res) {
    // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
    alert('用户点击发送给朋友');
   },
   success: function (res) {
    alert('已分享');
   },
   cancel: function (res) {
    alert('已取消');
   },
   fail: function (res) {
    alert(json.stringify(res));
   }
  });
  alert('已注册获取“发送给朋友”状态事件');
 };

  // 5 图片接口
 // 5.1 拍照、本地选图
 var images = {
  localid: [],
  serverid: []
 };
 document.queryselector('#chooseimage').onclick = function () {
  wx.chooseimage({
   success: function (res) {
    images.localid = res.localids;
    alert('已选择 ' + res.localids.length + ' 张图片');
   }
  });
 };
  // 5.2 图片预览
 document.queryselector('#previewimage').onclick = function () {
  wx.previewimage({
   current: 'http://img5.douban.com/view/photo/photo/public/p1353993776.jpg',
   urls: [
    'http://img3.douban.com/view/photo/photo/public/p2152117150.jpg',
    'http://img5.douban.com/view/photo/photo/public/p1353993776.jpg',
    'http://img3.douban.com/view/photo/photo/public/p2152134700.jpg'
   ]
  });
 };

  // 7.2 获取当前地理位置
 document.queryselector('#getlocation').onclick = function () {
  wx.getlocation({
   success: function (res) {
    alert(json.stringify(res));
   },
   cancel: function (res) {
    alert('用户拒绝授权获取地理位置');
   }
  });
 };

  // 9 微信原生接口
 // 9.1.1 扫描二维码并返回结果
 document.queryselector('#scanqrcode0').onclick = function () {
  wx.scanqrcode();
 };

});

wx.error(function(res){
  json.stringify(res)
});

至此,基本功能已经完成。附上效果图

基于nodejs的微信JS-SDK简单应用实现

基于nodejs的微信JS-SDK简单应用实现

基于nodejs的微信JS-SDK简单应用实现

踩的坑:

1.签名算法不一致: 通过 验证算法正确性

2.url 必须完全一致,并且外网可访问。 将代码部署到 bae ,或者其他应用引擎服务器上。

3.timestamp需要精确到秒。

源码:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。