安卓端微信第三方登陸與服務器端的根據CODE獲取微信用戶信息

參考博客地址:https://www.cnblogs.com/liuhongfeng/p/5099149.html

    今日的打雜任務之二是實現安卓端的微信第三方登陸,客戶端的同學提出的要求是,向服務器發送code,服務器能夠返回用戶的開放個人信息。雖然理論上我只需要負責服務端的內容就可以了,但爲了方便測試,我從他那裏要來了一個簡單的第三方登陸的安卓Demo(說實話,光是跑通就花了我半天,也是很廢了)。所以接下來我主要講一下我服務端的實現,和在跑客戶端的Demo的時候碰到的一些小問題吧。

客戶端:

    首先,需要明確的是,已經申請好了appid和secret,而且項目文件夾的名字微信官方規定的,所以我就直接在客戶端同學給我的代碼上進行修改增加功能了。最開始跑程序的時候,當然是各種環境的問題,包括gradle的版本啊,sdk的版本啊巴拉巴拉的,改好了也就差不多了,然後我就在debug模式下直接開始測試了。我的APP界面大概長這個樣子,最頂上是個TextView,理論上應該現實CODE,下面的微信圖標就是個按鈕,按按鈕後,詢問用戶是否確認授權之類的。


    剛開始的時候,按了按鈕毫無反應,log一直打印的是onResp default errCode -6,於是我乖乖去百度了,查到的結果是驗證簽名錯了(懵,驗證簽名是什麼鬼)。各種查以後,我知道原來在debug模式下,和發佈的release模式下,驗證簽名會不同(忘記是不是這麼解釋來着),總之就是需要打包成帶簽名的APK,具體方法可自行百度或Google。再安裝到我的安卓機上後,果然成功返回了CODE。


    提示:因爲我一開始就選擇了信任程序,所以不存在權限問題,如果碰到閃退什麼的問題,可以考慮看看是不是有什麼權限沒打開。

服務端

    服務端的實現我幾乎完全是參考的在開頭我貼的那個博客中的代碼的,首先自然我創建了一個WeChatServlet類,用於接收客戶端發過來的CODE與向客戶端返回用戶信息的功能。當然,和我的上一篇博客一樣,需要關注在web.xml文件裏是否對該Servlet進行了設置。

@WebServlet(name = "WeChatServlet")
public class WeChatServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        PrintWriter out = response.getWriter();

        String username = "";
        final String code = request.getParameter("code");

        WeChatOauth2Token wat;
        wat = WeChatLoadUtil.getAccess(code);

        String accesToken = wat.getAccessToken();
        String openid = wat.getOpenId();
        //        out.print("openid:" + wat.getOpenId() + " ; accesstoken:" + wat.getAccessToken());

        WeChatUserInfo userInfo;
        userInfo = WeChatLoadUtil.getUserInfo(accesToken, openid);
        out.print("nickName:" + userInfo.getNickName() + " ; sex:" + userInfo.getSex());
//        out.print("code:" + code);

        out.flush();
        out.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

    爲了方便測試數據通訊,我在上一篇博客的基礎上,又對我的“index.jsp”進行了修改,增加了輸入code和發送code的輸入框與按鈕。


    當然這個code是我隨意造的,所以必然不可能獲取到與該code對應的用戶信息,只能返回我自己定義的字符串和空的結果字符串了,但至少我可以確定我的WebServlet正常工作了。


    在獲取用戶信息前,我需要首先獲取的是ACCESS_TOKEN和OpenID,具體的獲取函數和我的參考博客裏是一樣的(包括CommonUtil類我是直接複製過來用了,所以就不貼出來了),其中的WeChatOauth2Token類變量,和參考博中的結構基本接近,只不過我暫時只有OpenId和ACCESS_TOKEN兩個變量和它們的get和set函數而已。

