搜尋
首頁web前端js教程實作Node.js在微信JS-SDK後端接口

實作Node.js在微信JS-SDK後端接口

Jul 18, 2017 pm 05:57 PM
javascriptjs-sdknode.js

做了一個網站,放到線上,用微信打開,點擊分享,可是分享後發給朋友的連結卡是微信預設自帶的,如下:
實作Node.js在微信JS-SDK後端接口


這標題,描述以及圖片是預設自帶的,醜不說,分享給別人還以為是盜號網站呢,而接入微信的JSSDK後,分享可以自訂內容,如下:
實作Node.js在微信JS-SDK後端接口


我承認,雖然這分享的標題和內容也不正經,但這不妨礙我表達我們可以透過微信JSSDK定義分享內容,接下來我們將一步一步從零實作JSSDK從後端Node.js的存取。

介面設定資訊

修改介面設定資訊

  1. #URL位址必須是你伺服器上的位址,此位址要能通過瀏覽器的位址欄訪問到(沒有伺服器?沒關係,一會兒我們搭建一個)
    假設我這裡填寫的伺服器位址是"http://www.your_server_name.com/wxJssdk"


## Token你可以隨意填寫,用作生成簽名,(不知道簽名?沒關係,一會兒會用到這東西的)假設我這裡填寫的Token是"jegfjaeghfuccawegfgjdbh" #此時點擊提交是會提示配置失敗的,因為在提交的時候,微信是會請求你的伺服器地址,而你的當前配置的地址並不能訪問,所以會提示配置失敗。不過別急,我們先來搭建一個簡單的Node伺服器,讓微信能夠存取該伺服器。 搭建簡單的Node伺服器我們需要在這個網域上搭建一個伺服器,並且曝出一個介面為/wxJssdk
const express = require('express')const app = express()app.get('/wxJssdk', (req, res) => {
  res.send('请求成功了了了了')})app.listen(80, err => {
  if(!err) console.log('connect succeed')})
現在我們在地址欄中訪問,如果頁面顯示“請求成功了了了”,則進入到下一步,如果沒有成功的話,檢查一下你的伺服器是否開啟Node伺服器,如: node index.js此時保存微信測試公眾號後台的介面配置訊息,仍然會提示配置失敗,這是因為我們沒有按照它的要求返回。 根據微信測試公眾號請求資訊返回對應內容根據微信公眾號開發文件存取指南,微信在請求我們配置的介面時,會帶上以下資訊參數
描述
#signature######微信加密簽名,signature結合了開發者填寫的token參數和請求中的timestamp參數、nonce參數。 ############timestamp######時間戳記#############nonce######隨機數字######## ####echostr######隨機字串############

微信服务器会通过GET请求,来请求我们所配置的接口,并带上以上表格的信息,而我们必须按照以下要求,将微信发送的信息进行要求校验,以确保是微信发送的信息,其中校验流程如下:

1)将token、timestamp、nonce三个参数进行字典序排序
2)将三个参数字符串拼接成一个字符串进行sha1加密
3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

const express = require('express')const app = express()const sha1 = require('sha1')app.get('/wxJssdk', (req, res) => {
  let wx = req.query

  let token = 'jegfjaeghfuccawegfgjdbh'
  let timestamp = wx.timestamp
  let nonce = wx.nonce

  // 1)将token、timestamp、nonce三个参数进行字典序排序
  let list = [token, timestamp, nonce].sort()  // 2)将三个参数字符串拼接成一个字符串进行sha1加密
  let str = list.join('')  let result = sha1(str)  // 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
  if (result === wx.signature) {res.send(wx.echostr) // 返回微信传来的echostr,表示校验成功,此处不能返回其它
  } else {res.send(false)  }})

此时我们重启Node服务器,再次保存接口配置信息即可配置成功。

微信JSSDK使用步骤

根据微信JSSDK说明文档,我们需要完成如下:

填写安全域名

登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”,即要调用接口的域名,不包含协议

前端引入JS

在需要调用JS接口的页面引入此JS文件,(支持https):

填写接口的配置信息

wx.config({
  debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  appId: '', // 必填,公众号的唯一标识
  timestamp: , // 必填,生成签名的时间戳
  nonceStr: '', // 必填,生成签名的随机串
  signature: '',// 必填,签名
  jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2});

