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

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

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

踩的坑:

1.签名算法不一致: 通过 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 验证算法正确性

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

3.timestamp需要精确到秒。

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

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

(0)

相关推荐

  • Node.js 获取微信JS-SDK CONFIG的方法示例

    背景 前端在调用微信提供的分享.拍照.扫一扫等功能时需要到后台获取配置,主要是签名(signature).Node 开发可以用朴灵大佬的SDK-- co-wechat-api. 配置 到微信公众平台进入"公众号设置"的"功能设置"里填写"JS接口安全域名".前提是该域名的项目目录下有微信提供的校验文件.如果需要本地调试或者测试环境调试,可以把IP白名单也顺便配置一下. 开发 实例化 WechatAPI 对象 const WECHAT_API =

  • 详解基于Node.js的微信JS-SDK后端接口实现代码

    做了一个网站,放到线上,用微信打开,点击分享,可是分享后发给朋友的链接卡片是微信默认自带的,如下: 这标题,描述以及图片是默认自带的,丑不说,分享给别人还以为是盗号网站呢,而接入微信的JSSDK后,分享可以自定义内容,如下: 我承认,虽然这分享的标题和内容也并不正经,但这不妨碍我表达我们可以通过微信JSSDK定义分享内容,接下来我们将一步一步从零实现JSSDK从后端Node.js的接入. 成为测试公众号开发者 登录测试公众号后台 首先我们需要在微信公众平台申请测试接口,地址:https://mp

  • 微信JS SDK接入的几点注意事项(必看篇)

    微信JS SDK接入,主要可以先参考官网说明文档,总结起来有几个步骤: 1.绑定域名: 先登录微信公众平台进入"公众号设置"的"功能设置"里填写"JS接口安全域名". 备注:登录后可在"开发者中心"查看对应的接口权限. 2.引入JS文件:在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.2.0.js, 备注:支持使用 AMD/CMD 标准

  • 微信js sdk invalid signature签名错误问题的解决方法分析

    本文实例讲述了微信js sdk invalid signature签名错误问题的解决方法.分享给大家供大家参考,具体如下: /**最近在做微信js sdk 接口调用说明*/ ***相信很多人都遇见像我这样的问题,再加上自己只能算是半个程序员,所以苦苦摸索了好久终于搞懂了. ****下面就把自己所遇见的各种问题和大家分享一下,都是自己亲手实验过的********/ 一.问题说明 如果出现 invalid signature,首先可以确定的是你的签名算法有问题. 建议:首先查看微信官方网站给出的解决

  • 基于nodejs实现微信支付功能

    本文实例为大家分享了nodejs实现微信支付的具体代码,供大家参考,具体内容如下 通过nodejs使用微信支付最重要的就是微信的签名,在这里md5后的字符必须转化为大写 一.回复微信通知消息模版 message.ejs <xml> <return_code><![CDATA[<%-return_code%>]]></return_code> <return_msg><![CDATA[<%=return_msg%>]]

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

    2015 是 Hybrid App 崛起之年 ,Web App 和 Native App 各有其强大之处,也有着致命的缺点,人们一边追求native流畅的用户体验,一边同时期望产品能够快速的迭代更新,Hybrid 成为必然的趋势. 鹅厂一马当先,发布了业内震惊一时的 JS-SDK , 这对于基于微信的h5开发者来说简直是如降甘露,从此开发者们告别了用箭头来提示右上角可以分享,并且随时可以使用微信的原生能力,微信变成了一个超级浏览器. 一.准备工作 1.在微信公众平台申请测试账号,并设置好好 JS

  • 基于JS实现简单的样式切换效果代码

    本文实例讲述了基于JS实现简单的样式切换效果.分享给大家供大家参考.具体如下: 这是一款基于JS实现简单的样式切换代码,自由切换CSS样式,很多大网站现在正在用,我觉得这是个挺实用的不错的功能,希望大家喜欢哦. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-simple-tab-cha-style-codes/ 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transiti

  • 基于JS实现简单滑块拼图游戏

    成品效果 <body> <div id="game" style="position:relative"></div> </body> /** * js配置 */ var config = { width: 300, height: 300, img: "./img/fj.jpg", gameDom: document.getElementById("game"), row: 3

  • 基于python实现微信好友数据分析(简单)

    一.功能介绍 本文主要介绍利用网页端微信获取数据,实现个人微信好友数据的获取,并进行一些简单的数据分析,功能包括: 1.爬取好友列表,显示好友昵称.性别和地域和签名, 文件保存为 xlsx 格式 2.统计好友的地域分布,并且做成词云和可视化展示在地图上 二.依赖库 1.Pyecharts:一个用于生成echarts图表的类库,echarts是百度开源的一个数据可视化库,用echarts生成的图可视化效果非常棒,使用pyechart库可以在python中生成echarts数据图. 2.Itchat

  • 基于HTML+JS实现简单的年龄计算器

    目录 前言 演示效果 HTML代码 CSS代码 Javascript代码 演示地址 前言 在线演示地址:http://haiyong.site/age-calculator JavaScript提供了一些内置的日期和时间函数,有助于从日期(出生日期)开始计算年龄.使用这些JavaScript方法,您可以轻松找到任何人的年龄.为此,我们需要用户输入日期和当前系统日期. 演示效果 HTML代码 <div class="container"> <div class=&quo

  • 基于JS实现简单的3D立方体自动旋转

    目录 演示 技术栈 源码 css js 雪花部分 演示 技术栈 display:inline-block,block,inline元素的区别: display:block将元素显示为块级元素,从而可以更好地操控元素的宽高,以及内外边距,每一个块级元素都是从新的一行开始. display : inline将元素显示为行内元素,高度,行高以及底边距不可改变,高度就是内容文字或者图片的宽度,不可以改变.多个相邻的行内元素排在同一行里,知道页面一行排列不下,才会换新的一行. display:inline

  • 基于React.js实现简单的文字跑马灯效果

    刚好手上有一个要实现文字跑马灯的react项目,然后ant-design上面没有这个组件,于是只能自己手撸一个. 我想到的最简单的方法,就是定位啦,定时移动这个文字块不就跑起来了. 需要注意的是,要判断文字的宽度,当文字超出屏幕的宽度的时候再动起来,我用的是hook的写法,要在销毁页面的时候清掉定时器.定时器要放在useRef里面. const timer = useRef<any>(null); const [left, setLeft] = useState(0); const conte

随机推荐