網站實現掃描二維碼關注微信公衆號,自動登錄網站並獲取其信息

需求

     網站實現掃描二維碼關注微信公衆號,若是已經關注公衆號就自動登錄網站並獲取其微信暱稱,頭像等信息,若是用戶未關注就等用戶關注公衆號後自動登錄網站html

     --若是用戶已關注公衆號,網站端直接自動登錄,若是沒有關注,就等用戶關注公衆號以後網站端自動登錄ajax

     (目前已經完成了這個功能,示例網址:http://www.bid-data.com/ 愛招標——免費實時標訊推送平臺,爲企業負責人及商務人員即時掌控招標動態、中標檢索、競爭對手中標項目分析等服務平臺。)redis

   作微信掃碼登錄,生成二維碼必須是微信公衆號中綁定的域這個域名,網站生成不了二維碼(網站與微信服務器不是同一個域名) ,而是調用微信系統的接口獲取二維碼,用戶掃碼後也是請求微信服務器 json

   

實現思路

   1,微信的系統,提供生成帶參數的二維碼的接口,這個參數就是惟一值(場景值)
   2,網站調用微信系統,獲取生成的二維碼圖片
   3,用戶掃碼會直接調用微信服務器,將用戶訪問微信服務器的信息記錄到redis,key就是惟一值(場景值)
   4,網站端作輪訓去查詢redis中是否有這個惟一值的數據,若是有就獲取用戶信息登陸,沒有就五秒一次輪訓,登陸後就不在作輪訓(從二維碼彈出以後開始作輪訓,關閉二維碼後中止輪訓)
   5,這裏的惟一值是能夠本身定義的,我用的是截取了幾位的時間戳 
 

實現步驟

(1)微信端:寫一個獲取帶參數的臨時二維碼接口。
  // 臨時二維碼 
    private final static String QR_SCENE = "QR_SCENE";  
    // 永久二維碼  
    private final static String QR_LIMIT_SCENE = "QR_LIMIT_SCENE";  
    // 永久二維碼(字符串)  
    private final static String QR_LIMIT_STR_SCENE = "QR_LIMIT_STR_SCENE";   
    // 建立二維碼  
    private String create_ticket_path = "https://api.weixin.qq.com/cgi-bin/qrcode/create";  
    // 經過ticket換取二維碼  
    private String showqrcode_path = "https://mp.weixin.qq.com/cgi-bin/showqrcode";  
    
    @RequestMapping("getQrcode")
    public @ResponseBody String getQrcode(@RequestParam(value = "sceneId")int sceneId) throws Exception{
    
        
        String ticket = createTempTicket(tokenService.getToken(),"2592000",sceneId);
        LOGGER.info("get wechat qrcode  ==> start");
        LOGGER.info("sceneId :"+sceneId);
        LOGGER.info("ticket :"+ticket);
        LOGGER.info("get wechat qrcode  ==> end");
        return ticket;
    }
    /** 
     * 建立臨時帶參數二維碼 
     * @param accessToken 
     * @expireSeconds 該二維碼有效時間,以秒爲單位。 最大不超過2592000(即30天),此字段若是不填,則默認有效期爲30秒。 
     * @param sceneId 場景Id 
     * @return 
     */  
    public String createTempTicket(String accessToken, String expireSeconds, int sceneId) {  
      
        TreeMap<String,String> params = new TreeMap<String,String>();  
        params.put("access_token", accessToken);  
        Map<String,Integer> intMap = new HashMap<String,Integer>();
        intMap.put("scene_id",sceneId);  
        Map<String,Map<String,Integer>> mapMap = new HashMap<String,Map<String,Integer>>();  
        mapMap.put("scene", intMap);  
        
        Map<String,Object> paramsMap = new HashMap<String,Object>();  
        paramsMap.put("expire_seconds", expireSeconds);  
        paramsMap.put("action_name", QR_SCENE);  
        paramsMap.put("action_info", mapMap);  
        String data = new Gson().toJson(paramsMap);  
        String tse = HttpRequestUtil.HttpsDefaultExecute(HttpRequestUtil.POST_METHOD,create_ticket_path,params,data);  
        
        JSONObject jsonObject = JSONObject.fromObject(tse);
        LOGGER.info("ticket :"+jsonObject.getString("ticket"));

     return showqrcode_path+"?ticket="+jsonObject.getString("ticket");
}
accessToken就是調用微信接口的憑證token

(2)網站端:網站寫一個調用微信生成二維碼的接口api

    @RequestMapping("getQrcode")
    public @ResponseBody Hashtable getQrcode(int sceneId){
        
        System.out.println(sceneId);
        
        Hashtable param = new Hashtable();
        param.put("sceneId", sceneId);

        String qrcodePath = HttpUtil.postRequest(Constant.getValue("get_qrcode"), param);

        System.out.println(" qrcodePath ==> "+qrcodePath);
        param.put("path", qrcodePath);
        return param;
    }

直接使用http調用接口就行,Constant.getValue("get_qrcode")這個就是微信提供二維碼接口的url服務器

(3)微信端:微信處理用戶請求(這個地址是微信公衆號填的那個地址,微信服務器會將全部用戶請求轉發到這個地址)微信

       // 事件推送
            else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
                // 事件類型
                String eventType = requestMap.get("Event");
                // 關注
                if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
                  //獲取用戶信息
                    String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID";
                    requestUrl = requestUrl.replace("ACCESS_TOKEN", tokenService.getToken())
                            .replace("OPENID", fromUserName);
                    JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET",null);
                    String nickname = jsonObject.getString("nickname");
                    String address = jsonObject.getString("country")+"-"+jsonObject.getString("province")+"-"+jsonObject.getString("city");
                    String headimgurl = jsonObject.getString("headimgurl");

            //將用戶信息存入redis,key爲惟一值(場景值) Hashtable params
= new Hashtable(); params.put("phoneIme", fromUserName); params.put("state", 1); params.put("location", address); params.put("realName", nickname); params.put("nickname", nickname); params.put("headimgurl", headimgurl); if(StringUtils.isNotBlank(eventKey)){ redisCacheTool.setDataToRedis(eventKey.replace("qrscene_", ""), 3600, params); System.out.println("qrcode redis key ==> "+eventKey.replace("qrscene_", "")); params.put("equipmentType", eventKey); }
            //入庫 HttpUtil.postRequest(Constant.getValue(
"UPDATE_USER"), params); } // 取消關注 else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) { // TODO 取消訂閱後用戶不會再收到公衆帳號發送的消息,所以不須要回復 Hashtable params = new Hashtable(); params.put("phoneIme", fromUserName); params.put("state", 0); HttpUtil.postRequest(Constant.getValue("UPDATE_USER_ANS"), params); } // 掃描帶參數二維碼 else if (eventType.toLowerCase().equals(MessageUtil.EVENT_TYPE_SCAN)) { // TODO 處理掃描帶參數二維碼事件 if(StringUtils.isNotBlank(eventKey)){ String requestUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID"; //獲取用戶信息 requestUrl = requestUrl.replace("ACCESS_TOKEN", tokenService.getToken()) .replace("OPENID", fromUserName); JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET",null); String nickname = jsonObject.getString("nickname"); String address = jsonObject.getString("country")+"-"+jsonObject.getString("province")+"-"+jsonObject.getString("city"); String headimgurl = jsonObject.getString("headimgurl");
              //將用戶信息存入redis,key爲惟一值(場景值) Hashtable params
