玩玩微信公眾號Java版之三:access_token及存儲access_token


微信官方參考文檔:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

 
基本說明:
access_token是公眾號的全局唯一接口調用憑據,公眾號調用各接口時都需使用access_token。開發者需要進行妥善保存。access_token的存儲至少要保留512個字符空間。access_token的有效期目前為2個小時,需定時刷新,重復獲取將導致上次獲取的access_token失效。
 
調用方式:
公眾號可以使用AppID和AppSecret調用本接口來獲取access_token。AppID和AppSecret可在“微信公眾平台-開發-基本配置”頁中獲得(需要已經成為開發者,且帳號沒有異常狀態)。調用接口時,請登錄“微信公眾平台-開發-基本配置”提前將服務器IP地址添加到IP白名單中,點擊查看設置方法,否則將無法調用成功。
 
特別說明:建議公眾號開發者使用中控服務器統一獲取和刷新Access_token,其他業務邏輯服務器所使用的access_token均來自於該中控服務器,不應該各自去刷新,否則容易造成沖突,導致access_token覆蓋而影響業務;
 
了解這些信息后,我們需要理解確定如下幾點:
1、統一token調用方法,其他地方需用到token均采用本方法獲取;
2、請求獲取token信息接口的實現;
3、token數據存儲至本地數據庫;
4、判斷是否需要重新獲取token還是直接從本地數據庫中查詢;
 
下面來進行具體的實現:
首先看一下整體的類圖:
 

那么在獲取token時,可以根據appid和appsecret來獲取,其中判斷是否需要更新的方法為:

能否獲取到當前仍有效的token:查詢SQL如下:
 

對應表結構參考如下:

對應的java代碼如下: 如果能獲取到,那么直接返回: 

 1     /**
 2      * 通過參數獲取Token信息
 3      * @param appID
 4      * @param appSceret
 5      * @return
 6      */
 7     public Token getToken(String appID, String appSceret)
 8     {
 9         mAppID = appID;
10         mAppSceret = appSceret;
11 
12         // 1.確定是否要更新token,無需更新則直接直接返回獲取的token
13         if (updateToken())
14         {
15             return mToken;
16         }
17 
18         // 2. 如需更新
19         if (!getTokenbyhttps(mAppID, mAppSceret))
20         {
21             System.out.println("獲取失敗!");
22             return null;
23         }
24 
25         return mToken;
26     }
View Code

 其中明細方法實現為:

 1     /**
 2      * 獲取Token信息
 3      * @return
 4      */
 5     private boolean updateToken()
 6     {
 7         // 查詢數據庫數據,如果有則不用更新,無則需要更新
 8         Connection con = null;
 9         PreparedStatement stmt = null;
10         ResultSet rs = null;
11         // 判斷當前token是否在有效時間內
12         String sql = " select * from token where appid ='" + mAppID + "' and appsecret ='" + mAppSceret
13                 + "' and ( current_timestamp -createtime) <expires_in order by createTime desc limit 0,1";
14         try
15         {
16             // 創建數據庫鏈接
17             con = DBConnPool.getConnection();
18             // 創建處理器
19             stmt = con.prepareStatement(sql);
20             // 查詢Token,讀取1條記錄
21             rs = stmt.executeQuery();
22             if (rs.next())
23             {
24                 mToken.setTokenid(rs.getString("tokenid"));
25                 mToken.setToken(rs.getString("token"));
26                 mToken.setExpires_in(rs.getInt("expires_in"));
27                 mToken.setAppid(rs.getString("appid"));
28                 mToken.setAppsecret(rs.getString("appsecret"));
29             }
30             else
31             {
32                 System.out.println("未查詢到對應token");
33                 return false;
34             }
35         }
36         catch (Exception e)
37         {
38             // TODO: handle exception
39             return false;
40         }
41 
42         System.out.println(mToken.getToken());
43 
44         return true;
45     }
View Code

