安卓端微信第三方登陆与服务器端的根据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

    最后的最后,如果有任何建议或者发现我有任何的错误,请大家在评论里指出,我一定会好好接受,争取早日成为一名正式的 程序媛!


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