= new Hashtable(); params.put("nickname", nickname); params.put("headimgurl", headimgurl); params.put("location", address); redisCacheTool.setDataToRedis(eventKey, 3600, params); System.out.println("qrcode redis key ==> "+eventKey); } respContent = "返回的信息"; textMessage.setContent(respContent); respXml = MessageUtil.messageToXml(textMessage); }

(4)網站端:登錄頁面中作輪訓,每隔幾秒查詢一次redis,若是有用戶信息就登錄app

        var timestamp = new Date().getTime() + "";
    var str = timestamp.substring(8, timestamp.length);
    
        window.setInterval(function() {
        
        getUser(cont);
        
    }, 10000);

        function getUser() {
        $.ajax({
            type : 'get',
            data : {
                sceneId : str
            },
            dataType : 'json',
            url : "getUser.do",
            success : function(data) {

                if (data.msg == "success") {
                    location.reload(); 
                }

            },
            error : function(data) {

                if (data.msg == "success") {
                    location.reload();
                }

            }
        });
    }        

    

  --本文意在對網站實現微信公衆號用戶掃碼關注登陸的實現思路作了概述 post

  --這個方案中輪訓訪問是個問題,也是能夠改進的地方,可是目前沒有更好的方案,若是您有什麼更好的建議,歡迎留言給點思路優化

   優化後的方案 :http://www.cnblogs.com/cmyxn/p/7814120.html

相關文章
相關標籤/搜索