思路
1、Vue前端页面获取一个公众号的二维码,不是普通二维号,是带有场景值的
2、java后端接收前端的请求,生成一个带时效性的二维码链接返回给前端
3、公众号平台配置服务器接口地址
4、接收到关注或扫码请求并相应处理
5、前端轮询状态,如果检查到验证通过进到下一页面
前端页面
vue代码
wxlogin() { this.$showLoading(); getTempQrCode(this.token).then((res) => { console.log("res==========",res); this.$closeLoading(); this.imageUrl = objToStr(res.data.message); this.loginType='wx' setTimeout(() => { this.check(); }, 1000); }) },
java代码
@RequestMapping(value = "/getTempQrCode", method = RequestMethod.GET)public Result<?> getTempQrCode(@RequestParam(name = "scene_str", required = true) String sceneStr) { WeixinHelper.setAppId(appid); WeixinHelper.setSecret(secret); String result = WeixinHelper.createTempQrCode(WeixinHelper.getAccessToken(), sceneStr); return Result.ok(result);}public static String createTempQrCode(String access_token, String scene_str) { String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + access_token; Map<String, Object> data = new HashMap<>(); data.put("expire_seconds", 604800); data.put("action_name", "QR_STR_SCENE"); Map<String, Object> action_info = new HashMap<>(); Map<String, Object> scene = new HashMap<>(); scene.put("scene_str", scene_str); action_info.put("scene", scene); data.put("action_info", action_info); String json = HttpUtil.createPost(url) .header("Content-Type", "application/json") .body(JSONUtil.toJsonStr(data)) .execute().body(); System.out.println("json = " + json); String qrcode = (String) JSONUtil.getByPath(JSONUtil.parse(json), "ticket"); return "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + qrcode; }public static String getAccessToken() { accessToken = getNewAccessToken(); return accessToken;}public static String getNewAccessToken() { String access_token = ""; String grant_type = "client_credential";//获取access_token填写client_credential String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=" + grant_type + "&appid=" + appId + "&secret=" + secret; try { URL urlGet = new URL(url); HttpURLConnection http = (HttpURLConnection) urlGet.openConnection(); http.setRequestMethod("GET"); // 必须是get方式请求 http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); http.setDoOutput(true); http.setDoInput(true); System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒 System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒 http.connect(); InputStream is = http.getInputStream(); int size = is.available(); byte[] jsonBytes = new byte[size]; is.read(jsonBytes); String message = new String(jsonBytes, "UTF-8"); JSONObject demoJson = JSONObject.parseObject(message); System.out.println("JSON字符串:" + demoJson); access_token = demoJson.getString("access_token"); is.close(); } catch (Exception e) { e.printStackTrace(); } return access_token;}
公众号配置
java提供消息接收接口代码,有两个,一个get(公众平台网址验证的时候用),一个post(消息事件触发时用)
/* * @param signature 微信加密签名,signature结合了开发者填写的 token 参数和请求中的 timestamp 参数、nonce参数。 * @param timestamp 时间戳 * @param nonce 这是个随机数 * @param echostr 随机字符串,验证成功后原样返回 */ @GetMapping("/wx/event") public void get(@RequestParam(required = false) String signature, @RequestParam(required = false) String timestamp, @RequestParam(required = false) String nonce, @RequestParam(required = false) String echostr, HttpServletResponse response) throws IOException { System.out.println("接受事件===" + echostr); response.setCharacterEncoding("UTF-8"); response.getWriter().write(echostr); response.getWriter().flush(); response.getWriter().close(); } //处理微信推送事件 @PostMapping("/wx/event") public void post(final HttpServletRequest request, HttpServletResponse response) { System.out.println("接受事件"); try { // 微信加密签名 final String signature = request.getParameter("signature"); // 时间戳 final String timestamp = request.getParameter("timestamp"); // 随机数 final String nonce = request.getParameter("nonce"); // 随机字符串 final String echostr = request.getParameter("echostr"); //将xml文件转成易处理的map(下方贴出) final Map<String, String> map = oConvertUtils.parseXml(request); //开发者微信号 final String toUserName = map.get("ToUserName"); //OpenId final String fromUserName = map.get("FromUserName"); //消息创建时间 (整型) final String createTime = map.get("CreateTime"); //消息类型,event final String msgType = map.get("MsgType"); //事件类型 final String event = map.get("Event"); String scene_str = ""; String msg = ""; if ("event".equals(msgType)) { if (event.equals("subscribe")) { final String ticket = map.get("Ticket"); if (ticket != null) { scene_str = map.get("EventKey").replace("qrscene_", ""); } msg = getXmlReturnMsg(fromUserName, toUserName, (new Date()).getTime(), "欢迎您使用量子文档"); } //注:事件类型为SCAN即已关注 else if (event.equals("SCAN")) { final String ticket = map.get("Ticket"); if (ticket != null) { scene_str = map.get("EventKey"); } msg = getXmlReturnMsg(fromUserName, toUserName, (new Date()).getTime(), "您刚刚扫码登录了量子文档"); } } System.out.println("event:" + event); System.out.println("场景值:" + scene_str); System.out.println("openId:" + fromUserName); System.out.println("ToUserName:" + toUserName); // 如果scene_str 不为空代表用户已经扫描并且关注了公众号 if (oConvertUtils.isNotEmpty(scene_str)) { QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("open_id", fromUserName); SysUser sysUser = sysUserService.getOne(queryWrapper, false); if (sysUser == null) { sysUser = new SysUser(); sysUser.setOpenId(fromUserName); sysUser.setUsername(fromUserName); sysUser.setRealname(null); String salt = oConvertUtils.randomGen(8); String passwordEncode = PasswordUtil.encrypt(fromUserName, salt, salt); sysUser.setSalt(salt); sysUser.setMemberLevelId("1"); sysUser.setPassword(passwordEncode); sysUser.setStatus(1); sysUser.setDelFlag(CommonConstant.DEL_FLAG_0); sysUserService.save(sysUser); LzMessage message = new LzMessage(); message.setMsgDate(new Date()); message.setContent("欢迎您使用量子文档"); message.setFileId(null); message.setIsRead(0); message.setDelFlag(0); message.setMsgType(3); message.setFromUserId("001"); message.setFromUserName("小量子"); message.setToUserId(sysUser.getId()); lzMessageService.save(message); } // 将