https://blog.csdn.net/qq_42851002/article/details/81327770javascript
場景:用戶掃描微信公衆號的二維碼,關注後自動登陸網站,若已關注則直接登陸。html
邏輯:
1.系統生成帶參數(此參數自定義爲惟一值)的臨時二維碼(微信公衆平臺有提供該接口,可查看一下開發文檔);
2.用戶使用微信掃描該二維碼,關注後微信服務器會將數據(自定義參數、openid…)返回到咱們的服務器;
3.咱們服務器將接收到的openid再次向微信服務器發起請求,獲取該用戶的信息(暱稱、頭像、地域、unionid(若綁定了微信開放平臺,則有此參數));
4.咱們將返回的用戶信息存儲到數據庫,用做於登陸。java
準備工做:登陸微信公衆平臺,在基本配置下,查看appid和設置appsecret、回調URL、token,小編這裏使用的是測試帳號
jquery
package com.lrfun.web.controller; import java.io.InputStream; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import com.google.gson.Gson; @Controller public class WechatController { //Lrfun測試公衆號 private static final String app_id = "xxx"; private static final String app_secret = "xxx"; private static final Gson gson = new Gson(); /*** * httpClient-Get請求 * @param url 請求地址 * @return * @throws Exception */ public static Map<String, Object> httpClientGet(String url) throws Exception { HttpClient client = new HttpClient(); client.getParams().setContentCharset("UTF-8"); GetMethod httpGet = new GetMethod(url); try { client.executeMethod(httpGet); String response = httpGet.getResponseBodyAsString(); Map<String, Object> map = gson.fromJson(response, Map.class); return map; } catch (Exception e) { throw e; } finally { httpGet.releaseConnection(); } } /*** * httpClient-Post請求 * @param url 請求地址 * @param params post參數 * @return * @throws Exception */ public static Map<String, Object> httpClientPost(String url, String params) throws Exception { HttpClient client = new HttpClient(); client.getParams().setContentCharset("UTF-8"); PostMethod httpPost = new PostMethod(url); try { RequestEntity requestEntity = new ByteArrayRequestEntity(params.getBytes("utf-8")); httpPost.setRequestEntity(requestEntity); client.executeMethod(httpPost); String response = httpPost.getResponseBodyAsString(); Map<String, Object> map = gson.fromJson(response, Map.class); return map; } catch (Exception e) { throw new RuntimeException(e); } finally { httpPost.releaseConnection(); } } // 獲取access_tocken private String getAccessToken() throws Exception{ String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + app_id + "&secret=" + app_secret; Map<String, Object> accessTokenMap = WechatController.httpClientGet(url); System.out.println(accessTokenMap); return accessTokenMap.get("access_token").toString(); } // 經過openid獲取用戶信息 private Map<String, Object> getUserInfoByOpenid(String openid) throws Exception { String access_tocken = getAccessToken(); String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + access_tocken + "&openid=" + openid; Map<String, Object> map = httpClientGet(url); return map; } // 生成帶參數的二維碼,掃描關注微信公衆號,自動登陸網站 @RequestMapping(value = "/wechat/mpLogin.html") public ModelAndView wechatMpLogin(ModelMap modelMap) throws Exception { String access_token = getAccessToken(); String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + access_token; String scene_str = "lrfun.com." + new Date().getTime(); String params = "{\"expire_seconds\":600, \"action_name\":\"QR_STR_SCENE\", \"action_info\":{\"scene\":{\"scene_str\":\"" + scene_str + "\"}}}"; Map<String, Object> resultMap = httpClientPost(url, params); if (resultMap.get("ticket") != null) { String qrcodeUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + resultMap.get("ticket"); modelMap.put("qrcodeUrl", qrcodeUrl); } modelMap.put("scene_str", scene_str); return new ModelAndView("/test/wechatMpLogin.vm", modelMap); } // 檢測登陸 @RequestMapping("/wechat/checkLogin.html") public @ResponseBody Map<String, Object> wechatMpCheckLogin(String scene_str){ // 根據scene_str查詢數據庫,獲取對應記錄 // SELECT * FROM wechat_user_info WHERE event_key='scene_str'; Map<String, Object> returnMap = new HashMap<String, Object>(); if (true) { returnMap.put("result", "true"); } else { returnMap.put("result", "false"); } return returnMap; } // 回調函數 @RequestMapping(value = "/wechat/callback.html") public void callback(HttpServletRequest httpServletRequest) throws Exception { Map<String, String> callbackMap = xmlToMap(httpServletRequest); //獲取回調信息 //下面是返回的xml //<xml><ToUserName><![CDATA[gh_f6b4da984c87]]></ToUserName> //微信公衆號的微信號 //<FromUserName><![CDATA[oJxRO1Y2NgWJ9gMDyE3LwAYUNdAs]]></FromUserName> //openid用於獲取用戶信息,作登陸使用 //<CreateTime>1531130986</CreateTime> //回調時間 //<MsgType><![CDATA[event]]></MsgType> //<Event><![CDATA[SCAN]]></Event> //<EventKey><![CDATA[lrfun.com.UxJkWC1531967386903]]></EventKey> //上面自定義的參數(scene_str) //<Ticket><![CDATA[gQF57zwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyY2ljbjB3RGtkZWwxbExLY3hyMVMAAgTvM0NbAwSAOgkA]]></Ticket> //換取二維碼的ticket //</xml> if (callbackMap != null && callbackMap.get("FromUserName").toString() != null) { // 經過openid獲取用戶信息 Map<String, Object> wechatUserInfoMap = getUserInfoByOpenid(callbackMap.get("FromUserName")); // 將數據寫入到數據庫中,前面自定義的參數(scene_str)也需記錄到數據庫中,後面用於檢測匹配登陸 // INSERT INTO wechat_user_info......(數據庫操做) } } // xml轉爲map private Map<String, String> xmlToMap(HttpServletRequest httpServletRequest) { Map<String, String> map = new HashMap<String, String>(); try { InputStream inputStream = httpServletRequest.getInputStream(); SAXReader reader = new SAXReader(); // 讀取輸入流 org.dom4j.Document document = reader.read(inputStream); Element root = document.getRootElement(); // 獲得xml根元素 List<Element> elementList = root.elements(); // 獲得根元素的全部子節點 // 遍歷全部子節點 for (Element e : elementList) map.put(e.getName(), e.getText()); // 釋放資源 inputStream.close(); inputStream = null; return map; } catch (Exception e) { e.getMessage(); } return null; } }
靜態文件wechatMpLogin.vm: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>微信掃碼,關注並登陸</title> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> <style>a{outline:0}h1,h2,h3,h4,h5,h6,p{margin:0;font-weight:400}a img,fieldset{border:0}body{font-family:"Microsoft Yahei";color:#fff;background:0 0}.impowerBox{display:inline-block;vertical-align:middle;line-height:1.6;position:relative;width:100%;z-index:1;text-align:center}.impowerBox .title{text-align:center;font-size:20px}.impowerBox .qrcode{width:280px;height:280px;margin-top:15px;border:1px solid #E2E2E2}.impowerBox .info{width:280px;margin:0 auto}.impowerBox .status{padding:7px 14px;text-align:left}.impowerBox .status.normal{margin-top:15px;background-color:#232323;border-radius:100px;-moz-border-radius:100px;-webkit-border-radius:100px;box-shadow:inset 0 5px 10px -5px #191919,0 1px 0 0 #444;-moz-box-shadow:inset 0 5px 10px -5px #191919,0 1px 0 0 #444;-webkit-box-shadow:inset 0 5px 10px -5px #191919,0 1px 0 0 #444}.impowerBox .status.status_browser{text-align:center}.impowerBox .status p{font-size:13px}</style> <script type="text/javascript" src="http://www.lrfun.com/statics/fun2/js/jquery.min.js"></script> </head> <body style="background-color: rgb(51, 51, 51); padding: 50px;"> <div class="main impowerBox"> <div class="loginPanel normalPanel"> <div class="title">微信登陸</div> <div class="waiting panelContent"> <div class="wrp_code"> <img class="qrcode lightBorder" src="$!{qrcodeUrl}"/> </div> <div class="info"> <div class="status status_browser js_status normal" id="wx_default_tip"> <p>請使用微信掃描二維碼登陸</p> <p>「lrfun.com」</p> </div> </div> </div> </div> </div> <script type="text/javascript"> $(document).ready(function () { setInterval("wechatCheckLogin()", 2000); }); function wechatCheckLogin(){ $.post("/wechat/checkLogin.html", {scene_str:"$!{scene_str}"}, function(data){ if(data.result == "true"){ alert("成功,登陸跳轉!"); } else { alert("失敗!"); } }, "JSON"); } </script> </body> </html>