微信公衆號開發系列(二) 網頁授權登錄

上一篇,進行了微信公衆號的服務器配置,下面開始微信公衆號的網頁授權

通過官網的文檔,可以知道網頁授權大致分爲幾步

這裏我們暫且不考慮刷新網頁授權的access_token。

第一步獲取code,這個code 可以看作是一個預授權碼,官方說法是一個用來換取access_token的票據,下面是第一步所需要的參數

第一個appid這個就是你公衆號的標識,等於你要告訴微信,用戶正在登錄哪個公衆號;回調地址,這個就是微信返回給你code的地址,等於你告訴微信你發code到這個地址上;sope,這個看需求,只是獲取openid就用snsapi_base,需要個人信息的用snsaapi_userinfo;最後帶上#wechat_redirect。記住參數的順序不要錯,微信服務器會做校驗

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

下面上代碼

 /**
     * @description 獲取回調中的code(這個可以讓前端直接去請求這個url,而不是讓後端做重定向)
     * @author zhou
     * @param
     * @return
     * @date 2019/6/8
     */
    @GetMapping(value = "/preAuth")
    public void preAuth(HttpServletResponse response)  {
        //拼接請求地址
        StringBuilder sb = new StringBuilder(WxOaUrlConfig.API_PRE_AUTH);
        sb.append("appid=").append(wxOfficialsAccountConfiguration.getAppid())
           .append("&").append("redirect_uri=").append(EncoderUtil
                .UrlEncode(wxOfficialsAccountConfiguration.getRedirectUrl()))
           .append("&").append("response_type=code")
                //獲取用戶信息
           .append("&").append("scope=snsapi_userinfo")
           .append("&").append("state=4959a8b50e8e41ad")
           .append("#wechat_redirect");
        String url = sb.toString();
        try {
            //httpUtil.doGetJson(url);
            response.sendRedirect(url);
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new HttpException(HttpErrorEnum.REQUEST_ERROR);
        }
    }

 也是比較簡單的按順序拼接好url然後以https協議重定向。(也可以讓前端去請求)

第二步

在微信端同意授權後,在回調地址接受code

appid介紹過了,code可以從回調請求的參數中獲取,secret是公衆號的密鑰開發時保存在後端。

/**
     * @description 授權回調
     * @author zhou
     * @param
     * @return
     * @date 2019/6/8
     */
    @GetMapping(value = "/authCallback")
    public WebResponse authCallBack(HttpServletRequest request){
        String code = request.getParameter("code");
        //獲取網頁授權的accessToken
        JSONObject tokenObject = wxOfficialAccountService.getWebAccessToken(code);
        if(!tokenObject.containsKey("access_token")){
            log.error(tokenObject.getString("errmsg"));
            throw new WxErrorException(tokenObject.getInteger("errcode"),tokenObject.get("errMsg").toString());
        }
        WebResponse webResponse = wxOfficialAccountService.loginInfo(tokenObject);
        return webResponse;
    }

 /**
     * @description 獲取網頁授權的accessToken
     * @author zhou
     * @param code 預授權碼
     * @return jsonObject
     * @date 2019/6/8
     */
    @Override
    public JSONObject getWebAccessToken(String code) {
        //拼裝url
        StringBuilder sb = new StringBuilder(WxOaUrlConfig.API_WEB_ACCESS_TOKEN);
        sb.append("appid=").append(wxOfficialsAccountConfiguration.getAppid())
           .append("&").append("secret=").append(wxOfficialsAccountConfiguration.getAppsecret())
           .append("&").append("code=").append(code)
           .append("&grant_type=authorization_code");
        String url = sb.toString();
        JSONObject jsonObject = null;
        try {
            jsonObject = httpUtil.doGetJson(url);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jsonObject;
    }

同樣拼裝url進行請求,這裏可以獲得access_token.這個就是獲取個人信息的憑證,它的有效期是兩小時,在有效期內可以直接調用去請求個人信息。所以在獲取後可以選擇保存在第三方緩存中,比如redis中

第三步獲取用戶信息

 /**
     * @description 登錄
     * @author zhou
     * @param tokenObject 網頁授權token信息
     * @return webResponse
     * @date 2019/6/9
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public WebResponse loginInfo(JSONObject tokenObject) {
        //網頁授權token存入redis
        redisUtil.set(tokenObject.getString("openid"),tokenObject.getString("access_token"),
                (long) 7200);
        //拼裝請求url
        StringBuilder sb = new StringBuilder(WxOaUrlConfig.API_USER_INFO);
        sb.append("access_token=").append(tokenObject.getString("access_token"))
           .append("&").append("openid=").append(tokenObject.getString("openid"))
           .append("&").append("lang=zh_CN");
        String url = sb.toString();
        OaUserVO oaUserVO = new OaUserVO();
        try {
            //獲取用戶信息
            JSONObject jsonResult = httpUtil.doGetJson(url);
            if(jsonResult.containsKey("errmsg")){
                //含有錯誤信息
                log.error(jsonResult.getString("errmsg"));
                throw new WxErrorException(jsonResult.getInteger("errcode"),
                        jsonResult.getString("errmsg"));
            }else{
                OaUser oaUser = OaUser.builder()
                        .avatar(jsonResult.getString("headimgurl"))
                        .city(jsonResult.getString("city"))
                        .country(jsonResult.getString("country"))
                        .createTime(LocalDateTime.now())
                        .deleted(false)
                        .nickName(jsonResult.getString("nickname"))
                        .openid(jsonResult.getString("openid"))
                        .province(jsonResult.getString("province"))
                        .refreshTime(LocalDateTime.now())
                        .refreshToken(tokenObject.getString("refresh_token"))
                        .sex(jsonResult.getShort("sex"))
                        .unionid(jsonResult.containsKey("unionid")?jsonResult.getString("unionid"):null)
                        .privilege(jsonResult.getString("privilege"))
                        .updateTime(LocalDateTime.now())
                        .build();
                oaUserRepository.saveAndFlush(oaUser);
                oaUserVO.setAvatar(jsonResult.getString("headimgurl"));
                oaUserVO.setNickname(jsonResult.getString("nickname"));
                oaUserVO.setOpenid(jsonResult.getString("openid"));
                oaUserVO.setUserId(oaUser.getUserId());
            }
        } catch (Exception e) {
            log.error("登錄失敗");
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new WeChatOaException(WeChatOaErrorEnum.AUTH_LOGIN_ERROR);
        }
        return WebResponse.success(oaUserVO);
    }

 

同樣的也是拼裝成url請求數據,將請求的數據存入數據庫中。這個也比較簡單,歸納一下,就是按照文檔,請求數據入庫。

到此微信公衆號網頁授權結束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章