美文网首页服务端开发实战微信公众号开发-Java微信
Java微信公众号开发 - 获取用户信息

Java微信公众号开发 - 获取用户信息

作者: SteinsGate | 来源:发表于2016-05-18 15:37 被阅读3737次

    本文旨在提供一个Java开发微信公众号服务器的一个入门级别教程,由于本人水平有限,文中若出现错误欢迎同学们指正!作者邮箱luo.xuelin@nclantuo.com。本文欢迎转载,但请注明出处来自SteinsGate博客!
    俗话说的好,什么教程都比不上官方开发者文档。所以,微信开发者开发文档在此:开发者文档

    目录

    <a name="part1">一、网页授权获取用户信息</a>

    1、网页授权的说明

    网页授权 即用户在微信客户端访问第三方网页时,可以通过网页授权机制,来获取用户的基本信息,从而实现业务逻辑。例如登陆、注册等。
    openid 即用户相对于一个公众号来说的唯一标识,可以理解成在此公众号内的用户ID

    配置回调域名
    在微信公众号使用网页授权之前,开发者需要到公众平台的 开发 > 接口权限 菜单中的网页授权获取用户基本信息栏配置授权回调域名,且只需要填写域名,不需要加http://等协议头。
    回调域名必须为全域名。比如配置的域名为www.baidu.com,配置以后此域名下的页面http://www.baidu.com/code.htmlhttp://www.baidu.com/test/login.html都可以进行网页授权。但http://tieba.baidu.com之类的无法进行网页授权。

    网页授权两种scope的区别
    snsapi_base 为scope发起的网页授权,是用来获取进入页面用户的openid的,并且是静默授权并自动跳转到回调页面。用户并不会感知到授权过程直接进入了第三方的页面。
    snsapi_userinfo 为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动确认,并且由于用户确认过,所以开发者也可以获取到未关注用户的基本信息。

    特殊场景下的静默授权
    上面已提到,对于已snsapi_base为scope的网页授权,就静默授权,用户不会感知到。
    对于已关注公众号的用户,如果是从公众号的会话或者是菜单进入的网页授权页面,即使scope是snsapi_userinfo,也是静默授权。

    网页授权access_token与普通access_token的区别
    网页授权是通过Oauth2.0机制实现的,在用户授权给公众号后,公众号可以获取到一个网页授权特有的接口调用凭据(网页授权access_token),通过网页授权access_token可以进行授权后接口调用,如获取用户基本信息。
    其他的微信接口,需要通过 获取access_token 接口来获取普通的access_token

    2、网页授权的流程

    网页授权的流程
    网页授权的流程大致可以分为以下五步:

    • 生成网页授权URL
    • 引导用户进入授权页面并同意授权,获取code
    • 通过code换去网页授权access_token
    • 如果需要,开发者可以刷新网页授权access_token,避免过期
    • 通过网页授权access_token和openid获取用户基本信息

    2.1、生成网页授权URL
    接口地址

    https://open.weixin.qq.com/connect/oauth2/authorize?
    
    参数 是否必须 说明
    appid 公众号的唯一标识
    redirect_uri 授权后重定向的回调链接地址,请使用urlencode对链接进行处理
    response_type 返回类型,填code
    scope snsapi_userinfo、snsapi_base
    state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
    wechat_redirect 无论直接打开还是做页面302重定向时候,必须带此参数

    一个完整的网页授权URL如下:

    https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxd91aa2e2fab6&redirect_uri=http%3A%2F%2Fwww.baidu.com&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
    

    当用户点进入URL时就会进入授权界面,如下:

    2.2、用户同意授权后
    如果用户同意授权,页面就会跳转到redirect_uri

    code:code作为换取access_token的票据,每次用户授权带上的code是不一样的,code只能用一次,且5分钟未使用自动过期。

    跳转到重定向地址后,开发者可以直接在请求参数中获取到code。

    2.3、code换取access_token

    此处获取到的access_token与其他接口需要使用到的access_token是不同的。如果网页授权使用的scope是snsapi_base,则在此处获取到access_token的同时,也获取到了openid,snsapi_base的流程也到此结束。

    请求地址

    https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code 
    

    参数说明

    参数 是否必须 说明
    appid 公众号的唯一标识
    secret 公众号的appsecret
    code 前面获取到的code
    grant_type 填写authorization_code

    返回说明
    请求正确时的返回数据

    { 
     "access_token":"ACCESS_TOKEN",    
     "expires_in":7200,    
     "refresh_token":"REFRESH_TOKEN",    
     "openid":"OPENID",    
     "scope":"SCOPE" 
    }
    
    参数 说明
    access_token 网页授权接口调用凭证
    expires_in access_token接口调用凭证超时时间,单位(秒)
    refresh_token 用户刷新access_token需要用到的token
    openid 用户唯一标识
    scope 用户授权的作用域

    示例代码

    String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    Map<String, String> params = new HashMap<String, String>();
    params.put("APPID", appid);
    params.put("SECRET", appsecret);
    params.put("CODE", code);
    
    JSONObject json = HttpUtil.get(StringFormat.format(url, params));
    if(json != null){
        boolean isErr = json.containsKey("errcode");
        if(isErr){//请求失败
            String errCode = json.getString("errcode");
            String errMsg = json.getString("errmsg");
        }else{
            String accessToken = json.getString("access_token");
            int expires = json.getInt("expires_in");
            String refreshToken = json.getString("refresh_token");
            String openid = json.getString("openid");
            String scope = json.getString("scope");
        }
    }
    

    2.4、验证access_token是否有效
    请求地址

    https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID 
    

    参数说明

    参数 是否必须 说明
    access_token 网页授权接口调用凭证
    openid 用户的唯一标识

    返回说明
    请求正确时的返回数据

    { "errcode":0,"errmsg":"ok"}
    

    示例代码

    String url = "https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID";
    Map<String, String> params = new HashMap<String, String>();
    params.put("ACCESS_TOKEN", access_token);
    params.put("OPENID", openid);
    
    JSONObject json = HttpUtil.get(StringFormat.format(url, params));
    if(json != null){
        String errCode = json.getString("errcode");
        String errMsg = json.getString("errmsg");
    }
    

    2.5、刷新access_token(若有必要)

    由于access_token有效期比较短,当access_token失效后,可以使用refresh_token进行刷新,refresh_token的有效期为30天。refresh_token失效后需要用户重新授权。

    请求地址

    https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
    

    参数说明

    参数 是否必须 说明
    appid 公众号的唯一标识
    grant_type 填写refresh_token
    refresh_token 填写获取到的refresh_token参数

    返回说明
    请求正确时的返回数据

    { 
     "access_token":"ACCESS_TOKEN",  
     "expires_in":7200,   
     "refresh_token":"REFRESH_TOKEN",   
     "openid":"OPENID",   
     "scope":"SCOPE" 
    }
    
    参数 说明
    access_token 网页授权接口调用凭证
    expires_in access_token接口调用凭证超时时间,单位(秒)
    refresh_token 用户刷新access_token需要用到的token
    openid 用户唯一标识
    scope 用户授权的作用域

    示例代码

    String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";
    Map<String, String> params = new HashMap<String, String>();
    params.put("APPID", appid);
    params.put("REFRESH_TOKEN", refresh_token);
    
    JSONObject json = HttpUtil.get(StringFormat.format(url, params));
    if(json != null){
        boolean isErr = json.containsKey("errcode");
        if(isErr){//请求失败
            String errCode = json.getString("errcode");
            String errMsg = json.getString("errmsg");
        }else{
            String accessToken = json.getString("access_token");
            int expires = json.getInt("expires_in");
            String refreshToken = json.getString("refresh_token");
            String openid = json.getString("openid");
            String scope = json.getString("scope");
        }
    }
    

    2.6、获取用户信息(当scope为snsapi_userinfo)
    请求地址

    https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN 
    

    参数说明

    参数 是否必须 说明
    access_token 网页授权接口调用凭证
    openid 用户的唯一标识
    lang 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语

    返回说明
    请求正确时的返回数据

    {
     "openid":"OPENID",  
     "nickname":"NICKNAME",   
     "sex":"1",   
     "province":"PROVINCE"   
     "city":"CITY",   
     "country":"COUNTRY",    
     "headimgurl":"http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ
    4eMsv84eavHiaiceqxibJxCfHe/46",  
    "privilege":[ "PRIVILEGE1","PRIVILEGE2"],    
     "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" 
    } 
    
    参数 说明
    openid 用户的唯一标识
    nickname 用户昵称
    sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
    province 用户个人资料填写的省份
    city 普通用户个人资料填写的城市
    country 国家,如中国为CN
    headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
    privilege 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)
    unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。

    示例代码

    CloseableHttpClient httpclient = HttpClients.createDefault();
    HttpGet httpget = new HttpGet("https://api.weixin.qq.com/sns/userinfo?access_token="+ access_token +"&openid="+ openid +"&lang="+ lang +"");
    CloseableHttpResponse response = httpclient.execute(httpget);
    JSONObject json = null;
    try {
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == HttpStatus.SC_OK) {
            HttpEntity entity = response.getEntity();
            InputStream inStream = entity.getContent(); // 获取请求参数数据
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
            
            outStream.close();
            inStream.close();
            String j = new String(outStream.toByteArray(), "utf-8");
            json = JSONObject.fromObject(j);
            System.out.println(result);
        }
    } finally {
        response.close();
    }
    if(json != null){        
        
        boolean isErr = json.containsKey("errcode");
        if(isErr){//请求失败
            System.out.println(json);
        }else{
            System.out.println(json);
        }
    }
    

    <a name="part2">二、根据openid获取用户信息</a>

    使用此接口的前提是已有用户的openid作为参数。
    需要注意的是,此处用到的access_token与网页授权中用到的access_token是完全不同的。此处access_token的获取方式参见Java微信公众号开发 - 开始接入

    接口地址

    https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN 
    

    参数说明

    参数 是否必须 说明
    access_token 微信接口全局调用凭证
    openid 用户的唯一标识
    lang 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语

    返回说明

    请求正确时的返回数据

    {
       "subscribe": 1, 
       "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", 
       "nickname": "Band", 
       "sex": 1, 
       "language": "zh_CN", 
       "city": "广州", 
       "province": "广东", 
       "country": "中国", 
       "headimgurl":  "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4
    eMsv84eavHiaiceqxibJxCfHe/0",
      "subscribe_time": 1382694957,
      "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
      "remark": "",
      "groupid": 0,
      "tagid_list":[128,2]
    }
    
    参数 说明
    subscribe 用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。
    openid 用户的标识,对当前公众号唯一
    nickname 用户的昵称
    sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
    city 用户所在城市
    country 用户所在国家
    province 用户所在省份
    language 用户的语言,简体中文为zh_CN
    headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
    subscribe_time 用户关注时间,为时间戳。如果用户曾多次关注,则取最后关注时间
    unionid 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
    remark 公众号运营者对粉丝的备注,公众号运营者可在微信公众平台用户管理界面对粉丝添加备注
    groupid 用户所在的分组ID(兼容旧的用户分组接口)
    tagid_list 用户被打上的标签ID列表

    示例代码

    String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=";
    url = url + access + "&openid=" + openId + "&lang=" + lang;
    CloseableHttpClient httpclient = HttpClients.createDefault();
    HttpGet httpget = new HttpGet(url);
    CloseableHttpResponse response = httpclient.execute(httpget);
    JSONObject json = null;
    try {
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == HttpStatus.SC_OK) {
            HttpEntity entity = response.getEntity();
            InputStream inStream = entity.getContent(); // 获取请求参数数据
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, len);
            }
            
            outStream.close();
            inStream.close();
            String j = new String(outStream.toByteArray(), "utf-8");
            json = JSONObject.fromObject(j);
        }
    } finally {
        response.close();
    }
    if(json != null){
        boolean isErr = json.containsKey("errcode");
        if(isErr){//请求失败
            System.out.println(json);
        }else{
            System.out.println(json);
        }
    }
    

    相关文章

      网友评论

      • 22ef108c03c0:liner20@qq.com。希望伟大的博主发下demo。感激不尽
      • bdb4154cd17e:我也是啊, 作者有没有源码愿意分享呢, 我是java小白, 感觉好难啊... 287524916@qq.com
      • 7d64d066c916:你好。我最近也在学习这个,但是有个很大的问题就是,理念多代码不知道怎么写。不知道您是否愿意分享你的源码呢?我的邮箱是381898417@qq.com 万分感谢

      本文标题:Java微信公众号开发 - 获取用户信息

      本文链接:https://www.haomeiwen.com/subject/medwrttx.html