這裏說一下先後端的思路,頁面加載時聲明一個變量
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();
}
}
複製代碼