public static WeChatOauth2Token getAccess(String code){
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                "appid=" + Constants.WEIXIN_APP_ID +
                "&secret=" + Constants.WEIXIN_APP_SECRET +
                "&code=" + code +
                "&grant_type=authorization_code";
        JSONObject jsonObject = CommonUtil.httpsRequest(url,"GET",null);
        if(null != jsonObject){
            try{
                wat.setAccessToken(jsonObject.getString("access_token"));
                wat.setOpenId(jsonObject.getString("openid"));
//                user.setNickName(jsonObject.getString("nickname"));
//                user.setHeadImgUrl(jsonObject.getString("headimgurl"));
//                user.setOpenId(jsonObject.getString("openid"));
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return wat;
    }

    經過以上步驟,我已經獲得了ACCESS_TOKEN和OpenID,根據這兩個值, 用類似的方法,就可以獲得用戶的信息了。其中的userInfo是WeChatUserInfo類型的變量,其主要包含的信息有用戶的id,用戶的暱稱,用戶的性別和用戶的頭像地址以及它們各自的get和set函數。

public static WeChatUserInfo getUserInfo(String accessToken,String openId){
        // 拼接請求地址
        String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
        requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
        // 通過網頁授權獲取用戶信息
        JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);

        if (null != jsonObject) {
            try {
                // 用戶的標識
                userInfo.setOpenId(jsonObject.getString("openid"));
                // 暱稱
//                userInfo.setNickname(jsonObject.getString("nickname"));
                userInfo.setNickName(jsonObject.getString("nickname"));
                //性別
                userInfo.setSex(jsonObject.getString("sex"));
                // 用戶頭像
                userInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
            } catch (Exception e) {
                userInfo = null;
                int errorCode = jsonObject.getInt("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                e.printStackTrace();
            }
        }
        return userInfo;
    }

    在我的WebServlet類中,我調用了以上提到的兩個函數,並最終將用戶的信息(我只返回了暱稱和性別)返回給了客戶端,至此,服務端的基本功能也就實現了。隨後我將該javaWeb程序部署到了我的阿里雲服務器上,然後進行了測試,客戶端的反饋結果大概長這個樣子,上面打印的是“code------nickname ; sex”(微信名暴露了)。


問題:

    當然,怎麼可能這麼順利!服務端我也是碰到了不少問題的!小問題也就不提了,我碰到的一個十分可怕的問題是。。我一開始甚至不知道JSONObject從哪裏來的,昨天的經歷告訴我,這一定是,某個外部依賴庫吧。於是我去百度了JSONObject庫,然後順利找到了它,那麼它究竟是幹嘛的呢?此處偷偷引用一句一個博主的結束:JSONObject-lib包是一個beans,collections,maps,java arrays和xml和JSON互相轉換的包,我再非常菜鳥得概括一下,大概就是說,有了它,在我的java文件裏也可以創建JSONObject類型的變量的,嗯。

    然而在部署到tomcat上,利用Web網頁進行測試時,依舊報錯了。然後找到了https://blog.csdn.net/qq_40646143/article/details/79148619這個解決方法,下載了在這個博客中提到的需要的所有jar包,然後放到了tomcat的lib目錄下以後,果然(貌似)問題就解決了(我是到處找的jar包,但是也看到有這些在struct的lib中都能找到,大家可以找找看)。


    但是我因爲沒有找到博主提到的commons-lang-2.5.jar的版本,所以就下載了3-3.1,依舊報錯了(emm,截圖忘記截了0 0),查到的解決方法是再下一個2.6版本的,放到tomcat的lib目錄下後,果然(真)解決了。


    爲了方便像我這樣子CSDN積分0的窮苦孩子,我把這些jar包都打包放網盤了,請自取。

    鏈接:https://pan.baidu.com/s/11wdWgJo8KT1MjVedw5xwBw

    密碼:wemq

    最後的最後,如果有任何建議或者發現我有任何的錯誤,請大家在評論裏指出,我一定會好好接受,爭取早日成爲一名正式的 程序媛!


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