1. 程式人生 > >[3]java微信開發-獲取access_token

[3]java微信開發-獲取access_token

什麼是access_token?

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

access_token有什麼用?

   access_token 作為公眾號唯一的介面呼叫憑據,顧名思義就公眾號呼叫微信提供的介面時都需要提供access_token,否則無法正常呼叫微信提供的介面。比如建立自定義選單介面,獲取微信伺服器ip以及後面的JS-SDK 中獲取api_ticket等等介面都會用到access_token。

怎麼獲取access_token?

通過GET請求介面:

介面引數說明

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

從表格可看出,呼叫獲取access_token的介面需要三個引數,第一個引數用client_credential就行。第二、三個引數對應“微信公眾平臺-開發-基本配置”微信公眾號的AppID和AppSecret(開發者測試賬號中測試號資訊中的AppID和AppSecret)。

返回說明

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

{“access_token”:”ACCESS_TOKEN”,”expires_in”:7200}

引數說明

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

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

{“errcode”:40013,”errmsg”:”invalid appid”}

返回碼說明

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

獲取access_token程式碼實現

1、實現X509TrustManager信任管理器。 

  https請求用到SSL技術,需要新增一個信任管理器。至於為什麼,這裡不做詳細解釋。感興趣的童鞋可以自己去學習相關知識。

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
 * 描述:HTTPS證書信任管理器,實現X509TrustManager介面
 * @author pwu
 * 建立日期:2017-6-15
 */
public class MyX509TrustManager implements X509TrustManager {
    //驗證客戶端證書
    @Override
    public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
        // TODO Auto-generated method stub

    }

    //驗證服務端證書
    @Override
    public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
        // TODO Auto-generated method stub

    }

    //返回被信任的證書陣列
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        // TODO Auto-generated method stub
        return null;
    }

}

2、https請求程式碼實現

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import com.alibaba.fastjson.JSONObject;
import com.carwash.modules.wechat.common.MyX509TrustManager;
public class HttpsUtils {

    /**
     * 描述:  發起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;
        StringBuffer buffer = new StringBuffer();
        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 httpsConn = (HttpsURLConnection) url.openConnection();
            httpsConn.setSSLSocketFactory(ssf);

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

            // 當有資料需要提交時
            if (null != outputStr) {
                OutputStream outputStream = httpsConn.getOutputStream();
                // 注意編碼格式,防止中文亂碼
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 將返回的輸入流轉換成字串
            InputStream inputStream = httpsConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

            String str = null;
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 釋放資源
            inputStream.close();
            inputStream = null;
            httpsConn.disconnect();
            jsonObject = JSONObject.parseObject(buffer.toString());
        } catch (ConnectException ce) {
            System.err.println("連線超時:"+ce);
        } catch (Exception e) {
            System.err.println("https請求異常:"+e);
        }
        return jsonObject;
    }
}

3、獲取access_token實現

import com.alibaba.fastjson.JSONObject;
import com.carwash.modules.wechat.common.Globle;
import com.carwash.modules.wechat.entity.WxAccessToken;
/**
 * 描述:微信access_token工具類
 * @author pwu
 * 建立時間:2017-6-15
 * @version V1.0
 */
public class AccessTokenUtils {
    // 獲取access_token的介面地址(GET) 限2000(次/天)
    public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

    public static WxAccessToken getAccessToken(){
        //TODO 持久化token
        WxAccessToken token = null;
        //向微信請求access_token的url,由appid和appsecret組合微信請求介面構成
        //Globle.appid和Globle.appsecret即為自己的appid和appsecret
        String requestUrl = access_token_url.replace("APPID", Globle.appid).replace("APPSECRET", Globle.appsecret);
        //發起https GET請求獲取憑證json
        JSONObject jsonObject = HttpsUtils.httpsRequest(requestUrl, "GET", null);   
        if(jsonObject != null){
            token = new WxAccessToken();
            token.setAccessToken(jsonObject.getString("access_token"));
            token.setExpiresIn(jsonObject.getIntValue("expires_in"));
        }
        return token;
    }
}

結語 

   至此,微信access_token的獲取完成,文章憑藉的是網上查詢資料及個人理解整理出來的,可能比較粗糙,如果有不對的地方,希望大家指出來,我及時改正避免誤導其他人。如有看完這篇部落格還不知道怎麼獲取access_token的朋友,歡迎留言或私信給我,我會及時解答。