这里说一下先后端的思路,页面加载时声明一个变量
state
='时间戳+6位随机数', 前端路径生成二维码, 其中有个state
参数须要咱们传递,这个参数你传什么,微信回调的时候就会给你返回什么。 咱们用以前生成那个state,当用户点击微信登陆的按钮,咱们就经过以state值为key和后端进行websocket链接,同时弹出二维码页面。 state对前端来讲就至关于一个令牌,告诉后端是谁在使用微信登陆。目的在于,当后台收到回调的时候,能准确的把数据返回当前扫码的用户, 后台在微信回调的时候能拿到code
的值和state
的值,经过code
去拿access_token
和openid
, 经过这两个值去请求微信用户最新信息, 后端定义好返回的状态值表明啥,无非两种状态码:1.已经绑定:取出user
信息, 经过websocket返回给前端,2.没绑定:返回微信帐户的openid和头像昵称。 前端收到后端发送的websocket信息,判断微信绑定状态,若是绑定路由跳转到登陆完成页面,若是未绑定,跳转到绑定或注册页面。javascript
前端先设置好生成二维码的路径,前端
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";
复制代码
参数名 | 备注 |
---|---|
appid | 这个就是申请微信登陆应用的appid |
redirect_uri | 微信的回调地址,记得这里要url转码 |
state | 这个是微信给咱们本身传递的参数,无论你传的是啥,都会在回调中给你返回回来 |
用户点击微信登陆页面,和后端进行websocket链接,链接的key就是咱们生产二维码链接中的state
java
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 并进行相应的操做
})
复制代码
而后再弹出二维码页面(居中显示)git
//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"
);
}
复制代码
github.com/niezhiliang…github
这边是websocket的代码web
@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();
}
}
}
}
复制代码
@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";
}
复制代码
这边是微信回调代码spring
/** * 微信扫码回调 * @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();
}
}
复制代码