调用接口

做你前端该做的,调用微信分享接口,或微信提供的其它接口,whatever you need,当然,这并不是我们所要讲的重点,我们接下来要看一下微信的配置信息从哪获取

在Node服务器中生成jssdk所需要的配置信息

从上一节可以看到,调用微信JSSDK需要以下信息

  1. appId

  2. timestamp

  3. nonceStr

  4. signature

  5. jsApiList

其中:

  1. 第1项appId是测试公众号后台的appId,我们已知

  2. 第2项时间戳我们也可以自己生成

  3. 第3项nonceStr可以随意填写,你可以理解为密钥

  4. 第4项signature则需要我们按要求生成

  5. 第5项是所需要接口的接口名

生成signature

生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。

为了保证我们appid,appsecret,nonceStr等信息不在前端曝露,我们以下步骤将在服务器上进行操作,以免他人盗用信息获取(注:微信请求有每日次数限制,一旦超出,则无法使用,具体请求次数限制在微信公众号后台中可查看)

生成access_token

根据微信开发文档[获取access_token文档说明],我们需要将微信测试公众号后台的appid和和appsecret以GET的请求方式向 发起请求获取token,请求成功后我们会获得下返回JSON转化的字符串

{"access_token":"ACCESS_TOKEN","expires_in":7200}

具体请求代码如下:

const request = require('request')const grant_type = 'client_credential'const appid = 'your app id'const secret = 'your app secret'request('https://api.weixin.qq.com/cgi-bin/token?grant_type=' + grant_type + '&appid=' + appid + '&secret=' + secret, (err, response, body) => {
  let access_toekn = JSON.parse(body).access_token})

获取jsapi_ticket

const request = require('request')const grant_type = 'client_credential'const appid = 'your app id'const secret = 'your app secret'request('https://api.weixin.qq.com/cgi-bin/token?grant_type=' + grant_type + '&appid=' + appid + '&secret=' + secret, (err, response, body) => {
  let access_toekn = JSON.parse(body).access_token

  request('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + access_token + '&type=jsapi', (err, response, body) => { let jsapi_ticket = JSON.parse(body).ticket
  })})

生成签名

生成签名的步骤和最开始的/wxJssdk的算法是一致的,具体如下:

let jsapi_ticket = jsapi_ticket  // 上一步从获取的jsapi_ticketlet nonce_str = '123456'    // 密钥,字符串任意,可以随机生成let timestamp = new Date().getTime()  // 时间戳let url = req.query.url   // 使用接口的url链接,不包含#后的内容// 将请求以上字符串,先按字典排序,再以'&'拼接,如下:其中j > n > t > u,此处直接手动排序let str = 'jsapi_ticket=' + jsapi_ticket + '&noncestr=' + nonce_str + '&timestamp=' + timestamp + '&url=' + url// 用sha1加密let signature = sha1(str)

连接后的代码为:

