access_token是微信公众号开发中比较重要的数据,因为公众号的许多接口都要使用access_token来验证.具体请参考文档(RTFM).

Access Token的获取

数据结构分析

获取access_token通过向微信服务器发送get请求,请求网址如下https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

参数 说明
appid 公众号的唯一凭证
grant_type 获取 access_token 是填写 client_credential
secret 唯一凭证密钥,即公众号的 appsecret
如正常会返回json数据包,包含access_token,expires_in(一般是7200,表示access_token的有效时间为2h)这两个参数.现在需要做的便是向服务器发送请求,并解析json数据包,拿到access_token就大功告成了.

具体实现

首先当然是写一个acess_token的实体类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public class AccessToken {
    private String access_token;
    private int expires_in;

    public int getExpires_in() {
        return expires_in;
    }

    public void setExpires_in(int expires_in) {
        this.expires_in = expires_in;
    }

    public String getAccess_token() {

        return access_token;
    }

    public void setAccess_token(String access_token) {
        this.access_token = access_token;
    }
}

接着新建一个WechatUtil类(主要用来和微信服务器交互),上面说过,获取access_token的http的请求方式为get.写一个doGet()方法.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    public JSONObject doGet(String url) {
        HttpURLConnection connection = null;
        BufferedReader reader = null;
        JSONObject jsonObject = null;
        try {

            URL url1 = new URL(url);
            connection = (HttpURLConnection) url1.openConnection();
            connection.setRequestMethod("GET");
            connection.setConnectTimeout(8000);
            connection.setReadTimeout(8000);
            InputStream in = connection.getInputStream();
            //读取输入流
            reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            jsonObject = JSONObject.fromObject(response.toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return jsonObject;
    }

可以看到这是一个很简单的发送HTTP请求代码,然后返回的是一个jsonObject.接着只要处理这个jsonObject就可以了.继续修改WechatUtil的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    public AccessToken getAcessToken() {
        AccessToken token = new AccessToken();
        String url = ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
        JSONObject jsonObject = doGet(url);
        if (jsonObject != null) {
            token.setAccess_token(jsonObject.getString("access_token"));
            token.setExpires_in(jsonObject.getInt("expires_in"));
        }
        return token;
    }

getAcessToken()方法调用了doGet()方法,并把含有appid和appsercet的URL传入,最终得到access_token.新建一个测试类,WechatInitial.代码如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    public static void main(String[] args){
        try{
            WechatUtil wechatUtil=new WechatUtil();
            AccessToken token=wechatUtil.getAcessToken();
            String access_token=token.getAccess_token();
            int expires_in=token.getExpires_in();
            System.out.println("Access_token:"+access_token);
            }catch (Exception e){
            e.printStackTrace();
        }
    }

结果如图:

本地持久化(todo)

由于acess_token的有效期是两个小时,而且一天的获取上限是2000次,当用户较多是,重复获取可以会造成超过次数上限,而影响业务. 目前我的想法是将access_token保存到本地,并且定时刷新.(也可以保存到本地,调用替他接口是根据微信全局返回码判断是否过期,如过期,则主动刷新.