微信平台扫码登陆时,由于开放平台的openid与原系统不一致,因此使用了原公众平台二维码扫码后获取用户openid,继而转连接形式.javascript
油腻腻的大猪蹄进行测试
oysIt005E1TDKTKIdc8TmR6VTViA < 使用开放平台的登陆二维码扫码获取的openid html
o4mIl1jXCq4b2MkQ0tTZTzKzl2XY < 微信平台获取的openid前端
o4mIl1jXCq4b2MkQ0tTZTzKzl2XY < 扫码临时二维码获取的openidjava
大体流程:jquery
用户点击微信登陆->跳转到该请求 wechat/wechatLoginweb
请求到该控制层ajax
package com.baigehuidi.demo.controller; import com.baigehuidi.demo.loader.WeixinInsLoader; import com.baigehuidi.demo.weixin4j.WeixinException; import com.baigehuidi.demo.weixin4j.model.qrcode.Qrcode; import com.baigehuidi.demo.weixin4j.model.qrcode.QrcodeType; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Date; /** * 生成带参二维码 */ @Controller public class WeixinQrcodeController { //该方法为用户点击微信登陆后请求的地址(第一步) @RequestMapping("/wechat/wechatLogin") public String wechatLogin(Model model) throws WeixinException { //场景字符串使用baige+时间 String scene_str = "baige"+new Date().getTime(); //字符串场景临时二维码 Qrcode qrcode = WeixinInsLoader.getWeixinInstance().qrcode().create(QrcodeType.QR_STR_SCENE,scene_str,600); String ticket = qrcode.getTicket(); String qrcodeUrl = null; if(ticket!=null){ qrcodeUrl = WeixinInsLoader.getWeixinInstance().qrcode().showQrcode(ticket);//方法中已经进行了encode } model.addAttribute("qrcodeUrl",qrcodeUrl); model.addAttribute("scene_str",scene_str); //return ModelAndView(qrcode展现页面路径,modelMap); //跳转到二维码展现页面 (参数为字母+时间戳) return "/wechat/qrcode"; } }
其中上面方法中执行了建立临时二维码的官方的api接口请求连接 create() 方法建立了二维码spring
获取ticket以后展现二维码,获取二维码展现url showQrcode就是干这个的.数据库
以后将展现二维码的路径放到model里,返回页面到wechat/qrcodejson
wechat/qrcode
截取展现jsp的控制器中展现qrcode的:
/** * 扫码登陆 临时带参二维码版 qrcode二维码展现页面 * @return */ @RequestMapping("/wechat/qrcode") public String wqrcode(){ return "/wechat/qrcode"; }
展现的就是qrcode.jsp
<%-- 微信扫码登陆 openid版本 --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>微信扫码,关注并登陆</title> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"/> <style>a { outline: 0 } h1, h2, h3, h4, h5, h6, p { margin: 0; font-weight: 400 } a img, fieldset { border: 0 } body { font-family: "Microsoft Yahei"; color: #fff; background: 0 0 } .impowerBox { display: inline-block; vertical-align: middle; line-height: 1.6; position: relative; width: 100%; z-index: 1; text-align: center } .impowerBox .title { text-align: center; font-size: 20px } .impowerBox .qrcode { width: 280px; height: 280px; margin-top: 15px; border: 1px solid #E2E2E2 } .impowerBox .info { width: 280px; margin: 0 auto } .impowerBox .status { padding: 7px 14px; text-align: left } .impowerBox .status.normal { margin-top: 15px; background-color: #232323; border-radius: 100px; -moz-border-radius: 100px; -webkit-border-radius: 100px; box-shadow: inset 0 5px 10px -5px #191919, 0 1px 0 0 #444; -moz-box-shadow: inset 0 5px 10px -5px #191919, 0 1px 0 0 #444; -webkit-box-shadow: inset 0 5px 10px -5px #191919, 0 1px 0 0 #444 } .impowerBox .status.status_browser { text-align: center } .impowerBox .status p { font-size: 13px }</style> <script src="http://www.jq22.com/jquery/jquery-3.3.1.js"></script> </head> <body style="background-color: rgb(51, 51, 51); padding: 50px;"> <div class="main impowerBox"> <div class="loginPanel normalPanel"> <div class="title">微信登陆</div> <div class="waiting panelContent"> <div class="wrp_code"> <img class="qrcode lightBorder" src="${qrcodeUrl}"/> </div> <div class="info"> <div class="status status_browser js_status normal" id="wx_default_tip"> <p>请使用微信扫描二维码登陆</p> <p>白鸽惠递</p> </div> </div> </div> </div> </div> <script type="text/javascript"> $(document).ready(function () { setInterval("wechatCheckLogin()", 2000); }); function wechatCheckLogin() { $.post("/wechat/checkLogin", {scene_str: "${scene_str}"}, function (data) { console.log("请求/wechat/checkLogin方法中..."); //数据1, 成功获取用户信息 if (data.code===1) { window.location.href="http://baige.free.idcfengye.com/wechat/callback"; } else if(data.code===0) { //虽然有用户openid,可是没法获取用户信息,多是用户取消了关注 //须要跳转到从新扫码生成界面 window.location.href="http://baige.free.idcfengye.com/wechat/wechatLogin"; }else if(data.code===-1){ //若是场景字符串为空 -1 检查场景字符串时间戳生成是否正确 window.location.href="http://baige.free.idcfengye.com/error"; }else if(data.code===-2){ //检查openid为何没正确传入 window.location.href="http://baige.free.idcfengye.com/error"; }else if(data.code===-3){ //-3 //二者都为空,系统挂了吗 window.location.href="http://baige.free.idcfengye.com/error"; } }, "JSON"); } </script> </body> </html>
上面jsp中对请求进行轮询: wechat/checkLogin
下面是WeixinConnectionController中的请求到的方法:
/** * TODO 若是数据库要进行更改,能够根据当时生成的scene_str查询用户openid或具体信息 * 该方法为 * @param scene_str * @return */ @ResponseBody @RequestMapping("/wechat/checkLogin") public Map wechatCheckLogin(String scene_str,HttpSession session) throws WeixinException { System.err.println("scene_str : " + scene_str); String toUserName = null;//用户openid if (xmlObj != null) { toUserName = xmlObj.getToUserName(); System.out.println("toUserName:" + toUserName); } //其中scene_str为场景字符串,使用了baige+时间戳 而toUserName则是扫码用户的openid if (scene_str != null && scene_str != "" && toUserName != null && toUserName != "") { System.err.println("wechatCheckLogin(String scene_str)->WeixinInsLoader.getWeixinInstance().getToken().getAccess_token()::::::"+WeixinInsLoader.getWeixinInstance().getToken().getAccess_token()); User user = WeixinInsLoader.getWeixinInstance().user().info(toUserName); System.out.println("user:"+user); Map map = new HashMap(); if(user!=null){ //成功获取用户状态码 // model.addAttribute(user); session.setAttribute("nickname",user.getNickname()); map.put("code",1); // map.put("user",user); return map; }else if(user==null && toUserName!=null && toUserName !=""){ //虽然有用户openid,可是没法获取用户信息,多是用户取消了关注 //须要跳转到从新扫码生成界面 map.put("code",0); return map; } else if(scene_str == null && scene_str == ""){ //若是场景字符串为空 -1 检查场景字符串时间戳生成是否正确 map.put("code",-1); return map; }else if(toUserName == null && toUserName == ""){ //检查openid为何没正确传入 map.put("code",-2); return map; }else{ //二者都为空,系统挂了吗 map.put("code",-3); return map; } } return null; }
该方法写在上面的Controller中虽有不太合适之嫌,但为了赶着完工,如今先放到这里,后期改善.
上面方法return map后,前端的qrcode.jsp页面接收返回值,若是用户已经扫码,则能够进行跳转回调页面.
这里到回调wechat/callback页面是由于若是仅仅获取微信用户信息,其实已经能够获取了:
经过上面的
User user = WeixinInsLoader.getWeixinInstance().user().info(toUserName);
该信息就是用户的微信资料信息.
可是除了这个信息,网站只是经过微信进行登陆,其它的网站上的信息,帐户,订单等是对应该用户的openid 或是openid同时的自增主键.
因此进入回调页面是要获取用户的更详尽的其它信息.
wechat/callback.jsp :
<%-- 缺乏样式 (正在跳转) --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>正在跳转...</title> <script src="http://www.jq22.com/jquery/jquery-3.3.1.js"></script> </head> <body> <p>该页面为回调页面,文本内容可为空.</p> 欢迎您,<%=session.getAttribute("nickname")%>. 正在跳转... <script> $.ajax({ // url: "/user/getOpenSnsUserInfoByCode", url: "/wechat/callbackAndGetUserInfo", // data: "${user.openid}", contentType: "application/json", dataType: "json", method: "POST", success: function (data) { if(data===1){ //right code -> to index window.location.href="http://baige.free.idcfengye.com"; }else{ //wrong code -> show error page window.location.href="http://baige.free.idcfengye.com/error"; } } }); </script> </body> </html>
wechat/callbackAndGetUserInfo:
/** * 将用户信息放入session * * @param * @return * @throws WeixinException */ @ResponseBody @RequestMapping(value = "/wechat/callbackAndGetUserInfo", method = RequestMethod.POST) public Integer callBackAndGetUserInfo(HttpSession session) throws WeixinException { System.out.println("callBackAndGetUserInfo method"); String access_token = WeixinInsLoader.getWeixinInstance().getToken().getAccess_token(); System.err.println("Connection:Access_token:" + access_token); SnsUser snsUser = null; String openid = xmlObj.getToUserName(); System.out.println("openid:" + openid); User user = null; if (openid != null && openid != "") { //查询该openid下的其它表数据,如帐户表等,放入一个实体传回到首页 //这里先只展现用户信息 user = WeixinInsLoader.getWeixinInstance().user().info(openid); session.setAttribute("user",user); } //存数据库 if (user != null) { return 1; } else { return 0; } }
这里还有一些逻辑没作,好比用户以前关注过微信平台,再返回来关注时,虽然用户的openid仍是相同的,可是给出提示
应该是: 欢迎回来.
而第一次关注的则是 : 欢迎关注...并给出新手提示.
这里还有一篇文章:
微信公众号与微信开放平台的openid不一致怎么破解?unionID为你解围
简单记录下整个流程
最后补一个index.jsp
<%@ page import="com.baigehuidi.demo.weixin4j.model.user.User" %> <%@ page import="com.baigehuidi.demo.weixin4j.model.sns.SnsUser" %><%-- 测试首页 将登陆作为单独的页面 (也能够在该页面中进行弹出[或iframe形式或遮罩窗体形式]) TODO 每页(包括子页面)都应有登陆或者展现用户昵称的头部bar 该页面为PC端. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>微信扫码登陆</title> <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"></script> <style> .link{display: none;} .show{display: block;} </style> </head> <body> TODO : index.jsp 该页面也为最终用户登陆后的页面,登陆后,再也不展现登陆集,而展现用户名 <br> <p id="nickname"></p> 用户登陆后设定session时间 <br> <a href="login">登陆集</a> <br> <a href="/menuCreate">自定义菜单</a> <br> <a href="/wxpay/notify">支付测试</a> <br> 测试号二维码<br> <img src="img/0.jpg" style="height:300px;width:300px"> ${snsUser.nickname} <%if(session.getAttribute("user")!=null){%> <%User user = (User)session.getAttribute("user");%> <%=user.getNickname()%> <%}%> <%--<%if(session.getAttribute("SnsUser")!=null){%>--%> <%--<%SnsUser snsUser = (SnsUser)session.getAttribute("SnsUser");%>--%> <%--<%=snsUser.getNickname()%>--%> <%--<%}%>--%> <a href="" class="link a2 show">不是微信端</a> <a href="" class="link a1">微信端</a> <p>该页面经过断定是不是微信内置浏览器,执行/非执行网页受权获取用户信息.</p> <script> function isWeiXin() { var ua = window.navigator.userAgent.toLowerCase(); console.log(ua);//mozilla/5.0 (iphone; cpu iphone os 9_1 like mac os x) applewebkit/601.1.46 (khtml, like gecko)version/9.0 mobile/13b143 safari/601.1 if (ua.match(/MicroMessenger/i) == 'micromessenger') { return true; } else { return false; } } if(isWeiXin()){ console.log(" 是来自微信内置浏览器"); $(".a1").addClass("show"); $(".a2").removeClass("show"); //是微信内置浏览器执行经过code获取用户信息 getSnsUserInfoByCode(); function getSnsUserInfoByCode(){ alert("getSnsUserInfoByCode in method"); //下面页面为手机端页面获取 $.ajax({ url: "/user/getSnsUserInfoByCode", // url: "/callBackLogin", data: "<%=request.getParameter("code")%>", contentType: "application/json", dataType: "json", method: "POST", success: function (data) { alert(JSON.stringify(data)); var nickname = data.SnsUser.nickname; $("#nickname").html(nickname+"同窗"); alert("你好啊,"+data.SnsUser.nickname+"同窗,很久不见你瘦了一大圈."); //将数据反填到html或jsp页面上 } }); } } else{ console.log("不是来自微信内置浏览器"); $(".a2").addClass("show"); $(".a1").removeClass("show"); } </script> </body> </html>