这里说一下前后端的思路,页面加载时声明一个变量state ='时间戳+6位随机数', 前端路径生成二维码, 其中有个state 参数需要我们传递,这个参数你传什么,微信回调的时候就会给你返回什么。 我们用之前生成那个state,当用户点击微信登录的按钮,我们就通过以state值为key和后端进行websocket连接,同时弹出二维码页面。 state对前端来说就相当于一个令牌,告诉后端是谁在使用微信登录。目的在于,当后台收到回调的时候,能准确的把数据返回当前扫码的用户, 后台在微信回调的时候能拿到code 的值和state 的值,通过code 去拿access_token 和openid , 通过这两个值去请求微信用户最新信息, 后端定义好返回的状态值代表啥,无非两种状态码:1.已经绑定:取出user 信息, 通过websocket返回给前端,2.没绑定:返回微信账户的openid和头像昵称。 前端收到后端发送的websocket信息,判断微信绑定状态,如果绑定路由跳转到登录完成页面,如果未绑定,跳转到绑定或注册页面。
第一步
前端先设置好生成二维码的路径,
this.url = "https://open.weixin.qq.com/connect/qrconnect?appid=" + this.appid + "&redirect_uri=" + this.redirect_uri + "&response_type=code&scope=snsapi_login&state=" + this.state + "#wechat_redirect"; 复制代码
参数解释(这里直解释需要修改的参数)
第二步
用户点击微信登录页面,和后端进行websocket连接,连接的key就是我们生产二维码连接中的state
let wsname = "ws://www.niezhiliang.com:8086/socketServer/" + this.state; this.ws = new WebSocket(wsname); //连接成功触发 this.ws.onopen = function(evt) { }; //这个是接收后台发送信息的方法 this.ws.onmessage = function(evt) { var data = JSON.parse(evt.data); console.log(data) //在这里判断后台给的状态是1还是2 并进行相应的操作 }) 复制代码
然后再弹出二维码页面(居中显示)
//this.url=我们在页面加载的时候拼接好的 WxLogin() { this.itop = (window.screen.availHeight - 500) / 2; //获得窗口的水平位置 this.ileft = (window.screen.availWidth - 400) / 2; this.w = window.open( this.url, "newwindow", "height=500, width=400, top=" + this.itop + ", left = " + this.ileft + ", toolbar=no, menubar=no,scrollbars=no, resizable=no,location=no, status=no" ); } 复制代码
后端Java实现(websocket就不解释啦,如果不懂可以去看我的另一个项目)
github.com/niezhiliang…
第一步
这边是websocket的代码
- 配置websocket连接服务
@ServerEndpoint(value = "/socketServer/{userid}") @Component public class SocketServer { private Session session; private static Map<String,Session> sessionPool = new HashMap<String,Session>(); private static Map<String,String> sessionIds = new HashMap<String,String>(); /** * 用户连接时触发 * @param session * @param userid */ @OnOpen public void open(Session session,@PathParam(value="userid")String userid){ this.session = session; sessionPool.put(userid, session); sessionIds.put(session.getId(), userid); } /** * 收到信息时触发 * @param message */ @OnMessage public void onMessage(String message){ System.out.println("当前发送人sessionid为"+session.getId()+"发送内容为"+message); } /** * 连接关闭触发 */ @OnClose public void onClose(){ sessionPool.remove(sessionIds.get(session.getId())); sessionIds.remove(session.getId()); } /** * 发生错误时触发 * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { error.printStackTrace(); } /** *信息发送的方法 * @param message * @param userId */ public static void sendMessage(String message,String userId){ Session s = sessionPool.get(userId); if(s!=null){ try { s.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } } } 复制代码
- 提供给前端发送信息的api
@RequestMapping(value = "/sendpost") public String sendPost(@RequestBody Params params) { if (params.getJson() == null || params.getUserid() == null) { return "error"; } logger.info(params.getJson()+"-----------"+params.getUserid()); SocketServer.sendMessage(params.getJson(),params.getUserid()); return "success"; } 复制代码
第二步
这边是微信回调代码
/** * 微信扫码回调 * @return */ @RequestMapping(value = "/callback") public void callBack(Device device) { String code = request.getParameter("code"); String state = request.getParameter("state"); RespInfo respInfo = new RespInfo(); respInfo.setStatus(InfoCode.ERROR); if (code != null) { StringBuffer url = new StringBuffer(); /*********获取token************/ url.append(request_url) .append("appid=") .append(appid) .append("&secret=") .append(secret) .append("&code=") .append(code) .append("&grant_type=") .append(grant_type); logger.info(url.toString()); //调用微信查询用户基本信息的api方法 JSONObject jsonObject = JSON.parseObject(HttpUtil.getResult(url.toString())); //拿到openid和请求微信api使用的token String openid =jsonObject.get("openid").toString(); String token = jsonObject.get("access_token").toString(); /*********获取userinfo************/ url = new StringBuffer(); url.append(userinfo_url) .append("access_token=") .append(token) .append("&openid=") .append(openid); logger.info(url.toString()); //通过上面拿到的token和openid获取用户的基本信息 String result = HttpUtil.getResult(url.toString()); WeixinInfo weixinInfo = JSON.parseObject(result,WeixinInfo.class); if (weixinInfo != null) { //这个方法是为了去除微信昵称的特殊符号,为了避免保存数据库操作报异常我把所有的昵称表情都替换成了* weixinInfo.setNickname(filterEmoji(weixinInfo.getNickname())); //插入数据库操作 weiXinService.insertOrUpdateSelective(weixinInfo); } //通过openid去找用户是否绑定 User user = userService.getByOpenId(openid); if (user == null) {//说明该微信未绑定任何账号 respInfo.setStatus(InfoCode.INVALID_TOKEN); respInfo.setMessage("请先注册再进行微信绑登录操作"); Map<String,Object> map = new HashMap<String,Object>(); map.put("openid",openid); map.put("headimgurl",weixinInfo.getHeadimgurl()); map.put("nickname",weixinInfo.getNickname()); respInfo.setContent(map); } else {//这里是表示该微信已经绑定了用户账号,直接返回用户登录信息就好 respInfo.setStatus(InfoCode.SUCCESS); respInfo.setContent(user); } } String json = JSON.toJSONString(respInfo); /************websocket将数据响应给前端**************/ Map map = new HashMap(); map.put("userid",state); map.put("json",json); String params = JSON.toJSONString(map); try { //这里是将结果通过websocket返回给前端 System.out.println(HttpUtil. doPost(“http://www.niezhiliang.com:8086/websocket/sendpost”,params)); } catch (Exception e) { e.printStackTrace(); } } 复制代码
本文暂时没有评论,来添加一个吧(●'◡'●)