详解nodejs微信jssdk后端接口
发布时间 - 2026-01-11 01:19:02 点击率:次写过了两个微信的页面,遇到了挺多不会的问题,当时也是自己边查资料,边实践完成了简单的需求,刚好现在有空,把之前的东西整理一遍。

与普通的手机页面不同的是,微信页面提供给你了调用微信APP内置功能的接口,可以实现更复杂的功能。
jssdk的前端使用
- 前端页面调用jssdk首先要通绑定“公众号设置”的“功能设置”里填写“JS接口安全域名”
- 然后在页面中引入http://res.wx.qq.com/open/js/...
- 调用 wx.config({...}) 来验证权限配置
- 然后可根据需要 调用微信所提供的接口
后端返回接口
在前端调用时wx.config({...})中需要的参数需要我们自己进行返回
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的JS接口列表
});
其中 timestamp , nonceStr, signature,是需要后端计算返回的。
签名获取方法
签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。
而其中的 jsapi_ticket 是通过 access_token 来获取的,且两者都有过期时间(7200秒)其中 jsapi_ticket 更是限制了获取次数。所以为了保存两者,使用redis数据库保存在内存中是个很好的选择(可快速读取,并设置过期时间)。
token获取方法:
/**
* 获取token
* @return {promise} res 值为token
*/
function getToken () {
return redis.getVal('token') // 首先读取 redis 是否存在token
.then(function (res) {
if (res === null) { // 若不存在,则返回savetoken() 获取
// console.log('不存在token 调用saveToken')
return saveToken ()
} else { // 若存在 则直接返回
// console.log('存在token 直接返回')
return res
}
})
.catch(function (err) { // 捕获 错误
console.log(err)
})
}
/**
* 从服务端获取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中是否存在,如果存在就直接返回,没有的话,就调用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 调用saveJsTicket')
return saveJsTicket ()
} else { // 若存在 则直接返回
// console.log('存在ticket 直接返回')
return res
}
})
.catch(function (err) { // 捕获 错误
console.log(err)
})
}
/**
* 从服务端获取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) // 解析微信服务器返回的
let ticket = bodys.ticket // 获取 ticket
let expires = bodys.expires_in // 获取过期时间
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权限验证的签名了
/**
* 1. appId 必填,公众号的唯一标识
* 2. timestamp 必填,生成签名的时间戳
* 3. nonceStr 必填,生成签名的随机串
* 4. signature 必填,签名
*/
const crypto = require('crypto')
const getJsTicket = require('./getJsTicket')
const config = require('../../config') // 微信设置
// sha1加密
function sha1(str) {
let shasum = crypto.createHash("sha1")
shasum.update(str)
str = shasum.digest("hex")
return str
}
/**
* 生成签名的时间戳
* @return {字符串}
*/
function createTimestamp () {
return parseInt(new Date().getTime() / 1000) + ''
}
/**
* 生成签名的随机串
* @return {字符串}
*/
function createNonceStr () {
return Math.random().toString(36).substr(2, 15)
}
/**
* 对参数对象进行字典排序
* @param {对象} args 签名所需参数对象
* @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 ,注意必须动态获取,不能 hardcode
*
* @returns {对象} 返回微信jssdk所需参数对象
*/
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 所需参数对象
* @param {字符串} url 当前访问URL
* @return {promise} 返回promise类 val为对象
*/
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
以上基本就完成了后端返回签名的过程(省略了redis部分)。具体细节可参考我当时的练手项目中的代码。
至此,前端就可以使用jssdk来完成功能的调用了。
ps:某次使用录音接口做了一个功能,但是发现,微信服务器只会保存3天数据,需要自己下载到自己的服务器才行,不知道诸位有没做过类似的需求,给我提供下指导啥的,感激不尽~
后记
后来又写过一个获取用户信息的页面,感觉也是挺常用的就写个demo出来看看吧(没有做access_token的保存,好像是没有获取次数限制)。
router.get('/', function(req, res, next){
console.log("oauth - login")
// 第一步:用户同意授权,获取code
let router = 'get_wx_access_token'
// 这是编码后的地址
let return_uri = encodeURIComponent(base_url + router)
console.log('回调地址:' + 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')
})
// 第二步:通过code换取网页授权access_token
router.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){
// 第四步:根据获取的用户信息进行对应操作
let userinfo = JSON.parse(body)
console.log(JSON.parse(body))
console.log('获取微信信息成功!')
小测试,实际应用中,可以由此创建一个帐户
res.send("\
<h1>"+userinfo.nickname+" 的个人信息</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)
}
}
)
})
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# 微信jssdk
# nodejs
# jssdk
# 微信jssdk接口
# nodejs使用Express框架写后端接口的全过程
# 必填
# 所需
# 的是
# 是否存在
# 并保存
# 后端
# 不存在
# 若不
# 值为
# 服务端
# 就可以
# 自己的
# 这是
# 字段名
# 完成了
# 是个
# 给我
# 都有
# 很好
# 过了
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】
进行网站优化必须要坚持的四大原则
Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用
EditPlus 正则表达式 实战(3)
手机怎么制作网站教程步骤,手机怎么做自己的网页链接?
Laravel如何使用模型观察者?(Observer代码示例)
网易LOFTER官网链接 老福特网页版登录地址
零服务器AI建站解决方案:快速部署与云端平台低成本实践
软银砸40亿美元收购DigitalBridge 强化AI资料中心布局
Linux安全能力提升路径_长期防护思维说明【指导】
如何在建站宝盒中设置产品搜索功能?
深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?
瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口
如何快速查询网站的真实建站时间?
如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南
如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?
Python文件流缓冲机制_IO性能解析【教程】
Windows10如何更改计算机工作组_Win10系统属性修改Workgroup
高防服务器租用首荐平台,企业级优惠套餐快速部署
百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭
使用PHP下载CSS文件中的所有图片【几行代码即可实现】
如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?
如何选择可靠的免备案建站服务器?
Laravel如何与Pusher实现实时通信?(WebSocket示例)
如何快速重置建站主机并恢复默认配置?
Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】
iOS UIView常见属性方法小结
laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法
Bootstrap整体框架之CSS12栅格系统
如何在HTML表单中获取用户输入并用JavaScript动态控制复利计算循环
HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】
Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】
大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?
php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】
如何基于PHP生成高效IDC网络公司建站源码?
html5如何实现懒加载图片_ intersectionobserver api用法【教程】
Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南
Laravel如何配置Horizon来管理队列?(安装和使用)
Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权
Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】
湖南网站制作公司,湖南上善若水科技有限公司做什么的?
高端云建站费用究竟需要多少预算?
EditPlus中的正则表达式 实战(4)
Python面向对象测试方法_mock解析【教程】
如何在阿里云虚拟服务器快速搭建网站?
高防服务器租用指南:配置选择与快速部署攻略
Laravel如何使用Blade模板引擎?(完整语法和示例)
node.js报错:Cannot find module 'ejs'的解决办法
如何在IIS中新建站点并解决端口绑定冲突?
使用Dockerfile构建java web环境

