1. 程式人生 > >微信公眾平臺 獲取access_token

微信公眾平臺 獲取access_token

前言:access_token是微信公眾平臺介面的重要引數,很多介面都需要這個引數。

一、access_token說明

access_token是公眾號的全域性唯一介面呼叫憑據,公眾號呼叫各介面時都需使用access_token。開發者需要進行妥善儲存。access_token的儲存至少要保留512個字元空間。access_token的有效期目前為2個小時,需定時重新整理,重複獲取將導致上次獲取的access_token失效。

1:公眾平臺的API呼叫所需的access_token的使用

1、建議公眾號開發者使用中控伺服器統一獲取和重新整理Access_token,其他業務邏輯伺服器所使用的access_token均來自於該中控伺服器,不應該各自去重新整理,否則容易造成衝突,導致access_token覆蓋而影響業務;
2、目前Access_token的有效期通過返回的expire_in來傳達,目前是7200秒之內的值。中控伺服器需要根據這個有效時間提前去重新整理新access_token。在重新整理過程中,中控伺服器對外輸出的依然是老access_token,此時公眾平臺後臺會保證在重新整理短時間內,新老access_token都可用,這保證了第三方業務的平滑過渡;
3、Access_token的有效時間可能會在未來有調整,所以中控伺服器不僅需要內部定時主動重新整理,還需要提供被動重新整理access_token的介面,這樣便於業務伺服器在API呼叫獲知access_token已超時的情況下,可以觸發access_token的重新整理流程。

2:access_token的生成說明

公眾號可以使用AppID和AppSecret呼叫本介面來獲取access_token。AppID和AppSecret可在“微信公眾平臺-開發-基本配置”頁中獲得(需要已經成為開發者,且帳號沒有異常狀態)。呼叫介面時,請登入“微信公眾平臺-開發-基本配置”提前將伺服器IP地址新增到IP白名單中,點選檢視設定方法,否則將無法呼叫成功
這裡寫圖片描述

二、介面呼叫請求說明

1:介面呼叫

https請求方式: GET

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

2:引數說明

引數 是否必須 說明
grant_type 獲取access_token填寫client_credential
appid 第三方使用者唯一憑證
secret 第三方使用者唯一憑證金鑰,即appsecret

3:返回說明

正常情況下,微信會返回下述JSON資料包給公眾號:

{"access_token":"ACCESS_TOKEN","expires_in":7200}

引數說明

引數 說明
access_token 獲取到的憑證
expires_in 憑證有效時間,單位:秒


錯誤時微信會返回錯誤碼等資訊,JSON資料包示例如下(該示例為AppID無效錯誤):

{"errcode":40013,"errmsg":"invalid appid"}

4:返回碼說明

返回碼 說明
-1 系統繁忙,此時請開發者稍候再試
0 請求成功
40001 AppSecret錯誤或者AppSecret不屬於這個公眾號,請開發者確認AppSecret的正確性
40002 請確保grant_type欄位值為client_credential
40164 呼叫介面的IP地址不在白名單中,請在介面IP白名單中進行設定

三、java介面開發

1:返回介面封裝類Token

/**
 * 類名: Token.java</br> 
 * 描述: 憑證</br> 
 */
public class Token {
    // 介面訪問憑證
    private String accessToken;
    // 憑證有效期,單位:秒
    private int expiresIn;

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public int getExpiresIn() {
        return expiresIn;
    }

    public void setExpiresIn(int expiresIn) {
        this.expiresIn = expiresIn;
    }
}

2:獲取介面訪問憑證

    /**
     * 獲取介面訪問憑證
     * @param appid 憑證
     * @param appsecret 金鑰
     * @return
     */
    public static Token getToken(String appid, String appsecret) {
        Token token = null;
        String requestUrl = WeixinConstants.TOKEN_URL.replace("APPID", appid).replace("APPSECRET", appsecret);
        // 發起GET請求獲取憑證
        JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);

        if (null != jsonObject) {
            try {
                token = new Token();
                token.setAccessToken(jsonObject.getString("access_token"));
                token.setExpiresIn(jsonObject.getInt("expires_in"));
            } catch (JSONException e) {
                token = null;
                // 獲取token失敗
                log.error("獲取token失敗 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return token;
    }

3:http請求工具類

   /**
     * 傳送https請求
     * @param requestUrl 請求地址
     * @param requestMethod 請求方式(GET、POST)
     * @param outputStr 提交的資料
     * @return JSONObject(通過JSONObject.get(key)的方式獲取json物件的屬性值)
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        try {
            // 建立SSLContext物件,並使用我們指定的信任管理器初始化
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 從上述SSLContext物件中得到SSLSocketFactory物件
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 設定請求方式(GET/POST)
            conn.setRequestMethod(requestMethod);

            // 當outputStr不為null時向輸出流寫資料
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意編碼格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 從輸入流讀取返回內容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            // 釋放資源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            log.error("連線超時:{}", ce);
        } catch (Exception e) {
            log.error("https請求異常:{}", e);
        }
        return jsonObject;
    }

4:信任管理器工具類

/**
 * 類名: MyX509TrustManager.java</br> 
 * 描述: 信任管理器</br> 
 */
public class MyX509TrustManager implements X509TrustManager {

    // 檢查客戶端證書
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    // 檢查伺服器端證書
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    // 返回受信任的X509證書陣列
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

四、總結

上述java介面簡單歸納就是按照介面地址通過GET方式傳遞appid和appsecret兩個引數傳送http請求,獲取access_token。看似很簡單,請求後也可以獲取access_token引數,但是微信公眾平臺的介面文件也說明了,access_token的有效期是7200秒,而且還需要中控伺服器去控制access_token的重新整理,所以建議將生產的access_token存放在redis中,redis快取的有效時間等於access_token的有效時間。這樣可以避免介面的不必要請求,減少併發量。先去redis中判斷access_token是否有效,有效就獲取,無效再去請求介面。