目录
前言
小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。
注意事项
- 会话密钥
session_key
是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。 - 临时登录凭证 code 只能使用一次
授权
部分接口需要经过用户授权同意才能调用。我们把这些接口按使用范围分成多个 scope
,用户选择对 scope
来进行授权,当授权给一个 scope
之后,其对应的所有接口都可以直接使用。此类接口调用时:
- 如果用户未接受或拒绝过此权限,会弹窗询问用户,用户点击同意后方可调用接口;
- 如果用户已授权,可以直接调用接口;
- 如果用户已拒绝授权,则不会出现弹窗,而是直接进入接口 fail 回调。请开发者兼容用户拒绝授权的场景。
express脚手架配置
第一步:在node.js安装完成的情况下搭建express脚手架,并在在根目录新建config.js,内容如下:
// token全局配置文件
module.exports = {
// 加密和解密的token秘钥(引号中的字符可以自定义)
jwtSecretKey: 'advance8',
// token有效期
expiresIn: '8640h'
}
第二步:在routes下新建router_handle/wxuser.js,并引入数据库连接模块以及config.js,内容如下:
const request = require('request')
//引入连接数据库模块
const db = require('../conn')
//连接数据
db.connect(() => {
console.log("连接成功")
})
const jwt = require("jsonwebtoken");// 导入生成token的包
const config = require("../../config");
const { jwtSecretKey } = require("../../config");
exports.wxuser = (req, res) => {
let params = req.body; // 接收小程序端传过来的所有数据
let code = params.code; //获取小程序传来的code
let encryptedData = params.encryptedData; //获取小程序传来的encryptedData
let iv = params.iv; //获取小程序传来的iv
let userInfo = JSON.parse(params.userInfo); //获取个人信息
let appid = ""; //自己小程序后台管理的appid,可登录小程序后台查看
let mysecret = ""; //小程序后台管理的secret,可登录小程序后台查看
let grant_type = "authorization_code"; // 授权(必填)默认值
//请求获取openid
let url =
"https://api.weixin.qq.com/sns/jscode2session?grant_type=" +
grant_type +
"&appid=" +
appid +
"&mysecret=" +
mysecret +
"&js_code=" +
code;
request(url, (err, response, body) => {
if (!err && response.statusCode == 200) {
// 服务器返回的openid、sessionKey
let _data = JSON.parse(body);
_data.code = code;
_data.session_key = "";
// 对用户信息进行加密生成字符串
const wxToken = jwt.sign(_data, jwtSecretKey, {
expiresIn: config.expiresIn,
});
// 定义sql 语句,查询当前用户是否存在(openid)
const sql = `select * from WeChatUser where user_id = ?`;
db.query(sql, _data.openid, (err, result) => {
if (err) return res.cc(err); //res.cc为自定义封装,可以换成res.send
if (result.length === 0) {
const sql = `insert into WeChatUser set ?`;
db.query(
sql, {
user_id: _data.openid,
nickName: userInfo.nickName,
avatar: userInfo.avatarUrl,
gender: userInfo.gender,
},
(err, result) => {
if (err) return res.cc(err);
if (result.affectedRows !== 1) return res.cc("授权失败,请重试");
res.send({
token: "Bearer " + wxToken,
status: 200,
messages: "WX授权成功",
});
}
);
} else {
const sql = `update WeChatUser set ? where user_id = ?`;
db.query(
sql, [{
user_id: _data.openid,
nickName: userInfo.nickName,
avatar: userInfo.avatarUrl,
gender: userInfo.gender,
},
_data.openid,
],
(err, result) => {
if (err) return res.cc(err);
res.send({
token: "Bearer " + wxToken,
status: 200,
messages: "WX授权成功",
});
}
);
}
});
} else {
res.cc("请求openid失败");
}
});
};
第三步:分别是路由模块以及app.js的配置
var express = require('express');
var router = express.Router();
//引入连接数据库模块
const conn = require('./conn')
//连接数据
conn.connect(() => {
console.log("WeChatUser表连接成功")
})
var jsonWrite = function(res, ret) {
if (typeof ret === 'undefined') {
res.json({
code: '1',
msg: '操作失败'
});
} else {
res.json(
ret
);
}
};
/*获取微信用户列表*/
router.post('/wxuserList', (req, res) => {
const sqlStr = `select * from WeChatUser`
conn.query(sqlStr, function(err, result) {
if (err) {
console.log(err);
}
if (result) {
jsonWrite(res, result);
}
})
});
const wxuserHandle = require('./router_handle/wxuser')
router.post('/wxuser', wxuserHandle.wxuser)
module.exports = router;
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'code/public')));
// error handler
app.use(function(err, req, res, next) {
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
res.status(err.status || 500);
res.render('error');
});
const wxuserApi = require('./routes/index');
// 允许跨域
app.all('*', function(req, res, next) {
console.log(req.headers.origin)
console.log(req.environ)
// res.header("Access-Control-Allow-Origin", req.headers.origin);
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin", "*");
//允许的header类型
res.header("Access-Control-Allow-Headers", "content-type");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
if (req.method == 'OPTIONS') {
/*让options请求快速返回*/
res.sendStatus(200)
} else {
next()
}
});
app.use('/wxuser', wxuserApi);
//配置默认端口
app.listen(3008, () => {
console.log("服务器已启动")
})
module.exports = app;
最后,启动服务器,显示如下内容表示成功
uniapp配置
HTML
<button class="cu-btn block bg-green margin-tb-sm lg shadow" @click="getUserProfile">
微信一键登录
</button>
JS
methods(){
getUserProfile: function(e) {
var that=this;
// 获取个人信息
wx.getUserProfile({
desc: '用于获取用户个人信息',
success: function(detail) {
wx.login({
success(res) {
var code = res.code; //登录凭证
uni.request({
url: '',
// 需要传给后端的数据
data: {
encryptedData: detail.encryptedData,
iv: detail.iv,
code: code,
userInfo: detail.rawData
},
method: 'post',
success: function(res) {
// 将用户授权信息存储到本地
wx.setStorageSync('userinfo', detail.userInfo)
// 将后端返回的token存储到本地
wx.setStorageSync('token', res.data.token)
//通过接口获取数据库中数据
uni.request({
url:'',
data: {},
method: 'post',
header: {
'content-type': 'application/json'
},
success: (res) => {
that.nickName=res.data[0].nickName
that.avatar=res.data[0].avatar
}
})
},
fail: function() {
console.log('系统错误')
}
})
}
});
},
fail: function() {
wx.showModal({
content: '取消授权将会影响相关服务,您确定取消授权吗?',
success(res) {
if (res.confirm) {
wx.showToast({
title: '已取消授权',
duration: 1500
})
} else if (res.cancel) {
this.getUserProfile()
}
}
})
}
})
}
}
运行结果
❤辛苦大佬们给下方公众号点个订阅❤
本文含有隐藏内容,请 开通VIP 后查看