JAVA 登陸這個功能我是隻請求了微信的登陸,token、登陸時長等設置我仍是使用了本身項目來控制的css
微信登陸真的很坑,建議理解透了再動手開發,下面核心的地方我標註起來了前端
向APPID之類的東西,建議添加到配置裏面,有不懂的能夠在下面留言java
小程序登陸能夠看一下個人另外一篇文章,相對來講更簡單一點 : 微信登陸-小程序版本json
話很少說,直接貼源碼,複製便可用,wink~小程序
private static Logger log = LoggerFactory.getLogger(XXX.class); //調用微信接口時,增長的css樣式,能夠不用加,文檔上有 private String href = "https://www.oschina.net/login-qrcode.css"; //回調本身項目的前端地址 private String callBackHref = "https://www.oschina.net/"; /** * @Author : Yanqiang * @Date : 2019/3/7 * @Param : [request] * @return : java.util.Map<java.lang.String,java.lang.Object> * @Description : 返回微信二維碼,可供掃描登陸 * * 總體請求流程: * 登陸頁面點擊微信登陸 ——> 請求後端的qrconnect()接口 ——> 後端請求:https://open.weixin.qq.com/connect/qrconnect 而且傳遞用戶掃碼後微信回調項目的地址 * ——> 微信本身去判斷用戶有沒有掃碼(不須要本身寫) ——> (已掃碼)微信回調你請求時傳遞的接口 * PS: * 如下爲排坑!!! * * 微信公衆平臺 and 微信開放平臺 是不同的東西 * * 微信登陸分爲 1·PC端, 2·APP, 3·小程序, 4·公衆號 .... * 以上調用的地址是不一樣的!!! PC端 在這個地址註冊 https://open.weixin.qq.com/ 點網站應用開發,好像是註冊一個三百多塊錢,準備好money * 這個地址是公衆號的開發!!!https://mp.weixin.qq.com/wiki 千萬不要看這個去開發PC * 不一樣應用之間APPID和Secret都不同(即便多個小程序或多個PC也是不一樣的),一個應用一個,千萬不要用錯了, */ @RequestMapping(value = "qrconnect", method = RequestMethod.GET) public BaseResult qrconnect(HttpServletRequest request, HttpServletResponse response){ BaseResult baseResult = new BaseResult(); //微信二維碼的接口 String wxLoginurl = "https://open.weixin.qq.com/connect/qrconnect?" + "appid={APPID}&redirect_uri={REUTL}&response_type=code&scope=snsapi_login&state={STATE}&href={HREF}#wechat_redirect"; //拼接組裝掃碼登陸url wxLoginurl = wxLoginurl.replace("{APPID}", "微信發放的APPID") .replace("{REUTL}","微信回調你本身項目的接口路徑")//這裏就是指向下面的getUserInfo()接口 .replace("{STATE}","隨意填寫的值,我是生成了一個隨機數,也能夠不變") .replace("{HREF}",href);//調用微信接口時,增長的css樣式,能夠不用加,文檔上有 //發送請求 String result = response.encodeURL(wxLoginurl); log.info("==掃碼result :"+result); // response.sendRedirect(result); //這裏能夠直接重定向到你的項目的前端地址, // 個人項目本身把二維碼鑲嵌在本身的網頁中, // 沒有直接跳到微信的二維碼網頁,因此返回地址就能夠了,前端作處理 baseResult.setData(result); return baseResult; } /** * @Author : Yanqiang * @Date : 2019/3/7 * @Param : [map, request, response] * @return : java.lang.String * @Description : 微信獲取用戶信息,用戶掃碼後微信調用此接口 * 請求流程: * 獲取code ——> 用code獲取AccessToken ——> 用AccessToken獲取userinfo * * 1·獲取微信調用時傳遞的參數code: String code = request.getParameter("code") * 2·經過Appid,Secret,code 去獲取AccessToken;接口:https://api.weixin.qq.com/sns/oauth2/access_token * 3·經過AccessToken去請求用戶信息;接口:https://api.weixin.qq.com/sns/userinfo * 4·unionid: * 4.1 只有關聯了小程序纔有這個,沒關聯的只有openid * 4.2 多個應用同一用戶的unionid 相同且惟一(應該相似用戶在微信的惟一ID) * 5·openid: * 5.1 不一樣應用之間同一用戶的openid是不一樣的(即便大家公司多個小程序也是不一樣的) * 5.2 相同應用中同一用戶openid是相同的 * 6·強烈推薦剛開始作項目就關聯起來,使用unionid作用戶二級ID,即便不使用unionid,也要記錄起來,否則後期是個大問題 */ @RequestMapping(value = "getUserInfo", method = RequestMethod.GET) public void getUserInfo(HttpServletRequest request, HttpServletResponse response) throws IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); //從微信傳遞的參數裏獲取code String code = request.getParameter("code"); // 經過code獲取WeixinOauth2Token 再獲取 access_token WeixinOauth2Token oauth2Token = WeiXinUtil.getOauth2AccessToken("微信發放的APPID", "微信發放的Secret", code); log.info("===========code = "+code+"==========="); String accessToken=oauth2Token.getAccessToken(); log.info("===========accessToken = "+accessToken+"==========="); String openId=oauth2Token.getOpenId(); log.info("===========openId = "+openId+"==========="); //獲取到用戶的基本信息 JSONObject snsUserInfo = WeiXinUtil.getSNSUserInfo(accessToken, openId); log.info("===========snsUserInfo = "+snsUserInfo.toString()+"==========="); if(snsUserInfo!=null){ //這裏能夠直接拿到用戶信息了,就能夠你的業務處理了 String headimgurl = (String) snsUserInfo.get("headimgurl"); String nickname = (String) snsUserInfo.get("nickname"); String language = (String) snsUserInfo.get("language"); String province = (String) snsUserInfo.get("province"); String country = (String) snsUserInfo.get("country"); String unionId = (String) snsUserInfo.get("unionid"); String openid = (String) snsUserInfo.get("openid"); int sex = (Integer) snsUserInfo.get("sex"); //重定向到你的項目的前端地址 response.sendRedirect(callBackHref+"?code=1"); }else{ //獲取不到用戶 登陸失敗 重定向到你的項目的前端地址,而且傳遞一個狀態值 response.sendRedirect(callBackHref+"?code=0"); } }
如下爲使用到的工具類後端
WeiXinUtilapi
public class WeiXinUtil { private static Logger log = LoggerFactory.getLogger(WeiXinUtil.class); //把 appid和appsecret改了就行 public final static String AccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; public final static String userinfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; /** * @Author : Yanqiang * @Date : 2019/3/7 * @Param : [appId, appSecret, code] * @return : com.mjt.passport.util.WeiXinUtils.WeixinOauth2Token * @Description : 網頁受權認證 */ public static WeixinOauth2Token getOauth2AccessToken(String appId,String appSecret,String code) { String requestUrl=AccessTokenUrl.replace("APPID", appId).replace("SECRET", appSecret).replace("CODE", code); //發送請求獲取網頁受權憑證,這個httpsRequest就不貼出來了,就是發送http請求,網上一大把,本身寫也很快 JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, EnumMethod.GET.name(), null); WeixinOauth2Token wxot=new WeixinOauth2Token(); wxot.setAccessToken(jsonObject.getString("access_token")); wxot.setExpiresIn(jsonObject.getInt("expires_in")); wxot.setRefreshToken(jsonObject.getString("refresh_token")); wxot.setOpenId(jsonObject.getString("openid")); wxot.setScope(jsonObject.getString("scope")); return wxot; } /** * @Author : Yanqiang * @Date : 2019/3/7 * @Param : [accessToken, openId] * @return : com.mjt.passport.util.WeiXinUtils.SNSUserInfo * @Description : 獲取用戶的基本信息 打印log日誌 便於查找問題 */ public static JSONObject getSNSUserInfo(String accessToken,String openId) { String requestUrl=userinfoUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId); log.info("===========requestUrl = "+requestUrl+"==========="); //經過網頁受權獲取用戶信息 JSONObject jsonObject=CommonUtil.httpsRequest(requestUrl, EnumMethod.GET.name(), null); log.info("===========jsonObject = "+jsonObject+"==========="); return jsonObject; } }
WeixinOauth2Token微信
public class WeixinOauth2Token { //網頁受權接口調用憑證 private String accessToken; //憑證有效時長 private int expiresIn; //用於刷新憑證 private String refreshToken; //用戶標識 private String openId; //用戶受權做用域(當scope=snsapi_base時,不彈出受權頁面,直接跳轉 只能獲取到openId,當scope=snsapi=userinfo時彈出受權頁面,獲取用戶信息) private String scope; public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken; } public int getExpiresIn() { return expiresIn; } public void setExpiresIn(int expiresIn) { this.expiresIn = expiresIn; } public String getRefreshToken() { return refreshToken; } public void setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; } public String getOpenId() { return openId; } public void setOpenId(String openId) { this.openId = openId; } public String getScope() { return scope; } public void setScope(String scope) { this.scope = scope; } }