本文共 13258 字,大约阅读时间需要 44 分钟。
微信扫码功能实现基于,但是这个申请账号是需要收费的。我们个人在做项目的过程中可以使用微信测试号来实现扫码登录功能。申请测试号需要去[微信公众平台]: https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
,微信扫码登录就可以了。 扫码登录成功后,会直接分配一个appId和appsecret,这两个参数就是我们要用的。首先,需要向微信申请一个用于登录的二维码:
@GetMapping("/weixinLogin") private ResultJson weixinLogin(){ try { // String token1=weiXinShareService.setAccessToken(); //获取token开发者 String token=weiXinShareService.getAccessToken(); String url="https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+token; String scene_str = getRandomString(8);//这里生成一个带参数的二维码,参数是scene_str String json="{\"expire_seconds\": 604800, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \""+scene_str+"\"}}}"; log.info(json); JSONObject jsonObject = JSONObject.parseObject(json); JSONObject jsonObject1 = HttpUtils.httpPost(url,jsonObject); jsonObject1.put("sceneStr",scene_str); log.info("获取微信登录二维码成功!!!!"+jsonObject1.toJSONString()); return ResultJson.ok(jsonObject1); } catch (Exception e) { log.info("获取微信登录二维码失败:"+e); return ResultJson.failure(ResultCode.BAD_REQUEST); } }//length用户要求产生字符串的长度 public static String getRandomString(int length){ String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; Random random=new Random(); StringBuffer sb=new StringBuffer(); for(int i=0;i
上面方法返回的是一个json对象,我们需要使用json对象中的ticket换取二维码:
https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=//在这个地址后面拼接ticket直接获取二维码
换取的二维码是可以直接访问的,在前台通过一个标签就可以展示出来。
换取到二维码之后,在微信公众平台做一些配置:
URL处填写登录以后回调的接口路径,token出随便填写,但是要和后台代码保持一致,域名注意要去掉http,下面是我的回调方法
@RequestMapping ("/checkSign") public String checkSign ( HttpServletRequest request) throws Exception { //获取微信请求参数 log.info("接收微信公众号事件触发回调请求"); String signature = request.getParameter ("signature"); String timestamp = request.getParameter ("timestamp"); String nonce = request.getParameter ("nonce"); String echostr = request.getParameter ("echostr"); //参数排序。 token 就要换成自己实际写的 token String [] params = new String [] { timestamp,nonce,"123456"} ; Arrays.sort (params) ; //拼接 String paramstr = params[0] + params[1] + params[2] ; //加密 //获取 shal 算法封装类 MessageDigest Sha1Dtgest = MessageDigest.getInstance("SHA-1") ; //进行加密 byte [] digestResult = Sha1Dtgest.digest(paramstr.getBytes ("UTF-8")); //拿到加密结果 //String mysignature = WebUtils.byte2HexStr(digestResult); String mysignature = FileDataConvert.bytes2HexString(digestResult); mysignature=mysignature.toLowerCase(Locale.ROOT); log.info("微信加密,signature:"+signature); log.info("本地加密,mysignature:"+mysignature); //是否正确 boolean signsuccess = mysignature.equals(signature); //逻辑处理 if (signsuccess && echostr!=null) { //peizhi token return echostr ;//不正确就直接返回失败提示. }else{ String userInfo=callback(request); return userInfo; } }
注意:一定要项目先启动才能去配置相关路径,要不然获取不到token,配置失败
上面逻辑处理调用的方法,
@RequestMapping("callback") public String callback(HttpServletRequest request) throws Exception{ //request中有相应的信息,进行解析 WxMpXmlMessage message=WxMpXmlMessage.fromXml(request.getInputStream());//获取消息流,并解析xml String messageType=message.getMsgType(); //消息类型 String messageEvent=message.getEvent(); //消息事件 String fromUser=message.getFromUser(); //发送者帐号 String touser=message.getToUser(); //开发者微信号 String text=message.getContent(); //文本消息 文本内容 String eventKey=message.getEventKey(); //二维码参数 String uuid=""; //从二维码参数中获取uuid通过该uuid可通过websocket前端传数据 String userid=""; //从二维码参数中获取用户ID log.info("总的message:"+JSONObject.toJSONString(message)); log.info("消息类型:"+messageType); log.info("消息事件:"+messageEvent); log.info("发送者账号:"+fromUser); log.info("接收者微信:"+text); log.info("二维码参数:"+eventKey); //if判断,判断查询 if(messageType.equals("event")){ //从自己数据库中查取用户信息 UserInfo userInfo=userInfoService.selectByOpenId(fromUser); log.info("getToken得到的值:"+weiXinShareService.getAccessToken()); if(messageEvent.equals("SCAN")){ //扫描二维码 //return "欢迎回来"; } if(messageEvent.equals("subscribe")){ //关注 //return "谢谢您的关注"; } //没有该用户 if(userInfo==null){ //从微信上中拉取用户信息 String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + weiXinShareService.getAccessToken() + "&openid=" + fromUser + "&lang=zh_CN"; JSONObject userInfoJson = HttpUtils.httpGet(url); //插入并返回 UserInfo userInfo1 = new UserInfo(); userInfo1.setCity(String.valueOf(userInfoJson.get("city"))); userInfo1.setNickName(String.valueOf(userInfoJson.get("nickname"))); String sex = String.valueOf(userInfoJson.get("sex")); userInfo1.setGender(Integer.parseInt(sex)); userInfo1.setAvatarUrl(String.valueOf(userInfoJson.get("headimgurl"))); userInfo1.setOpenId(String.valueOf(userInfoJson.get("openid"))); Boolean flag= userInfoService.saveOrUpdate(userInfo1); log.info(userInfoJson.toString()); } //一个关联表,用与检查用户是否登录,登录向其中插入一条数据 RefUserLogin refUserLogin=new RefUserLogin(); refUserLogin.setEventKey(eventKey); refUserLogin.setOpenId(fromUser); refUserLoginService.saveOrUpdate(refUserLogin); return userInfoService.selectByOpenId(fromUser).toString(); //return userInfo.toString(); } return "消息不支持回复"; //log.info("消息类型:{},消息事件:{},发送者账号:{},接收者微信:{},文本消息:{},二维码参数:{}",messageType,messageEvent,fromUser,touser,text,eventKey); }
这里一个微信扫码登录网页的功能就完成了。
上面用到了工具类,在后台进行get和post的请求,工具类HttpUtils
import com.alibaba.fastjson.JSONObject;import org.apache.http.HttpEntity;import org.apache.http.HttpStatus;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.IOException;public class HttpUtils { private static Logger logger = LoggerFactory.getLogger(HttpUtils.class); private static RequestConfig requestConfig = null; static { // 设置请求和传输超时时 requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build(); } /** * post请求传输json参数 * * @param url url地址 * @param jsonParam 参数 * @return */ public static JSONObject httpPost(String url, JSONObject jsonParam) { // post请求返回结果 CloseableHttpClient httpClient = HttpClients.createDefault(); JSONObject jsonResult = null; HttpPost httpPost = new HttpPost(url); // 设置请求和传输超时时请求 httpPost.setConfig(requestConfig); try { System.out.println(jsonParam); if (null != jsonParam) { // 解决中文乱码问题 StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8"); entity.setContentEncoding("UTF-8"); entity.setContentType("application/json"); httpPost.setEntity(entity); } System.out.println(jsonParam); CloseableHttpResponse result = httpClient.execute(httpPost); // 请求发请求成功,并得到响应 if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { String str = ""; try { // 读取服务器返回过来的json字符串数 str = EntityUtils.toString(result.getEntity(), "utf-8"); // 把json字符串转换成json对象 jsonResult = JSONObject.parseObject(str); } catch (Exception e) { logger.error("post请求提交失败:" + url, e); } } } catch (IOException e) { logger.error("post请求提交失败:" + url, e); } finally { httpPost.releaseConnection(); } return jsonResult; } /** * post请求传输String参数 例如:name=Jack&sex=1&type=2 * Content-type:application/x-www-form-urlencoded * * @param url url地址 * @param strParam 参数 * @return */ public static JSONObject httpPost(String url, String strParam) { // post请求返回结果 CloseableHttpClient httpClient = HttpClients.createDefault(); JSONObject jsonResult = null; HttpPost httpPost = new HttpPost(url); httpPost.setConfig(requestConfig); try { if (null != strParam) { // 解决中文乱码问题 StringEntity entity = new StringEntity(strParam, "utf-8"); entity.setContentEncoding("UTF-8"); entity.setContentType("application/x-www-form-urlencoded"); httpPost.setEntity(entity); } CloseableHttpResponse result = httpClient.execute(httpPost); // 请求发宋成功,并得到响应 if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { String str = ""; try { // 读取服务器返回过来的json字符串数据 str = EntityUtils.toString(result.getEntity(), "utf-8"); // 把json字符串转换成json对象 jsonResult = JSONObject.parseObject(str); } catch (Exception e) { logger.error("post请求提交失败:" + url, e); } } } catch (IOException e) { logger.error("post请求提交失败:" + url, e); } finally { httpPost.releaseConnection(); } return jsonResult; } /** * 发送get请求 * * @param url 路径 * @return */ public static JSONObject httpGet(String url) { // get请求返回结果 JSONObject jsonResult = null; CloseableHttpClient client = HttpClients.createDefault(); // 发送get请求 HttpGet request = new HttpGet(url); request.setConfig(requestConfig); try { CloseableHttpResponse response = client.execute(request); // 请求发送成功,并得到响应 if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { // 读取服务器返回过来的json字符串数组 HttpEntity entity = response.getEntity(); String strResult = EntityUtils.toString(entity, "utf-8"); // 把json字符串转换成json对象 jsonResult = JSONObject.parseObject(strResult); } else { logger.error("get请求提交失败:" + url); } } catch (IOException e) { logger.error("get请求提交失败:" + url, e); } finally { request.releaseConnection(); } return jsonResult; }}
getAccessToken与seccesstAToken方法
/** * 获取微信全局Accesstoken,存储到redis */ public String setAccessToken() throws Exception{ String access_token = null; System.out.println("=======================像微信服务器发送获取全局accessToken======================="); String url = new StringBuilder().append("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential") .append("&appid="+weiXinProperties.getAppid()) .append("&secret="+weiXinProperties.getAppsecret()) .toString(); CloseableHttpClient client = HttpClients.createDefault(); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse res = client.execute(httpGet); if (res.getStatusLine().getStatusCode()== HttpStatus.SC_OK) { HttpEntity entity = res.getEntity(); String result = EntityUtils.toString(entity,"UTF-8"); JSONObject jsonObject = JSON.parseObject(result); access_token = jsonObject.getString("access_token"); System.out.println(result+"------------------------------"); redisUtil.set("getLiveToken",access_token,6000); } return access_token; } /** * 获取微信全局AccessToken */ public String getAccessToken() throws Exception{ String access_token = null; boolean reAsk = true; if (redisUtil.get("getLiveToken")!=null) { reAsk=false; Object obj = redisUtil.get("getLiveToken"); access_token = (String) obj; if (access_token==null) { reAsk=true; } } if (reAsk==true) { access_token = setAccessToken(); } return access_token; }
转载地址:http://gcyki.baihongyu.com/