簡單三步獲取微信公眾號使用者授權
阿新 • • 發佈:2019-02-18
之前做過幾次微信公眾號開發, 一直沒有記錄下開發過程, 為方便以後不用在去各種搜尋找資料, 在此記錄開發流程...
首先, 開通微信公眾號, 電梯直達(公眾號申請).
第二步, 繫結開發者許可權, 方便使用開發者工具除錯
一切準備就緒, 接下來分析微信公眾號授權流程, 下圖簡單介紹授權序列圖:
在沒有弄清楚該流程之前, 我一直有個疑惑, 到底該何時提示使用者授權呢? 也就是說微信伺服器與我們的業務伺服器在哪裡作為切入點.
這裡可以有兩種方式提示使用者授權:
- 訪問首頁授權
- 訪問指定介面授權
在需要的介面上指定 LoginValidation 註解即可, (在Class中註解表示該類所有介面都需要登入可以訪問, 也可在指定方法中註解)
指定需要攔截的地址, 以及攔截器規則開發:
接下來為微信伺服器提供回撥介面public class LoginInterceptor extends HandlerInterceptorAdapter { private final Logger LOGGER = LoggerFactory.getLogger(getClass()); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String path = request.getServletPath(); HandlerMethod method = (HandlerMethod) handler; Method originO = method.getMethod(); Class<?> clazz = originO.getDeclaringClass(); LoginValidation classAnnotation = clazz.getAnnotation(LoginValidation.class); LoginValidation methonAnnotation = method.getMethodAnnotation(LoginValidation.class); boolean needLogin = (null != methonAnnotation || null != classAnnotation); boolean isGuest = (null == WebUtil.getUser()); if (needLogin && isGuest) { ResponseBody responseBody = ((HandlerMethod) handler).getMethodAnnotation(ResponseBody.class); boolean isReqData = (null != responseBody); if (isReqData) path = "/"; // 如果是資料請求, 授權後返回首頁 redirectAuth(request, response, path); return false; } return true; } private void redirectAuth(HttpServletRequest request, HttpServletResponse response, String path) throws Exception { LOGGER.info("使用者未登入, 跳轉到授權頁面"); boolean normalReq = !isAjaxRequest(request); String redirectPath = "/wx/auth"; if (normalReq) { response.sendRedirect(redirectPath); } else { Map map = Maps.newHashMap(); map.put("flag", false); map.put("redirect", redirectPath); WebUtil.writeJSON(map); } WebUtil.setSessionAttr(Constants.SESSION_WECHAT_AUTH_BEFORE_PATH, path); } public boolean isAjaxRequest(HttpServletRequest request) { String header = request.getHeader("X-Requested-With"); boolean isAjax = "XMLHttpRequest".equals(header) ? true : false; return isAjax; } }
一切準備接續, 接下來重點關注 WeChatController, 我們先來看看 auth 這個介面的實現@Controller @RequestMapping("/wx") public class WeChatController { private static final String APP_ID = "wx1xxxxxxxxxxxxxxx"; private static final String APP_SECURITY = "aa23461daxxxxxxxxxxxxxxxxxxxxxxxxx"; @Autowired private UserService userService; /** * 構建授權頁面 */ @RequestMapping("auth") public String auth(); /** * 微信伺服器回撥介面 * @param code 用於換區access_Token, 用來獲取使用者資料 * @param state 自定義資料 */ @RequestMapping("callback") public String callback(String code, String state) }
@RequestMapping("auth")
public String auth() {
// 本地開發 WebUtil.getBaseUrl() 總是為 localhost
// String callback = URLEncoder.encode(WebUtil.getBaseUrl() + "wx/callback", "UTF-8");
String callback = StringUtil.encodeUrl("http://df52b8f6.ngrok.io/wx/callback", "UTF-8");
String url = WeChatUtil.createUrl(WeChatUtil.newAuthorizeParam(APP_ID, callback, WeChatUtil.Scope.SNSAPI_USERINFO, null));
return "redirect:" + url;
}
通過 WeChatUtil.createUrl() 通過簡單封裝, 構建一個微信授權的重定向連結, 該連結中包含以下幾部分,
需要重點關注Scope值:
- snsapi_base (不彈出授權頁面,直接跳轉,只能獲取使用者openid)
- snsapi_userinfo (彈出授權頁面,可通過openid拿到暱稱、性別、所在地。並且,即使在未關注的情況下,只要使用者授權,也能獲取其資訊)
/**
* 微信伺服器回撥介面
* @param code 用於換區access_Token, 用來獲取使用者資料
* @param state 自定義資料
*/
@RequestMapping("callback")
public String callback(String code, String state) {
AccessData accessData = WeChatUtil.accessToken(WeChatUtil.newAccessParam(code, APP_ID, APP_SECURITY));
String openId = accessData.getOpenId();
User user = userService.getByOpenId(openId);
if (null == user) {
WeChatUser wxUserInfo = accessData.getUser();
user = userService.loginByWeChat(wxUserInfo);
}
WebUtil.setUser(user);
String path = WebUtil.getSessionAttr(Constants.SESSION_WECHAT_AUTH_BEFORE_PATH);
return "redirect:" + path;
}
WeChatUtil.accessToken() 通過回撥引數 code 獲取 AccessData 物件, 通過該物件可以獲取到 openid 和 WeChatUser 資料.
- openid 為當前使用者對當前公眾號關聯應用唯一識別碼.
- WeChatUser 為使用者公開資訊, 可拿到暱稱、性別、所在地等資訊. Scope 必須為 WeChatUtil.Scope.SNSAPI_USERINFO (也就是snsapi_userinfo)
根據具體業務使用 WeChatUser 物件即可.
三步獲取使用者資料總結:
第一步, 構建授權重定向地址 WeChatUtil.createUrl(WeChatUtil.newAuthorizeParam(appId, callback, WeChatUtil.Scope, state))
第二步,獲取使用者授權 AccessData accessData = WeChatUtil.accessToken(WeChatUtil.newAccessParam(code, appId, security));
第三步,獲取使用者資料 WeChatUser wxUserInfo = accessData.getUser();