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


Posted in NodeJs onMay 21, 2019

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 + '×tamp=' + timestamp + '&url=' + url);
    callback({
      noncestr:noncestr,
      timestamp:timestamp,
      url:url,
      jsapi_ticket:jsapi_ticket,
      signature:sha1('jsapi_ticket=' + jsapi_ticket + '&noncestr=' + noncestr + '×tamp=' + 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 + '×tamp=' + timestamp + '&url=' + url);
            callback({
              noncestr:noncestr,
              timestamp:timestamp,
              url:url,
              jsapi_ticket:ticketMap.ticket,
              signature:sha1('jsapi_ticket=' + ticketMap.ticket + '&noncestr=' + noncestr + '×tamp=' + 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.签名算法不一致: 通过 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 验证算法正确性

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

3.timestamp需要精确到秒。

源码:https://github.com/liaobin312716/wechat-sdk-demo/

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

NodeJs 相关文章推荐
使用forever管理nodejs应用教程
Jun 03 NodeJs
nodejs 提示‘xxx’ 不是内部或外部命令解决方法
Nov 20 NodeJs
浅谈NodeJS中require路径问题
May 07 NodeJs
Nodejs初级阶段之express
Nov 23 NodeJs
深入浅析NodeJs并发异步的回调处理
Dec 21 NodeJs
nodejs 中模拟实现 emmiter 自定义事件
Feb 22 NodeJs
详解Nodejs基于mongoose模块的增删改查的操作
Dec 21 NodeJs
nodejs基础知识
Feb 03 NodeJs
nodejs中使用HTTP分块响应和定时器示例代码
Mar 19 NodeJs
浅析 NodeJs 的几种文件路径
Jun 07 NodeJs
nodejs操作mongodb的填删改查模块的制作及引入实例
Jan 02 NodeJs
Linux Centos7.2下安装nodejs&npm配置全局路径的教程
May 15 NodeJs
nodejs中实现用户注册路由功能
May 20 #NodeJs
nodejs实现日志读取、日志查找及日志刷新的方法分析
May 20 #NodeJs
NodeJS读取分析Nginx错误日志的方法
May 14 #NodeJs
nodejs搭建本地服务器并访问文件操作示例
May 11 #NodeJs
M2实现Nodejs项目自动部署的方法步骤
May 05 #NodeJs
nodejs通过钉钉群机器人推送消息的实现代码
May 05 #NodeJs
nodejs中request库使用HTTPS代理的方法
Apr 30 #NodeJs
You might like
php写的AES加密解密类分享
2014/06/20 PHP
深入讲解PHP的对象注入(Object Injection)
2017/03/01 PHP
PHP读取word文档的方法分析【基于COM组件】
2017/08/01 PHP
利用JS重写Cognos右键菜单的实现代码
2010/04/11 Javascript
分享XmlHttpRequest调用Webservice的一点心得
2012/07/20 Javascript
谈谈关于JavaScript 中的 MVC 模式
2013/04/11 Javascript
JavaScript实现大数的运算
2014/11/24 Javascript
js实现上传图片预览的方法
2015/02/09 Javascript
js计算德州扑克牌面值的方法
2015/03/04 Javascript
基于AngularJS+HTML+Groovy实现登录功能
2016/02/17 Javascript
js判断数组key是否存在(不用循环)的简单实例
2016/08/03 Javascript
最棒的Angular2表格控件
2016/08/10 Javascript
Jquery组件easyUi实现表单验证示例
2016/08/23 Javascript
AngularJS中一般函数参数传递用法分析
2016/11/22 Javascript
原生js实现电商侧边导航效果
2017/01/19 Javascript
微信小程序 支付功能开发错误总结
2017/02/21 Javascript
ES6学习教程之Map的常用方法总结
2017/08/03 Javascript
详解ajax的data参数错误导致页面崩溃
2018/04/30 Javascript
新手入门带你学习JavaScript引擎运行原理
2019/06/24 Javascript
[59:48]LGD vs IG 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python的Template使用指南
2014/09/11 Python
Python功能键的读取方法
2015/05/28 Python
matplotlib绘制动画代码示例
2018/01/02 Python
Django中url的反向查询的方法
2018/03/14 Python
python读取大文件越来越慢的原因与解决
2019/08/08 Python
python实现对服务器脚本敏感信息的加密解密功能
2019/08/13 Python
python 无损批量压缩图片(支持保留图片信息)的示例
2020/09/22 Python
用python获取txt文件中关键字的数量
2020/12/24 Python
Jeep牧马人、切诺基和自由人零配件:4 Wheel Drive Hardware
2017/07/02 全球购物
迪斯尼假期(欧洲、中东及非洲):Disney Holidays EMEA
2021/02/15 全球购物
产品质量承诺书
2014/03/27 职场文书
检举信的格式及范文
2014/04/04 职场文书
2015年社区教育工作总结
2015/05/13 职场文书
2019个人半年工作总结
2019/06/21 职场文书
Python3 使用pip安装git并获取Yahoo金融数据的操作
2021/04/08 Python
python_tkinter事件类型详情
2022/03/20 Python