先看一下官方文档,写的还算清晰,当然实际开发中,还是会踩到不少坑的。
服务端是node+ts开发的,其他语言基本也是大同小异。前端是vue3.0。
第一步,去申请一个微信公众平台接口测试帐号。
有了测试账号就方便很多,回调地址可以使用IP形式,不强迫使用域名,如果不用开发模式,那么还要本地做一个域名映射其实也挺麻烦,我个人选择测试账号。
然后添加一个网页授权获取用户基本信息,把本地的IP写上即可。
我这里填写的是192.168.1.4:7789,记住这里不要填写127.0.0.1这种本地IP,要通过ipconfig命令获取的本地的内网IP。
第二步,获取code
必须是让用户浏览器跳转到https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect这个页面,然后此页面再会跳转到redirect_uri指定的url,并且会携带code和state两个query参数。
注意:这里必须是页面跳转,前端跳转可以用js的location.href方法,后端跳转可以用res.redirect方法。
这里前端和后端跳转我都尝试过,后端跳转么,之后一系列的操作都是后端来执行,前端会轻松很多,以下一行代码搞定。
<a href="http://192.168.1.4:12159/wx/serverauth/member">提交本地</a>
但是有一个问题,最终后端还是要再跳转到前端的页面,那么此时如何把用户信息输送给前端,是一个麻烦事,不能直接通过query参数传递吧,那太不安全,可能还要通过各种加密解密来实现了。
我这里也贴一下,后端跳转代码,也非常简单,也就是上面serverauth/member这个url会跳转到以下后端地址
/**
* 请求snsapi_userinfo作用域的路由
*/
const routerGetMember = async (req, res) => {
const callback = encodeURIComponent(`http://191.168.1.4/wx/serverauth/callbackbase`)
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?
appid=${global.CONFIG.WX.AppID}&redirect_uri=
${callback}&response_type=code
&scope=snsapi_userinfo&state=STATE#wechat_redirect`
res.redirect(url)
}
我最终使用的还是前端跳转,代码如下,button添加事件。
<button @click='authUserInfo'>获取授权</button>
ts代码如下
const callback = 'http://192.168.1.4:7789/wx/exam'
const authUserInfo = () => {
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?
appid=APPID&redirect_uri=${callback}&response_type=code
&scope=snsapi_userinfo&state=STATE#wechat_redirect`
location.href = url
}
这里不用担心appid泄露的问题,这本身就不是敏感信息,就好比用户名一样,这里请求微信服务器后,会再跳转到本身的页面,callback就是当前页面的路由。一旦页面跳转后,微信就会弹出一个请求用户授权窗口,用户同意后,就会跳回redirect_uri里的url。
之后在onMounted方法中判断,url中是否有code参数,有的话则发送请求到后端,有后端返回用户信息。
onMounted(async () => {
if (route.query.code) {
const result = await AJRequest(route.query.code as string)
// 获得用户数据,距离逻辑后端实现
console.log(result)
}
})
AJRequest方法如下
/**
*
* @param code 请求token的code
* @returns
*/
export const AJReques = (code: string => {
return ajax<TUserInfoMember>({
method: 'POST',
url: '/wx/clientauth/memberuserinfo',
data: { code }
})
}
/wx/clientauth/memberuserinfo是后端实现的方法,下方会讲。
第三步,后端获取access_token
定义一个函数,后端获取到code后,发送使用axios发送post请求获取access_token
/**
* 根据code请求用户token结果
* @param code redirect_uri页面中query中的参数code
* @returns
*/
export const fnRequesToken = async (code: string) => {
const tokenURL = `https://api.weixin.qq.com/sns/oauth2/access_token?a
ppid=${APPID}&secret=${AppSecret}
&code=${code}
&grant_type=authorization_code`
const tokenInfo = await axios.post(tokenURL)
return tokenInfo.data as ITokenUserInfo
}
第四步,通过access_token获取用户信息
第二步中,请求后端的地址,是一个node路由,先要通过code获取的access_token,代码如下:
/**
* snsapi_userinfo作用域获取的code,
* @param req
* @param res
* @param next
*/
const getMemberUserInfo = async (req, res) => {
try {
const code = req.body.code
const { access_token, openid} = await fnRequestToken(code as string)
const userURL = `https://api.weixin.qq.com/sns/userinfo
?access_token=${access_token}
&openid=${openid}&lang=zh_CN`
const wxUser: IWXUserInfo = (await axios.post(userURL)).data
// wxUser就是微信用户对象了
// 实际业务中会根据情况进行数据库操作
res.send(wxUser)
}
catch (e) {
return res.send(e)
}
}
大致的流程就是如此,实际开发中,需要根据需求灵活变通,以上只是最基本的实现逻辑。
下一节我讲讲,如何通过请求snsapi_base作用域,让用户无感授权,避免每次用户授权都要弹出窗口,非常不友好。