開發微信網頁受權時須要一個外網能夠訪問的域名,由於用戶確認進行微信網頁受權後微信服務器會經過一個回調URL向開發服務器發送一個回調請求。
開發階段可使用一些內網穿透工具來實現,例如:natapp、花生殼等等。
福利:natapp和花生殼都會免費贈送一些隧道。
注意:natapp提供的免費隧道每次啓動客戶端時產生的域名時隨機的。
填坑:利用花生殼提供的域名進行內網穿透時可能會被微信攔截,因此推薦使用natapp(PS: 請測有效)。java
因爲是進行微信網頁受權,因此須要一個我的微信訂閱號做爲開發基礎。
福利:因爲微信我的訂閱號沒有提供微信網頁受權功能,可是能夠利用微信提供的測試號進行開發。
測試號在哪裏:登陸我的訂閱號 -> 開發 -> 開發者工具 -> 公衆平臺測試帳號
注意:整個開發過程當中都是使用測試號的appID和appsecret數據庫
JDK: 1.8
MAVEN: 3.x
SpringBoot: 2.x
IDEA: 2017專業版api
文檔在哪裏:登陸微信訂閱號 -> 開發 -> 開發者工具 -> 開發文檔 -> 微信網頁開發 -> 微信網頁受權瀏覽器
在哪裏配置:登陸我的訂閱號 -> 開發 -> 開發者工具 -> 公衆平臺測試帳號 -> 網頁服務 -> 網頁帳號 -> 修改 -> 填入受權回調頁面域名便可(推薦使用natapp)服務器
1 第一步:用戶贊成受權,獲取code
2 第二步:經過code換取網頁受權access_token
3 第三步:刷新access_token(若是須要)
4 第四步:拉取用戶信息(需scope爲 snsapi_userinfo)
5 附:檢驗受權憑證(access_token)是否有效微信
只須要經過微信瀏覽器訪問到微信受權的頁面便可。
思路
01 用戶經過微信瀏覽器進入一個頁面
02 點擊一個按鈕向開發者後臺發送一個GET請求
03 開發這個後臺封裝一個URL並重定向到這個URL
代碼片斷app
/** * 微信網頁受權邏輯入口 * @param map */ @GetMapping(value = "/auth") public void toAuth(ModelMap map, HttpServletRequest request, HttpServletResponse response) throws IOException { log.info("進入微信受權邏輯......"); // 微信網頁受權第一步 - 用戶贊成受權,獲取code - start String getCodeUrl = weixinBaseInfoProperties.getAuth().getGetCodeUrl(); String appid = weixinBaseInfoProperties.getAppid(); String appsecret = weixinBaseInfoProperties.getAppsecret(); String redirectUri = weixinBaseInfoProperties.getAuth().getRedirectUri(); String scope = weixinBaseInfoProperties.getAuth().getScope(); getCodeUrl = getCodeUrl.replace("APPID", appid) .replace("REDIRECT_URI", redirectUri) .replace("SCOPE", scope); log.info("封裝好的getCodeUrl爲:" + getCodeUrl); response.sendRedirect(getCodeUrl); // 微信網頁受權第一步 - 用戶贊成受權,獲取code - end }
微信用戶經過微信瀏覽器確認受權後,微信服務器會經過以前設定的回調URL向開發者後臺發送一個GET請求,這個請求中攜帶了CODE信息。
思路
01 用戶確認受權
02 微信服務器發送回調請求
03 開發服務器接收到回調請求
04 獲取CODE
05 經過CODE在拼裝一個url去請求微信服務器來獲取access_token、openid
06 經過access_token、openid封裝一個url去請求微信服務器來獲取用戶信息工具
獲取用戶信息成功後直接跳轉到目標頁面便可測試
思路:
01 獲取用戶信息成功
02 根據用戶openid到數據庫中去查找網頁帳號信息
03 若是查找到信息就說明已經綁定,直接跳轉拿到目標頁面便可
04 若是沒有獲取到就跳轉到登陸綁定頁面
05 用戶輸入帳號和密碼並提交到開發者後臺
06 後臺需對網站帳號合法性進行校驗
07 校驗經過後進行綁定操做
08 跳轉到目標頁面
代碼片斷一網站
/** * 回調頁面 * @param map * @return */ @GetMapping(value = "/callback") public String callback(ModelMap map, HttpServletRequest request, HttpServletResponse response) { log.info("進入回調處理邏輯......"); String appid = weixinBaseInfoProperties.getAppid(); String appsecret = weixinBaseInfoProperties.getAppsecret(); // 微信網頁受權第二步 - 經過code換取網頁受權access_token - start StringBuffer requestURL = request.getRequestURL(); log.info("進入回調處理邏輯的請求url爲:" + requestURL); String code = request.getParameter("code"); log.info("獲取到的用於換取access_token的票據的code值爲:" + code); String getAccessTokenUrl = weixinBaseInfoProperties.getAuth().getGetAccessTokenUrl(); getAccessTokenUrl = getAccessTokenUrl.replace("APPID", appid) .replace("SECRET", appsecret) .replace("CODE", code); log.info("封裝好的用於獲取accessToke的url爲:" + getAccessTokenUrl); String getAccessTokenResponseStr = httpUtils.doGetStrByRestTemplate(getAccessTokenUrl); log.info("發送獲取access_token請求後的響應爲STR:" + getAccessTokenResponseStr); GetAuthAccessTokenResponse getAuthAccessTokenResponse = transformerUtils.String2Object(getAccessTokenResponseStr, GetAuthAccessTokenResponse.class); log.info("發送獲取access_token請求後的響應爲:" + getAuthAccessTokenResponse); String access_token = getAuthAccessTokenResponse.getAccess_token(); String open_id = getAuthAccessTokenResponse.getOpenid(); // 微信網頁受權第二步 - 經過code換取網頁受權access_token - end // 微信網頁受權第四步 - 拉取用戶信息(需scope爲 snsapi_userinfo) - start String getUserInfoUrl = weixinBaseInfoProperties.getAuth().getGetUserInfoUrl(); getUserInfoUrl = getUserInfoUrl.replace("ACCESS_TOKEN", access_token) .replace("OPENID", open_id); log.info("封裝好的用於獲取userInfo的url爲:" + getUserInfoUrl); String getUserInfoResponseStr = httpUtils.doGetStrByRestTemplate(getUserInfoUrl); log.info("發送獲取userInfo請求後的響應爲STR:" + getUserInfoResponseStr); GetUserInfoResponse getUserInfoResponse = transformerUtils.String2Object(getUserInfoResponseStr, GetUserInfoResponse.class); log.info("發送獲取userInfo請求後的響應爲:" + getUserInfoResponse); // 微信網頁受權第四步 - 拉取用戶信息(需scope爲 snsapi_userinfo) - end // 第一種使用:直接使用微信的用戶用戶體系 // map.addAttribute("userinfo", getUserInfoResponse); // return "index2"; // 第二種:微信用戶和網站用戶進行綁定 // 根據openid查詢網站的帳戶信息 UserBindDO userBindDOByOpenid = userBindRepository.findByOpenid(getUserInfoResponse.getOpenid()); if (userBindDOByOpenid != null) { // 已經綁定過的狀況 log.info("已經綁定過啦"); map.addAttribute("userinfo", userBindDOByOpenid); return "index3"; } else { // 沒有綁定過的狀況 log.info("還未進行綁定操做"); map.addAttribute("openid", getUserInfoResponse.getOpenid()); map.addAttribute("nickname", getUserInfoResponse.getNickname()); return "login"; } }
代碼片斷二
@PostMapping(value = "/login") public String login(UserBindDO userBindDO, ModelMap map) { log.info("獲取到的參數信息爲:" + userBindDO); // TODO: 對帳戶信息進行格式校驗,若是格式不正確直接返回登陸綁定頁面 // TODO: 驗證帳戶是否存在, 若是不存在直接跳轉到註冊頁面(微信用戶信息同時返回),在註冊邏輯中直接進行綁定 // TODO: 驗證帳戶密碼是否正確,若是部正確直接返回登陸綁定頁面 UserBindDO save = userBindRepository.save(userBindDO); if (save != null) { log.info("bind - 綁定成功"); log.info("綁定後的結果信息爲:" + save); map.addAttribute("userinfo", save); return "index3"; } else { log.info("bind - 綁定失敗"); return "login"; } }
掃碼獲取