如果需要獲取新的token,則:
 1     /**
 2      * 通過https請求獲取token
 3      * @param appID
 4      * @param appSceret
 5      * @return
 6      */
 7     private boolean getTokenbyhttps(String appID, String appSceret)
 8     {
 9         String current_time = new Date().getTime() + "";
10 
11         try
12         {
13             // 請求地址
14             String path = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
15                     + appID + "&secret=" + appSceret;
16             
17             String strResp = WeChatUtil.doHttpsGet(path, "");
18             System.out.println(strResp);
19             
20             // 解析獲取的token信息
21             Map<String, Object> tMap = WeChatUtil.jsonToMap(strResp);
22 
23             System.out.println(tMap.toString());
24 
25             mToken.setTokenid(WeChatUtil.getMaxTokenID());
26             mToken.setToken((String) tMap.get("access_token"));
27             mToken.setExpires_in(Integer.parseInt((String) tMap.get("expires_in")));
28             mToken.setAppid(appID);
29             mToken.setAppsecret(appSceret);
30             mToken.setCreatetime(current_time);
31 
32             System.out.println(mToken.getToken());
33 
34         }
35         catch (HttpException e)
36         {
37             // TODO Auto-generated catch block
38             e.printStackTrace();
39         }
40         catch (IOException e)
41         {
42             // TODO Auto-generated catch block
43             e.printStackTrace();
44         }
45 
46         // 存儲token至數據庫
47         saveToken(mToken);
48 
49         return true;
50     }
51 
52     /**
53      * 保存Token信息
54      * @return
55      */
56     private boolean saveToken(Token token)
57     {
58         PreparedStatement pst = null;
59         Connection conn = null;
60         try
61         {
62             Token tToken = token.clone();
63 
64             System.out.println(tToken.getTokenid() + tToken.getToken());
65 
66             conn = DBConnPool.getConnection();
67             // 創建預處理器
68             pst = conn.prepareStatement("insert into token(tokenid, token, expires_in,appid, appsecret,createtime) values (?,?,?,?,?,?)");
69 
70             pst.setString(1, tToken.getTokenid());
71             pst.setString(2, tToken.getToken());
72             pst.setInt(3, tToken.getExpires_in());
73             pst.setString(4, tToken.getAppid());
74             pst.setString(5, tToken.getAppsecret());
75             long now = new Date().getTime();
76             pst.setTimestamp(6, new java.sql.Timestamp(now));
77             pst.execute();
78 
79         }
80         catch (CloneNotSupportedException e)
81         {
82             // TODO Auto-generated catch block
83             e.printStackTrace();
84             return false;
85         }
86         catch (SQLException e)
87         {
88             // TODO Auto-generated catch block
89             e.printStackTrace();
90             return false;
91         }
92         catch (Exception e)
93         {
94             // TODO: handle exception
95             System.out.println("出現額外異常");
96         }
97         return true;
98     }
View Code

對於https的GET和POST調用,可以寫2個公共方法,具體實現可參考:

 1     /**
 2      * HTTPS請求Get方法調用
 3      * @param path
 4      * @param requestData
 5      * @return
 6      * @throws HttpException
 7      * @throws IOException
 8      */
 9     public static String doHttpsGet(String path, String requestData) throws HttpException, IOException
10     {
11         // 創建https請求,未默認證書,可自行添加
12         // 設置編碼
13         HttpClient httpClient = new HttpClient();
14         GetMethod getMethod = new GetMethod(path);
15         httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
16 
17         httpClient.executeMethod(getMethod);
18 
19         // 讀取內容
20         byte[] responseBody = getMethod.getResponseBody();
21         String strResp = new String(responseBody, "UTF-8");
22 
23         System.out.println(strResp);
24 
25         getMethod.releaseConnection();
26 
27         return strResp;
28     }
29 
30     /**
31      * HTTPS請求Post方法調用
32      * @param path
33      * @param requestData
34      * @return
35      * @throws HttpException
36      * @throws IOException
37      */
38     public static String doHttpsPost(String path, String requestData) throws HttpException, IOException
39     {
40         // 創建https請求,未默認證書,可自行添加
41         String strResp ="";
42         HttpClient httpClient = new HttpClient();
43         PostMethod postMethod = new PostMethod(path);
44         // 設置編碼
45         httpClient.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
46         
47         System.out.println("path:" + path);
48         System.out.println("requestData:" + requestData);
49 
50         postMethod.setRequestBody(requestData);
51 
52         long start = System.currentTimeMillis();
53         // 執行getMethod
54         int statusCode = httpClient.executeMethod(postMethod);
55         System.out.println("cost:" + (System.currentTimeMillis() - start));
56         // 失敗
57         if (statusCode != HttpStatus.SC_OK)
58         {
59             System.out.println("Method failed: " + postMethod.getStatusLine());
60             // 讀取內容
61             byte[] responseBody = postMethod.getResponseBody();
62             // 處理內容
63             strResp = new String(responseBody, "UTF-8");
64             System.out.println(strResp);
65         }
66         else
67         {
68             // 讀取內容
69             byte[] responseBody = postMethod.getResponseBody();
70             strResp = new String(responseBody, "UTF-8");
71             System.out.println("服務器返回:" + strResp);
72         }
73 
74         postMethod.releaseConnection();
75 
76         return strResp;
77     }
View Code

 

需要加入返回是json,處理json 需要json對應的jar,另外需要用到httpclient 的jar包。
獲取token后,要進行數據存儲,再返回即可。
 
獲取access_token 這里就結束了,后面的功能接口均需要用到 access_token,這里寫的獲取方法后面可以直接調用,很方便了喲~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM