网站实现扫描二维码关注微信公众号,若是已经关注公众号就自动登录网站并获取其微信昵称,头像等信息,若是用户未关注就等用户关注公众号后自动登录网站html
--若是用户已关注公众号,网站端直接自动登录,若是没有关注,就等用户关注公众号以后网站端自动登录ajax
(目前已经完成了这个功能,示例网址:http://www.bid-data.com/ 爱招标——免费实时标讯推送平台,为企业负责人及商务人员即时掌控招标动态、中标检索、竞争对手中标项目分析等服务平台。)redis
作微信扫码登录,生成二维码必须是微信公众号中绑定的域这个域名,网站生成不了二维码(网站与微信服务器不是同一个域名) ,而是调用微信系统的接口获取二维码,用户扫码后也是请求微信服务器 json
// 临时二维码 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
--这个方案中轮训访问是个问题,也是能够改进的地方,可是目前没有更好的方案,若是您有什么更好的建议,欢迎留言给点思路优化