网站实现扫描二维码关注微信公众号,如果已经关注公众号就自动登陆网站并获取其微信昵称,头像等信息,如果用户未关注就等用户关注公众号后自动登陆网站
--如果用户已关注公众号,网站端直接自动登陆,如果没有关注,就等用户关注公众号之后网站端自动登陆
(目前已经完成了这个功能,示例网址:http://www.bid-data.com/ 爱招标——免费实时标讯推送平台,为企业负责人及商务人员即时掌控招标动态、中标检索、竞争对手中标项目分析等服务平台。)
做微信扫码登陆,生成二维码必须是微信公众号中绑定的域这个域名,网站生成不了二维码(网站与微信服务器不是同一个域名) ,而是调用微信系统的接口获取二维码,用户扫码后也是请求微信服务器
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)网站端:网站写一个调用微信生成二维码的接口
@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,如果有用户信息就登陆
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(); } } }); }
__
原文链接:https://www.cnblogs.com/cmyxn/p/7803117.html