最近在学习java相关知识,朋友推荐看一下若依框架,于是在若依框架(前后端分离版)的基础上扩展了一下微信登录功能。
标准的扫码登录需要申请微信开放平台账号,并拥有一个已审核通过的网站应用,即:网站应用微信登录,流程比较麻烦。这里为了省事就基于微信公众号网页授权来进行登录操作,同样也可以学习一下扫码登录的流程。
基于公众号网页授权进行扫码登录我们只需要准备一个公众号(需要认证过的服务号或者直接申请测试公众号)。
因为若依框架已经自带了用户表,所以我们这里的扫码登录要拆分成两部分来开发:
微信绑定的场景是我们需要先登录若依系统,然后打开个人信息页面,在页面上面点击微信绑定按钮弹出二维码,然后手机微信扫码完成绑定。
绑定部分的扫码流程大致如下:
PC 端点击微信绑定按钮后从当前登录token获取到用户的key,基于用户的key拼接链接在前端弹出一个二维码,二维码地址(附带了生成的用户key)是网页授权链接,微信扫码打开后直接进行公众号网页授权,获取 code 后重定向给后端接口来拿到用户 openid 更新到用户表中完成绑定。
基于此流程结合若依框架我们需要开发如下几个接口并修改页面:
因为需要存取用户微信信息,所以修改代码之前我们需要先向 sys_user
用户表追加两个字段:wx_nick_name、openid。
1.在ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/
下面新建WxController.java
用于处理微信相关请求。然后在WxController
中追加微信openid绑定方法:
/**
* 获取openid
*/
@GetMapping("/bind-openid")
public AjaxResult getOpenid(@RequestParam("code") String code, @RequestParam("key") String key) throws IOException
{
AjaxResult ajax = AjaxResult.success();
SysUser u = userService.getOpenid(code);
String openid = u.getOpenid();
LoginUser userCache = redisCache.getCacheObject(CacheConstants.LOGIN_TOKEN_KEY + key);
SysUser user = new SysUser();
user.setUserId(userCache.getUserId());
user.setOpenid(openid);
user.setWxNickName(u.getWxNickName());
userService.updateUserOpenid(user);
ajax.put("openid", openid);
ajax.put("wxnickname", u.getWxNickName());
return ajax;
}
方法里主要完成了微信公众号授权code的接收,并请求微信接口获取到用户openid,从当前用户登录信息redis缓存中拿到用户id然后把微信用户openid更新到用户表完成绑定。
这里为了方便,直接把code重定向给到了接口地址。
2.在ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
中追加微信 code 获取用户 openid 方法:
/**
* 通过code获取用户openid
*
* @param code 微信公众号网页授权码
* @return 用户openid
*/
@Override
public SysUser getOpenid(String code) {
RestTemplate restTemplate = new RestTemplate();
JSONObject jsonData = null;
// 构建获取access_token的URL
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?"
+ "appid=" + appId
+ "&secret=" + secret
+ "&code=" + code
+ "&grant_type=authorization_code";
System.out.println("url: " + url);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
System.out.println("responseEntity: " + responseEntity);
if (responseEntity.getStatusCodeValue() == 200 && responseEntity.getBody() != null) {
jsonData = JSONObject.parseObject(responseEntity.getBody());
}
String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?lang=zh_CN"
+ "&access_token=" + jsonData.getString("access_token")
+ "&openid=" + jsonData.getString("openid");
ResponseEntity<String> responseUserEntity = restTemplate.getForEntity(userInfoUrl, String.class);
if (responseUserEntity.getStatusCodeValue() == 200 && responseUserEntity.getBody() != null) {
JSONObject jsonUserData = JSONObject.parseObject(new String(responseUserEntity.getBody().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
System.out.println("jsonUserData: " + jsonUserData);
SysUser user = new SysUser();
user.setOpenid(jsonUserData.getString("openid"));
user.setWxNickName(jsonUserData.getString("nickname"));
return user;
}
return null;
}
因为这里用到了公众号appid和secret,所以我们要在 ruoyi-admin/src/main/resources/application.yml
配置文件中追加相应配置:
# 公众号配置
wechat:
# 应用ID
appid:
# 应用密钥
secret:
追加配置之后需要在 SysUserServiceImpl
中补充对应私有属性:
@Value("${wechat.appid}")
private String appId;
@Value("${wechat.secret}")
private String secret;
3.在ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
中追加修改用户openid的方法:
/**
* 修改用户openid
*
* @param user 用户信息
* @return 结果
*/
@Override
public int updateUserOpenid(SysUser user)
{
return userMapper.updateUser(user);
}
这里需要我们在 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
中追加对应的方法声明:
/**
* 修改用户信息
*
* @param user 用户信息
* @return 结果
*/
public int updateUser(SysUser user);
并且在 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
中补充更新对应的sql,即向更新用户sql的set部分追加微信openid及昵称的更新判断:
<update id="updateUser" parameterType="SysUser">
...
<if test="openid != null and openid != ''">openid = #{openid},</if>
<if test="wxNickName != null and wxNickName != ''">wx_nick_name = #{wxNickName},</if>
...
</update>
因为新增了微信openid及昵称的信息,所以需要修改一下ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
文件,追加微信昵称及openid属性:
/** 用户微信昵称 */
@Excel(name = "用户微信昵称")
private String wxNickName;
/** openid */
@Excel(name = "openid")
private String openid;
public String getOpenid()
{
return openid;
}
public void setOpenid(String openid)
{
this.openid = openid;
}
public String getWxNickName()
{
return wxNickName;
}
public void setWxNickName(String wxNickName)
{
this.wxNickName = wxNickName;
}
这样我们就完成了微信openid绑定接口的开发。
下面就是要查询微信绑定的信息了。
1.在ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/WxController.java
中追加户uuid查询openid方法:
/**
* 已登录用户uuid查询openid
*/
@GetMapping("/uuid")
public AjaxResult getCode(@RequestParam("uuid") String uuid) throws IOException
{
AjaxResult ajax = AjaxResult.success();
LoginUser userLogin = redisCache.getCacheObject(CacheConstants.LOGIN_TOKEN_KEY + uuid);
SysUser user = userService.selectUserById(userLogin.getUserId());
System.out.println("user-openid: " + user.getOpenid());
System.out.println("user-wxnickname: " + user.getWxNickName());
if (user.getOpenid() != null) {
ajax.put("openid", user.getOpenid());
ajax.put("wxnickname", user.getWxNickName());
}
ajax.put("status", user.getOpenid() != null ? 1: 0);
return ajax;
}
2.在ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
的selectUserVo查询sql中追加openid、微信昵称查询:
<sql id="selectUserVo">
select ...,
u.openid, u.wx_nick_name,
...
from sys_user u
</select>
这样查询到的用户信息里面就会包含绑定的微信信息了。
因为扫码绑定的时候用户在手机上是没有登录的所有要在 ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
中把绑定接口加入到允许列表中:
requests.antMatchers("/login", "/register", "/captchaImage", "/bind-openid").permitAll()
到这里绑定需要开发的接口就修改完了,我们接着来修改页面。
vue-qr
生成,在前端项目根目录npm install vue-qr
即可。ruoyi-ui/src/api/system/user.js
中追加我们上面写好的查询绑定状态接口: export function getUUid(data) {
return request({
url: '/uuid?uuid=' + data.uuid,
method: 'get'
})
}
3.页面修改。修改个人信息页ruoyi-ui/src/views/system/user/profile/userInfo.vue
。
3.1 增加微信绑定按钮及弹窗:
<el-form-item label="微信">
<span class="mr10">{{form.wxnickname || '未绑定'}}</span>
<el-button v-if="form.openid == '' || form.openid == null" :loading="bindloading" size="medium" type="primary" class="btn" @click.stop="wxBind()">绑 定</el-button>
<el-button v-else :loading="bindloading" size="medium" type="primary" class="btn" @click.stop="unBind()">解
绑</el-button>
</el-form-item>
<el-dialog title="绑定微信" custom-class="bind-dialog" class="new-common-dialog" :visible.sync="bindWxVisible" :close-on-click-modal="false" :close-on-press-escape="false" @close="wxLoginClose" width="320px">
<div class="qr-code">
<vue-qr :text="qrUrl" :size="280"></vue-qr>
</div>
</el-dialog>
3.2 导入依赖接口及相关方法:
import {
updateUserProfile,
getUUid
} from "@/api/system/user";
import {
getToken
} from '@/utils/auth'
import vueQr from 'vue-qr'
3.3 引用二维码组件:
components: {
vueQr,
},
3.4 data中新增属性:
timer: null,
bindWxVisible: false,
bindloading: false,
qrUrl: '',
3.5 修改user监听方法,使页面能够回显微信昵称:
user: {
handler(user) {
console.log('user', this.user)
if (user) {
this.form = {
nickName: user.nickName,
wxnickname: user.wxNickName,
phonenumber: user.phonenumber,
email: user.email,
sex: user.sex,
openid: user.openid
};
}
},
immediate: true
}
3.6 增加微信绑定相关方法:
wxBind() {
let token = getToken()
const key = JSON.parse(atob(token.split('.')[1]))['login_user_key'];
const redirect_uri = `http://web-hub.uat.kai12.cn/auth.html?backUrl=${本机IP}:8080/bind-openid?key=${key}`
const codeUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=公众号appid&redirect_uri=${encodeURIComponent(redirect_uri)}&response_type=code&scope=snsapi_userinfo&state=123456#wechat_redirect`
this.qrUrl = codeUrl
console.log(this.qrUrl)
this.bindWxVisible = true
let that = this
this.timer = setInterval(function() {
getUUid({
uuid: key
})
.then((res) => {
console.log(res)
if (res.status === 1) {
that.bindWxVisible = false
that.form.openid = res.openid
that.form.wxnickname = res.wxnickname
that.$message({
type: 'success',
message: '操作成功',
})
clearTimeout(this.timer)
}
})
.catch((err) => {
clearTimeout(that.timer)
})
}, 1000)
},
wxLoginClose() {
this.timer && clearTimeout(this.timer)
},
这里主要是通过获取浏览器缓存的token,从中解析出若依用户的 login_user_key
来实现关联绑定的。
然后整个微信绑定流程就大致完成了。
测试一下:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。