access_token是公衆號接口調用的憑據,公衆號調用各接口時均需使用access_token。
html
例如:
java
1)建立自定義菜單接口:https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN json
2)獲取素材列表接口:https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN api
3)獲取用戶基本信息接口:https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN 緩存
等等,這些接口的請求地址均須要一個ACCESS_TOKEN參數,該參數就須要調用獲取access_token接口來獲取服務器
注意:微信
1)access_token有時效性,當前有效時間爲7200秒,須要的存儲空間爲512個字符空間,須要注意的是,微信後期有可能會改這個access_token的過時時間併發
2)若是在佈署中有多臺業務邏輯服務器均在本身的程序中獲取access_token,這將形成屢次刷新access_token的狀況,建議佈署中經過一臺中控服務器來統一獲取,或者將access_token存入緩存中統一讀取app
一、接口請求地址:ide
http請求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
二、請求參數說明:
參數 | 是否必須 | 說明 |
grant_type | 是 | 獲取access_token固定爲client_credential |
appid | 是 | 第三方用戶惟一任證 |
secret | 是 | 第三方用戶惟一任證密鑰 |
注:appid和secret對應的是公衆平臺後臺中,【開發】選項中的【基本配置】中AppID和AppSecret
三、返回說明:
1)成功
{"access_token":"ACCESS_TOKEN","expires_in":7200}
2)失敗
{"errcode":40013,"errmsg":"invalid appid"}
下面是access_token獲取的java實現,注該代碼中json解析使用到了阿里巴巴的fastjson
package cn.kolbe.wechat.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.Date; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; /** * 獲取微信accessToken * @author admin * */ public class AccessTokenUtil { private static final String APP_ID = "xxxxxxx"; private static final String APP_SECRET = "xxxxxx"; // 當前程序使用的accessToken private static String accessToken = ""; // 微信獲取accessToken的接口地址 private static final String GET_ACCESS_TOKEN_API = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + APP_ID + "&secret=" + APP_SECRET; // accessToken的過時時效 private static final int EXPIRED_SECONDS = 7200; // 當前最後更新accessToken的日期 private static Date latestDate = new Date(); /** * 獲取accessToken * @return */ public static String getToken() { Date now = new Date(); if((now.getTime() - latestDate.getTime()) < EXPIRED_SECONDS*1000 && !accessToken.equals("")) { System.out.println("已經存在accessToken," + accessToken); return accessToken; } else { // 防止併發環境下,重複更新accessToken synchronized(AccessTokenUtil.class) { if((now.getTime() - latestDate.getTime()) < EXPIRED_SECONDS*1000 && !accessToken.equals("")) { System.out.println("accessToken已經被更新過," + accessToken); return accessToken; } System.out.println("accessToken過時,從新生成," + accessToken); latestDate = new Date(); JSONObject json = JSON.parseObject(sendGet(GET_ACCESS_TOKEN_API)); accessToken = json.getString("access_token"); return accessToken; } } } /** * 簡易發送Http的Get請求 * @param urlStr * @return */ private static String sendGet(String urlStr) { URL url = null; URLConnection conn = null; BufferedReader reader = null; try { url = new URL(urlStr); conn = url.openConnection(); conn.connect(); reader = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8")); StringBuilder result = new StringBuilder(); String s = new String(); while((s = reader.readLine()) != null) { result.append(s); } return result.toString(); } catch(Exception e) { e.printStackTrace(); return null; } finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 測試併發環境下,獲取accessToken * @param args * @throws Exception */ public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newCachedThreadPool(); for(int i = 0; i < 100; i++) { if(i % 10 == 0) { Thread.sleep(1000); } executor.submit(new AccessTokenUtil.AccessTokenThread()); } } /** * 模擬併發環境下,獲取accessToken * @author admin * */ public static class AccessTokenThread implements Runnable { @Override public void run() { AccessTokenUtil.getToken(); } } }
注:
1)該代碼中並無考慮錯誤狀況下的處理方式(建議提供一個強制刷新accessToken的方法)
2)刷新accessToken時,須要注意考慮併發狀況下,同時多個線程發現accessToken過時,重複去刷新accessToken的狀況,代碼中已經經過加鎖來防止這種狀況的發生