const request = require('request')const grant_type = 'client_credential'const appid = 'your app id'const secret = 'your app secret'request('https://api.weixin.qq.com/cgi-bin/token?grant_type=' + grant_type + '&appid=' + appid + '&secret=' + secret, (err, response, body) => {
  let access_toekn = JSON.parse(body).access_token

  request('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + access_token + '&type=jsapi', (err, response, body) => { let jsapi_ticket = JSON.parse(body).ticket let nonce_str = '123456'    // 密钥,字符串任意,可以随机生成 let timestamp = new Date().getTime()  // 时间戳 let url = req.query.url   // 使用接口的url链接,不包含#后的内容 // 将请求以上字符串,先按字典排序,再以'&'拼接,如下:其中j > n > t > u,此处直接手动排序 let str = 'jsapi_ticket=' + jsapi_ticket + '&noncestr=' + nonce_str + '&timestamp=' + timestamp + '&url=' + url     // 用sha1加密 let signature = sha1(str)  })})

曝露接口,返回给前端

app.post('/wxJssdk/getJssdk', (req, res) => {
  const request = require('request')  const grant_type = 'client_credential'
  const appid = 'your app id'
  const secret = 'your app secret'

  request('https://api.weixin.qq.com/cgi-bin/token?grant_type=' + grant_type + '&appid=' + appid + '&secret=' + secret, (err, response, body) => {let access_toekn = JSON.parse(body).access_tokenrequest('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + access_token + '&type=jsapi', (err, response, body) => {   let jsapi_ticket = JSON.parse(body).ticket   let nonce_str = '123456'    // 密钥,字符串任意,可以随机生成   let timestamp = new Date().getTime()  // 时间戳   let url = req.query.url   // 使用接口的url链接,不包含#后的内容   // 将请求以上字符串,先按字典排序,再以'&'拼接,如下:其中j > n > t > u,此处直接手动排序   let str = 'jsapi_ticket=' + jsapi_ticket + '&noncestr=' + nonce_str + '&timestamp=' + timestamp + '&url=' + url       // 用sha1加密   let signature = sha1(str)       res.send({ appId: appid, timestamp: timpstamp, nonceStr: nonce_str, signature: signature,   })})  })})

前端请求后端接口,获取配置信息

获取配置

axios.post('/wxJssdk/getJssdk', {url: location.href}).then((response) => {
  var data = response.data

  wx.config({debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId: data.appId, // 必填,公众号的唯一标识timestamp: data.timestamp, // 必填,生成签名的时间戳nonceStr: data.nonceStr, // 必填,生成签名的随机串signature: data.signature,// 必填,签名,见附录1jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
  });})

做你想做的,比如,自定义分享

if (wx) {
  axios.post('/wxJssdk/getJssdk', {url: location.href}).then((response) => {var data = response.datawx.config({  debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。  appId: data.appId, // 必填,公众号的唯一标识  timestamp: data.timestamp, // 必填,生成签名的时间戳  nonceStr: data.nonceStr, // 必填,生成签名的随机串  signature: data.signature,// 必填,签名,见附录1  jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2});wx.ready(function () {  wx.onMenuShareTimeline({  title: wxShare.title,  desc: wxShare.desc,  link: wxShare.link,  imgUrl: wxShare.imgUrl  });  wx.onMenuShareAppMessage({  title: wxShare.title,  desc: wxShare.desc,  link: wxShare.link,  imgUrl: wxShare.imgUrl});
  })wx.error(function (res) {   // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。})  })}

至此,后端配置好了,我们已经能够正常使用微信的接口了,但是微信每日接口请求是有上限的,通过2000次/天,因此如果网站上线后,一量当天访问量超过2000次你的接口将失效,而且每次都请求微信接口两次,造成请求时间浪费,所以我们需要将以上获取信息缓存在后端,避免造成接口失效以及多次请求微信后台。

缓存access_token及jsapi_ticket

此处直接上代码,利用node_cache包进行缓存

const request = require('request')const express = require('express')const app = express()const sha1 = require('sha1')const waterfall = require('async/waterfall')const NodeCache = require('node-cache')const cache = new NodeCache({stdTTL: 3600, checkperiod: 3600}) //3600秒后过过期app.get('/wxJssdk', (req, res) => {
  let wx = req.query

  // 1)将token、timestamp、nonce三个参数进行字典序排序
  let token = 'jegfjaeghfuyawegfgjdbh'
  let timestamp = wx.timestamp
  let nonce = wx.nonce

  // 2)将三个参数字符串拼接成一个字符串进行sha1加密
  let list = [token, timestamp, nonce]  let result = sha1(list.sort().join(''))  // 3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
  if (result === wx.signature) {res.send(wx.echostr)  } else {res.send(false)  }})app.get('/wxJssdk/getJssdk', (req, res) => {
  let grant_type = 'client_credential'
  let appid = 'your app id'
  let secret = 'your app secret' // appscret

  let steps = []  // 第一步,获取access_token
  steps.push((cb) => {

  let steps1 = []// 第1.1步,从缓存中读取access_tokensteps1.push((cb1) => {  let access_token = cache.get('access_token', (err, access_token) => {cb1(err, access_token)      })})// 第1.2步,缓存中有access_token则直接返回,如果没有,则从服务器中读取access_tokensteps1.push((access_token, cb1) => {  if (access_token) {cb1(null, access_token, 'from_cache')      } else {request('https://api.weixin.qq.com/cgi-bin/token?grant_type=' + grant_type + '&appid=' + appid + '&secret=' + secret, (err, response, body) => {  cb1(err, JSON.parse(body).access_token, 'from_server')})      }})// 第1.3步,如果是新从服务器取的access_token,则缓存起来,否则直接返回steps1.push((access_token, from_where, cb1) => {  if (from_where === 'from_cache') {console.log(' === 成功从缓存中读取access_token: ' + access_token + ' ===')cb1(null, access_token)      } else if (from_where === 'from_server') {cache.set('access_token', access_token, (err, success) => {  if (!err && success) {console.log(' === 缓存已过期,从服务器中读取access_token: ' + access_token + ' ===')cb1(null, access_token)          } else {cb1(err || 'cache设置access_token时,出现未知错误')          }})      } else {cb1('1.3获取from_where时,from_where值为空')      }})waterfall(steps1, (err, access_token) => {  cb(err, access_token)})  })  // 第二步,获取ticket
  steps.push((access_token, cb) => {let steps1 = []// 第2.1步,从缓存中读取ticketsteps1.push((cb1) => {  let ticket = cache.get('ticket', (err, ticket) => {cb1(err, ticket)      })})// 第2.2步,缓存中有ticket则直接返回,如果没有,则从服务器中读取ticketsteps1.push((ticket, cb1) => {  if (ticket) {cb1(null, ticket, 'from_cache')      } else {request('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' + access_token + '&type=jsapi', (err, response, body) => {  cb1(err, JSON.parse(body).ticket, 'from_server')})      }})// 第2.3步,如果新从服务器取的ticket,则缓存起来,否则直接返回steps1.push((ticket, from_where, cb1) => {  if (from_where === 'from_cache') {console.log(' === 成功从缓存中读取ticket: ' + ticket + ' ===')cb1(null, ticket)      } else if (from_where === 'from_server') {cache.set('ticket', ticket, (err, success) => {  if (!err && success) {console.log(' === 缓存已过期,从服务器中读取ticket: ' + ticket + ' ===');cb1(null, ticket)          } else {cb1(err || 'cache设置ticket时,出现未知错误')          }})      } else {cb1('2.3获取from_where时,from_where值为空')      }})waterfall(steps1, (err, ticket) => {  cb(err, ticket)})  })  // 第三步,生成签名
  steps.push((ticket, cb) => {let jsapi_ticket = ticketlet nonce_str = '123456'let timestamp = new Date().getTime()let url = req.query.urllet str = 'jsapi_ticket=' + jsapi_ticket + '&noncestr=' + nonce_str + '&timestamp=' + timestamp + '&url=' + urllet signature = sha1(str)cb(null, {  appId: appid,  timestamp: timestamp,  nonceStr: nonce_str,  signature: signature,  ticket: ticket})  })  waterfall(steps, (err, data) => {if (err) {  res.send({status: 'error', data: err})} else {  res.send({status: 'success', data: data})}
  })})app.use('/wxJssdk/public', express.static('public'))app.listen(80, err => {
  if(!err) console.log('connect succeed')})

以上是實作Node.js在微信JS-SDK後端接口的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript框架:為現代網絡開發提供動力JavaScript框架:為現代網絡開發提供動力May 02, 2025 am 12:04 AM

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

JavaScript,C和瀏覽器之間的關係JavaScript,C和瀏覽器之間的關係May 01, 2025 am 12:06 AM

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

node.js流帶打字稿node.js流帶打字稿Apr 30, 2025 am 08:22 AM

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python vs. JavaScript:性能和效率注意事項Python vs. JavaScript:性能和效率注意事項Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript的起源:探索其實施語言JavaScript的起源:探索其實施語言Apr 29, 2025 am 12:51 AM

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

幕後:什麼語言能力JavaScript?幕後:什麼語言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

Python和JavaScript的未來:趨勢和預測Python和JavaScript的未來:趨勢和預測Apr 27, 2025 am 12:21 AM

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python vs. JavaScript:開發環境和工具Python vs. JavaScript:開發環境和工具Apr 26, 2025 am 12:09 AM

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器