国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > JavaScript > 正文

詳解nodejs微信jssdk后端接口

2019-11-19 16:29:19
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

寫(xiě)過(guò)了兩個(gè)微信的頁(yè)面,遇到了挺多不會(huì)的問(wèn)題,當(dāng)時(shí)也是自己邊查資料,邊實(shí)踐完成了簡(jiǎn)單的需求,剛好現(xiàn)在有空,把之前的東西整理一遍。

與普通的手機(jī)頁(yè)面不同的是,微信頁(yè)面提供給你了調(diào)用微信APP內(nèi)置功能的接口,可以實(shí)現(xiàn)更復(fù)雜的功能。

jssdk的前端使用

  1. 前端頁(yè)面調(diào)用jssdk首先要通綁定“公眾號(hào)設(shè)置”的“功能設(shè)置”里填寫(xiě)“JS接口安全域名”
  2. 然后在頁(yè)面中引入http://res.wx.qq.com/open/js/...
  3. 調(diào)用 wx.config({...}) 來(lái)驗(yàn)證權(quán)限配置
  4. 然后可根據(jù)需要 調(diào)用微信所提供的接口

后端返回接口

在前端調(diào)用時(shí)wx.config({...})中需要的參數(shù)需要我們自己進(jìn)行返回

wx.config({  debug: true, // 開(kāi)啟調(diào)試模式,調(diào)用的所有api的返回值會(huì)在客戶端alert出來(lái),若要查看傳入的參數(shù),可以在pc端打開(kāi),參數(shù)信息會(huì)通過(guò)log打出,僅在pc端時(shí)才會(huì)打印。  appId: '', // 必填,公眾號(hào)的唯一標(biāo)識(shí)  timestamp: , // 必填,生成簽名的時(shí)間戳  nonceStr: '', // 必填,生成簽名的隨機(jī)串  signature: '',// 必填,簽名  jsApiList: [] // 必填,需要使用的JS接口列表});

其中 timestamp , nonceStr, signature,是需要后端計(jì)算返回的。

簽名獲取方法

簽名生成規(guī)則如下:參與簽名的字段包括noncestr(隨機(jī)字符串), 有效的jsapi_ticket, timestamp(時(shí)間戳), url(當(dāng)前網(wǎng)頁(yè)的URL,不包含#及其后面部分) 。對(duì)所有待簽名參數(shù)按照字段名的ASCII 碼從小到大排序(字典序)后,使用URL鍵值對(duì)的格式(即key1=value1&key2=value2…)拼接成字符串string1。這里需要注意的是所有參數(shù)名均為小寫(xiě)字符。對(duì)string1作sha1加密,字段名和字段值都采用原始值,不進(jìn)行URL 轉(zhuǎn)義。

而其中的 jsapi_ticket 是通過(guò) access_token 來(lái)獲取的,且兩者都有過(guò)期時(shí)間(7200秒)其中 jsapi_ticket 更是限制了獲取次數(shù)。所以為了保存兩者,使用redis數(shù)據(jù)庫(kù)保存在內(nèi)存中是個(gè)很好的選擇(可快速讀取,并設(shè)置過(guò)期時(shí)間)。

token獲取方法:

/** * 獲取token * @return {promise} res 值為token */function getToken () { return redis.getVal('token') // 首先讀取 redis 是否存在token  .then(function (res) {    if (res === null) {  // 若不存在,則返回savetoken() 獲取    // console.log('不存在token 調(diào)用saveToken')    return saveToken ()   } else {       // 若存在 則直接返回    // console.log('存在token 直接返回')    return res    }  })  .catch(function (err) {  // 捕獲 錯(cuò)誤   console.log(err)  })}/** * 從服務(wù)端獲取token 并保存在redis中 * @return {promise} 值 為 token */function saveToken () { return new Promise((resolve, reject) => {  let reqUrl = config.gettoken_url // https://api.weixin.qq.com/cgi-bin/token?  let params = {   grant_type: 'client_credential',   appid: config.appid,   secret: config.appsecret  }  let options = {   method: 'get',   url: reqUrl + qs.stringify(params)  }  request(options, function (err, res, body) {   if (res) {    let bodys = JSON.parse(body)    let expires = bodys.expires_in    let token = bodys.access_token        redis.setKey('token', token, expires) // 將token 保存到 redis     .catch(function (err) {      console.log(err)     })    resolve(token)   } else {    reject(err)   }  }) })}

在配置文件中配置好所需要的appid和appsecret,首先查看redis中是否存在,如果存在就直接返回,沒(méi)有的話,就調(diào)用saveToken去獲取并保存在redis中

jsapi_ticket 獲取方法

同理,jsapi_ticket 也采用同樣的方式去獲取

/** * 獲取ticket * @return {promise} res 值為ticket */function getJsTicket() { // 獲取token return redis.getVal('ticket') // 首先讀取 redis 是否存在ticket  .then(function (res) {    if (res === null) {  // 若不存在,則返回saveJsTicket() 獲取    // console.log('不存在ticket 調(diào)用saveJsTicket')    return saveJsTicket ()   } else {       // 若存在 則直接返回    // console.log('存在ticket 直接返回')    return res    }  })  .catch(function (err) {  // 捕獲 錯(cuò)誤   console.log(err)  })}/** * 從服務(wù)端獲取ticket 并保存在redis中 * @return {promise} 值 為 ticket */function saveJsTicket () { return new Promise((resolve, reject) => {  getToken().then(function (token) {   let reqUrl = config.ticket_start + token + config.ticket_end   let options = {    method: 'get',    url: reqUrl   }   request(options, function (err, res, body) {    if (res) {     let bodys = JSON.parse(body)   // 解析微信服務(wù)器返回的     let ticket = bodys.ticket    // 獲取 ticket     let expires = bodys.expires_in  // 獲取過(guò)期時(shí)間     redis.setKey('ticket', ticket, expires) // 將ticket 保存到 redis      .catch(function (err) {       console.log(err)      })     resolve(ticket)    } else {     reject(err)    }   })  }).catch(function (err) {    console.log(err)  }) })}

簽名算法

在獲取jsapi_ticket后就可以生成JS-SDK權(quán)限驗(yàn)證的簽名了

/** * 1. appId 必填,公眾號(hào)的唯一標(biāo)識(shí) * 2. timestamp 必填,生成簽名的時(shí)間戳 * 3. nonceStr 必填,生成簽名的隨機(jī)串 * 4. signature 必填,簽名 */const crypto = require('crypto')const getJsTicket = require('./getJsTicket')const config = require('../../config') // 微信設(shè)置// sha1加密function sha1(str) { let shasum = crypto.createHash("sha1") shasum.update(str) str = shasum.digest("hex") return str}/** * 生成簽名的時(shí)間戳 * @return {字符串}  */function createTimestamp () { return parseInt(new Date().getTime() / 1000) + ''}/** * 生成簽名的隨機(jī)串 * @return {字符串}  */function createNonceStr () { return Math.random().toString(36).substr(2, 15)}/** * 對(duì)參數(shù)對(duì)象進(jìn)行字典排序 * @param {對(duì)象} args 簽名所需參數(shù)對(duì)象 * @return {字符串}  排序后生成字符串 */function raw (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}/*** @synopsis 簽名算法 ** @param jsapi_ticket 用于簽名的 jsapi_ticket* @param url 用于簽名的 url ,注意必須動(dòng)態(tài)獲取,不能 hardcode** @returns {對(duì)象} 返回微信jssdk所需參數(shù)對(duì)象*/function sign (jsapi_ticket, url) { var ret = {  jsapi_ticket: jsapi_ticket,  nonceStr: createNonceStr(),  timestamp: createTimestamp(),  url: url } var string = raw(ret) ret.signature = sha1(string) ret.appId = config.appid return ret}/** * 返回微信jssdk 所需參數(shù)對(duì)象 * @param {字符串} url 當(dāng)前訪問(wèn)URL * @return {promise}   返回promise類 val為對(duì)象 */function jsSdk (url) { return getJsTicket()  .then(function (ticket) {   return sign(ticket, url)  })  .catch(function (err) {   console.log(err)  })}function routerSdk (req, res, next) { let clientUrl = req.body.url if (clientUrl) {  jsSdk(clientUrl)   .then(function (obj) {    res.json(obj)   }) } else {  res.end('no url') }}module.exports = routerSdk

以上基本就完成了后端返回簽名的過(guò)程(省略了redis部分)。具體細(xì)節(jié)可參考我當(dāng)時(shí)的練手項(xiàng)目中的代碼。

至此,前端就可以使用jssdk來(lái)完成功能的調(diào)用了。

ps:某次使用錄音接口做了一個(gè)功能,但是發(fā)現(xiàn),微信服務(wù)器只會(huì)保存3天數(shù)據(jù),需要自己下載到自己的服務(wù)器才行,不知道諸位有沒(méi)做過(guò)類似的需求,給我提供下指導(dǎo)啥的,感激不盡~

后記

后來(lái)又寫(xiě)過(guò)一個(gè)獲取用戶信息的頁(yè)面,感覺(jué)也是挺常用的就寫(xiě)個(gè)demo出來(lái)看看吧(沒(méi)有做access_token的保存,好像是沒(méi)有獲取次數(shù)限制)。

router.get('/', function(req, res, next){ console.log("oauth - login") // 第一步:用戶同意授權(quán),獲取code let router = 'get_wx_access_token' // 這是編碼后的地址 let return_uri = encodeURIComponent(base_url + router) console.log('回調(diào)地址:' + return_uri) let scope = 'snsapi_userinfo' res.redirect('https://open.weixin.qq.com/connect/oauth2/authorize?appid='+appid+'&redirect_uri='+return_uri+'&response_type=code&scope='+scope+'&state=STATE#wechat_redirect')})// 第二步:通過(guò)code換取網(wǎng)頁(yè)授權(quán)access_tokenrouter.get('/get_wx_access_token', function(req,res, next){ console.log("get_wx_access_token") console.log("code_return: "+req.query.code) let code = req.query.code request.get(  {     url:'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' + appid + '&secret=' + appsecret+'&code=' + code + '&grant_type=authorization_code',  },  function(error, response, body){   if(response.statusCode === 200){    // 第三步:拉取用戶信息(需scope為 snsapi_userinfo)    // console.log(JSON.parse(body))    let data = JSON.parse(body)    let access_token = data.access_token    let openid = data.openid    request.get(     {      url:'https://api.weixin.qq.com/sns/userinfo?access_token='+access_token+'&openid='+openid+'&lang=zh_CN',     },     function(error, response, body){      if(response.statusCode == 200){       // 第四步:根據(jù)獲取的用戶信息進(jìn)行對(duì)應(yīng)操作       let userinfo = JSON.parse(body)       console.log(JSON.parse(body))       console.log('獲取微信信息成功!')       小測(cè)試,實(shí)際應(yīng)用中,可以由此創(chuàng)建一個(gè)帳戶       res.send("/         <h1>"+userinfo.nickname+" 的個(gè)人信息</h1>/         <p><img src='"+userinfo.headimgurl+"' /></p>/         <p>"+userinfo.city+","+userinfo.province+","+userinfo.country+"</p>/       ")      }else{       console.log(response.statusCode)      }     }    )   }else{    console.log(response.statusCode)   }  } )})

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 肥乡县| 柯坪县| 玉田县| 宁蒗| 廊坊市| 郴州市| 南岸区| 深泽县| 琼中| 桂林市| 岳西县| 韩城市| 平昌县| 玉环县| 蕉岭县| 博兴县| 东乡族自治县| 石河子市| 静乐县| 玉溪市| 奇台县| 抚远县| 那坡县| 大冶市| 内江市| 宾阳县| 砀山县| 岚皋县| 若羌县| 云阳县| 玉田县| 宝兴县| 玉田县| 松滋市| 达日县| 杭锦旗| 鹿邑县| 子长县| 潢川县| 山阳县| 登封市|