准备工作
开发者ID和开发者密码
登录微信公众平台->开发->获取开发者ID(AppID)和开发者密码(AppSecret)。
网页授权
登录微信公众平台->开发->网页授权(修改)->网页授权域名(设置)->按提示下载文件上传服务器设置域名通过验证即可。
unionid
微信开放平台绑定公众号,获取用户信息时才会有unionid;
openid:需要该用户关注了公众号才产生,公众号下唯一,包括其他微信接口都需要此值;
unionid:微信开放平台下多个公众号,或在公众号、移动应用之间统一的用户帐号
开发者
登录微信公众平台->开发->开发者工具->web开发者工具->绑定开发者微信号->按提示
class Wechat {
// !!!!utils不存在,只做示例;
constructor(appid, appsecret, redirect_uri) {
super()
this.appid = appid
this.appsecret = appsecret
this.redirect_uri = encodeURIComponent(redirect_uri)
}
wechat(req, res) {
let redirect_uri = this.redirect_uri
if (req.query.referer) {
// 回调地址以redirect_uri查询字符串传递,重定向时会进行decode。所以需要再次encode;
redirect_uri += encodeURIComponent('?referer=' + encodeURIComponent(req.query.referer))
} else {
return '回调url,referer参数不存在'
}
let scope = req.query.scope || 'snsapi_userinfo'
redirect_uri = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' + this.appid + '&redirect_uri=' + redirect_uri + '&response_type=code&scope=' + scope + '#wechat_redirect'
this.redirect(res, redirect_uri)
return null
}
async getAccessToken(req, res) {
let referer = req.query.referer
let code = req.query.code
let errcode = null
let userinfo = null
let token = ''
if (code && referer) {
// 使用 code 请求获取 access_token、appid
let data = utils.require('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' + this.appid + '&secret=' + this.appsecret + '&code=' + code + '&grant_type=authorization_code')
if (data.errcode) {
errcode = 100002
} else {
if (data.scope === 'snsapi_userinfo') {
// 使用 access_token、appid 获取用户信息
userinfo = await utils.request('https://api.weixin.qq.com/sns/userinfo?access_token=' + data.access_token + '&openid=' + data.openid + '&lang=zh_CN')
if (userinfo.errcode) {
errcode = userinfo.errcode
} else {
//nickname的Emoji表情符号处理
userInfo.nickname = encodeURIComponent(userInfo.nickname)
// 用户存表
let insertUserinfo = await utils.insertUser('urer', userinfo)
if (insertUserinfo.insertId) {
// 写redis
let token = utils.md5(userinfo.openid)
let setRedisResult = await this.setUserinfoToRedis(token, userinfo)
if (setRedisResult) {
errcode = setRedisResult
}
} else {
errcode = 103306
}
}
} else {
// 处理 scope = snsapi_base,客户端可以存某个值来判断用户是否第一次微信登录
// 如果不是第一次登录,可以用openid查用户表
userinfo = utils.queryUser('urer', { 'openId': '= ' + data.openid })
let token = utils.md5(userinfo.openid)
if (userinfo) {
let setRedisResult = await this.setUserinfoToRedis(token, userinfo)
if (setRedisResult) {
errcode = setRedisResult
}
} else {
errcode = 113306
}
}
}
} else {
errcode = -5
}
if (errcode) {
this.redirect(res, referer, 'errcode=' + errcode)
} else {
this.redirect(res, referer, 'token=' + token)
}
return null
}
async getUserinfo(req) {
let token = req.query.token
if (token) {
let userinfo = await utils.getUserinfoByRedis(token)
if (userinfo) {
await utils.delRedis(token)
return JSON.parse(userinfo.toString())
} else {
return { errcode: 100001 }
}
} else {
return '参数,token不存在'
}
}
async setUserinfoToRedis(token, userinfo) {
if (userinfo) {
// 写Redis,用来获取用户,2分钟后过期,获取一次后删除;
let setUserinfo = await utils.setRedis(token, JSON.stringify(userinfo))
let expireUserinfo = await utils.expireRedis(token, 2 * 60)
if (!(setUserinfo && expireUserinfo)) {
return 106379
} else {
return null
}
} else {
return 116379
}
}
redirect(res, redirect_uri, queryStr) {
if (queryStr) {
if (redirect_uri.indexOf('?') === -1) {
redirect_uri += '?'
}
if (referer.indexOf('&') !== -1) {
redirect_uri += '&'
}
redirect_uri += queryStr
}
res.writeHead(302, {
Location: redirect_uri
})
res.end()
}
}