一、准备工作 微信开放平台 注册并申请资质
微信提供介绍的文档
https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
使用项目中新建模块
添加依赖,调用微信提供的接口用到httpClient
org.apache.httpcomponents httpclientcom.alibaba fastjson
模块配置文件添加
#固定,微信提供地址 wx.open.app_id=购买后微信返回的值 wx.open.app_secret=购买后微信返回的值 #回调地址 wx.open.redirect_url=http://购买设置的回调地址/api/user/wx/callback
创建工具类,读取配置文件中内容
@Component //@PropertySource("classpath:application.properties") public class ConstantPropertiesUtil implements InitializingBean { //读取配置文件并赋值 @Value("${wx.open.app_id}") private String appId; @Value("${wx.open.app_secret}") private String appSecret; @Value("${wx.open.redirect_url}") private String redirectUrl; public static String WX_OPEN_APP_ID; public static String WX_OPEN_APP_SECRET; public static String WX_OPEN_REDIRECT_URL; @Override public void afterPropertiesSet() throws Exception { WX_OPEN_APP_ID = appId; WX_OPEN_APP_SECRET = appSecret; WX_OPEN_REDIRECT_URL = redirectUrl; } }
控制层
@Controller @RequestMapping("/api/user/wx") public class WeixinApiController { //返回登陆二维码参数 @GetMapping("getLoginParam") @ResponseBody public R genQrConnect(HttpSession session) throws UnsupportedEncodingException { String redirectUri = URLEncoder.encode(ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL, "utf-8"); Mapmap = new HashMap<>(); map.put("appid", ConstantPropertiesUtil.WX_OPEN_APP_ID); map.put("redirectUri", redirectUri); map.put("scope", "snsapi_login"); map.put("state", System.currentTimeMillis() + "");//System.currentTimeM return R.ok().data(map); } }
vue中创建api/wx.js
import request from '@/utils/request' const api_name = `/api/user/wx` export default { getLoginParam() { return request({ url: `${api_name}/getLoginParam`, method: `get` }) } }
修改layouts/myheader.vue文件,添加微信二维码登录逻辑
import wxApi from '@/api/yygh/wx' 引入js文件
使用dom方式引入微信提供的js文件
mounted() { //页面渲染之后执行 // 注册全局登录事件对象 window.loginEvent = new Vue(); // 监听登录事件 loginEvent.$on('loginDialogEvent', function () { document.getElementById("loginDialog").click(); }) // 触发事件,显示登录层:loginEvent.$emit('loginDialogEvent') //引入微信二维码需要js文件 const script = document.createElement("script") script.type = 'text/javascript' script.src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js" document.body.appendChild(script) },
页面绑定点击事件
weixinLogin() { this.dialogAtrr.showLoginType = 'weixin' //调用二维码生成接口,得到返回数据 wxApi.getLoginParam().then(response => { var obj = new WxLogin({ self_redirect:true, id:"weixinLogin", appid: response.data.appid, // 公众号appid wx******* scope: response.data.scope, // 网页默认即可 redirect_uri: response.data.redirectUri, // 授权成功后回调的url state: response.data.state, // 可设置为简单的随机数加session用来校验 style: 'black', // 提供"black"、"white"可选。二维码的样式 href: '' // 外部css文件url,需要https }); }) },
此时启动即可访问到二维码
扫码后流程
扫码后-同意-微信回应(调用微信管理后台配置回调地址)-返回code:临时票据,state:生成二维码传过去的值
拿着code值与id请求微信接口地址,微信再返回opeid与access_token,接受数据后在请求-得到扫码人信息
控制层添加回调方法
@GetMapping("callback") public String callback(String code,String state){ try { //拿着code和appid请求微信接口 System.out.println("code:"+code); //第二步 拿着code和微信id和秘钥,请求微信固定地址 ,得到两个值 //使用code和appid以及appscrect换取access_token // %s 占位符 StringBuffer baseAccessTokenUrl = new StringBuffer() .append("https://api.weixin.qq.com/sns/oauth2/access_token") .append("?appid=%s") .append("&secret=%s") .append("&code=%s") .append("&grant_type=authorization_code"); //像占位符中传参数 String accessTokenUrl = String.format(baseAccessTokenUrl.toString(), ConstantPropertiesUtil.WX_OPEN_APP_ID, ConstantPropertiesUtil.WX_OPEN_APP_SECRET, code); //使用httpClient发送请求 String result = HttpClientUtils.get(accessTokenUrl); //拿着code值与id请求微信接口地址 JSonObject jsonObject = JSONObject.parseObject(result); String access_token = jsonObject.getString("access_token"); String openid = jsonObject.getString("openid"); //判断数据库是否存在openid UserInfo userInfo = userInfoService.findUserByOpenid(openid); if (userInfo == null){ //opeid与access_token请求获取扫码人信息 String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +"?access_token=%s" + "&openid=%s"; String userInfoUrl = String.format(baseUserInfoUrl, access_token,openid); String userResult = HttpClientUtils.get(userInfoUrl); //获取扫码人昵称 JSonObject userJson = JSONObject.parseObject(userResult); String nickname = userJson.getString("nickname"); //加入数据库 userInfo = new UserInfo(); userInfo.setNickName(nickname); userInfo.setOpenid(openid); userInfo.setStatus(1); userInfoService.save(userInfo); } //返回登陆需要的数据 Mapmap = new HashMap<>(); String name = userInfo.getName(); if(StringUtils.isEmpty(name)) { name = userInfo.getNickName(); } if(StringUtils.isEmpty(name)) { name = userInfo.getPhone(); } map.put("name", name); //判断userInfo是否有手机号,如果手机号为空,返回openid //如果手机号不为空,返回openid值是空字符串 //前端判断:如果openid不为空,绑定手机号,如果openid为空,不需要绑定手机号 if(StringUtils.isEmpty(userInfo.getPhone())) { map.put("openid", userInfo.getOpenid()); }else { map.put("openid",""); } //使用jwt生成token字符串 String token = JwtHelper.createToken(userInfo.getId(), name); map.put("token", token); //跳转到前端中转页面 return "redirect:http://localhost:3000/weixin/callback?token=" +map.get("token")+"&openid="+map.get("openid") +"&name="+URLEncoder.encode(map.get("name"),"utf-8"); } catch (Exception e) { e.printStackTrace(); return null; } }
vue中创建/pages/weixin/callback.vue 作为中转页面
在myheader.vue添加方法
methods: { loginCallback(name, token, openid) { // 没绑定手机号跳转到绑定 有手机号登陆 if(openid != '') { this.userInfo.openid = openid this.showLogin() } else { this.setcookies(name, token) } },
此时这个方法为私有的,页面调不到,在mounted() 中添加
// 微信登录回调处理 let self = this; window["loginCallback"] = (name,token, openid) => { self.loginCallback(name, token, openid); }
绑定手机号加入数据库,修改UserInfoServiceImpl
@Override public Maplogin(LoginVo loginVo) { String phone = loginVo.getPhone(); String code = loginVo.getCode(); //校验参数 if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)) { throw new YyghException(20001,"数据为空"); } //TODO 校验校验验证码 String redisCode = (String) redisTemplate.opsForValue().get(phone); if (!code.equals(redisCode)){ throw new YyghException(20001,"校验是失败"); } //判断手机验证码登陆还是微信绑定手机号 //获取页面传来的openid值 String openid = loginVo.getOpenid(); //判断openid不为空 绑定手机号 if (StringUtils.isEmpty(openid)){ //手机号已被使用 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("phone", phone); //获取会员 UserInfo userInfo = baseMapper.selectOne(queryWrapper); //注册 if(null == userInfo) { userInfo = new UserInfo(); userInfo.setName(""); userInfo.setPhone(phone); userInfo.setStatus(1); this.save(userInfo); } //校验是否被禁用 if(userInfo.getStatus() == 0) { throw new YyghException(20001,"用户已经禁用"); } //返回页面显示名称 登陆以后,若名称为空就在页面显示手机号 Map map = new HashMap<>(); String name = userInfo.getName(); if(StringUtils.isEmpty(name)) { name = userInfo.getNickName(); } if(StringUtils.isEmpty(name)) { name = userInfo.getPhone(); } map.put("name", name); //生成token String token = JwtHelper.createToken(userInfo.getId(), name); map.put("token", token); return map; }else { //openid不为空 绑定手机号 //根据手机号查询数据库中信息,若有先删除 baseMapper.delete(new QueryWrapper ().eq("phone",phone)); //根据openid查询微信信息 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("openid",openid); UserInfo userInfo = baseMapper.selectOne(wrapper); //设置绑定手机号 userInfo.setPhone(phone); //修改手机号 baseMapper.updateById(userInfo); //校验是否被禁用 if(userInfo.getStatus() == 0) { throw new YyghException(20001,"用户已经禁用"); } //返回页面显示名称 登陆以后,若名称为空就在页面显示手机号 Map map = new HashMap<>(); String name = userInfo.getName(); if(StringUtils.isEmpty(name)) { name = userInfo.getNickName(); } if(StringUtils.isEmpty(name)) { name = userInfo.getPhone(); } map.put("name", name); //生成token String token = JwtHelper.createToken(userInfo.getId(), name); map.put("token", token); return map; } }
流程总结:
扫码后回调方法,在方法中按微信规则,获取数据,若没绑定手机号自定义规则传到前端,前端跳转到中转页面,通过固定路由跳转到绑定页面,调用绑定手机号方法
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)