| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- package com.kingdee.eas.custom.beisen.utils;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import okhttp3.*;
- import org.apache.log4j.Logger;
- import java.io.IOException;
- import java.util.Map;
- import java.util.concurrent.TimeUnit;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- public class BeisenTokenManager {
- private static final Logger logger = Logger.getLogger(BeisenTokenManager.class);
- private static final MediaType JSON_MEDIA_TYPE = MediaType.parse("application/json; charset=utf-8");
- private static final long EXPIRY_BUFFER = 300_000; // 5分钟缓冲时间
- private final OkHttpClient httpClient;
- private final Lock lock = new ReentrantLock();
- private volatile TokenState tokenState;
- private final String appKey;
- private final String appSecret;
- private final String tokenUrl;
- // 添加单例实例
- private static volatile BeisenTokenManager instance;
- // 私有化构造器
- private BeisenTokenManager() {
- this(Config.APP_KEY, Config.APP_SECRET, Config.TOKEN_URL);
- }
- // 获取单例方法
- public static BeisenTokenManager getInstance() {
- if (instance == null) {
- synchronized (BeisenTokenManager.class) {
- if (instance == null) {
- instance = new BeisenTokenManager();
- }
- }
- }
- return instance;
- }
- public BeisenTokenManager(String appKey, String appSecret, String tokenUrl) {
- this.appKey = appKey;
- this.appSecret = appSecret;
- this.tokenUrl = tokenUrl;
- this.httpClient = buildHttpClient();
- this.tokenState = loadInitialToken();
- }
- public String getAccessToken() throws IOException {
- TokenState currentState = tokenState;
- if (currentState != null && !isTokenExpired(currentState)) {
- return currentState.getAccessToken();
- }
- if (currentState == null || isTokenExpired(currentState)) {
- lock.lock();
- try {
- currentState = tokenState;
- if (currentState == null || isTokenExpired(currentState)) {
- currentState = fetchNewToken();
- tokenState = currentState;
- }
- } finally {
- lock.unlock();
- }
- }
- return currentState.getAccessToken();
- }
- public void refreshToken() throws IOException {
- TokenState currentState = tokenState;
- if (currentState == null || currentState.getRefreshToken() == null) {
- tokenState = fetchNewToken();
- return;
- }
- if (isTokenExpired(currentState)) {
- lock.lock();
- try {
- currentState = tokenState;
- if (isTokenExpired(currentState)) {
- tokenState = refreshToken(currentState.getRefreshToken());
- }
- } finally {
- lock.unlock();
- }
- }
- }
- private boolean isTokenExpired(TokenState state) {
- // 添加缓冲时间,避免在token即将过期时使用
- return System.currentTimeMillis() > (state.getExpireTime() - EXPIRY_BUFFER);
- }
- private TokenState loadInitialToken() {
- try {
- return fetchNewToken();
- } catch (Exception e) {
- logger.error("Failed to initialize token", e);
- throw new RuntimeException("Token initialization failed", e);
- }
- }
- private TokenState fetchNewToken() throws IOException {
- JSONObject requestBody = new JSONObject();
- requestBody.put("grant_type", "client_credentials");
- requestBody.put("app_key", appKey);
- requestBody.put("app_secret", appSecret);
- return executeTokenRequest(requestBody);
- }
- private TokenState refreshToken(String refreshToken) throws IOException {
- JSONObject requestBody = new JSONObject();
- requestBody.put("grant_type", "refresh_token");
- requestBody.put("refresh_token", refreshToken);
- return executeTokenRequest(requestBody);
- }
- private TokenState executeTokenRequest(JSONObject requestBody) throws IOException {
- Request request = new Request.Builder().url(tokenUrl).post(RequestBody.create(JSON_MEDIA_TYPE, requestBody.toJSONString())).build();
- try (Response response = httpClient.newCall(request).execute()) {
- if (!response.isSuccessful()) {
- String errorBody = response.body() != null ? response.body().string() : "null";
- logger.error("Token request failed. Code: " + response.code() + ", Body: " + errorBody);
- throw new IOException("Token request failed with code: " + response.code());
- }
- String responseBody = response.body().string();
- JSONObject jsonResponse = JSON.parseObject(responseBody);
- String accessToken = jsonResponse.getString("access_token");
- String refreshToken = jsonResponse.getString("refresh_token");
- Long expiresIn = jsonResponse.getLong("expires_in");
- // 更健壮的空值检查
- if (accessToken == null || expiresIn == null || expiresIn <= 0) {
- throw new IOException("Invalid token response: " + responseBody);
- }
- return new TokenState(accessToken, System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expiresIn), refreshToken);
- }
- }
- private OkHttpClient buildHttpClient() {
- return new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).writeTimeout(10, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).retryOnConnectionFailure(true).build();
- }
- private static class TokenState {
- private final String accessToken;
- private final long expireTime;
- private final String refreshToken;
- public TokenState(String accessToken, long expireTime, String refreshToken) {
- this.accessToken = accessToken;
- this.expireTime = expireTime;
- this.refreshToken = refreshToken;
- }
- public String getAccessToken() {
- return accessToken;
- }
- public long getExpireTime() {
- return expireTime;
- }
- public String getRefreshToken() {
- return refreshToken;
- }
- }
- public static class Config {
- private static final String BESON_CONFIG_PATH = "/server/properties/beisen/BeiSenConfig.properties";
- // public static String APP_KEY = "FFEC5C62AB444567AFC11E8D394CC072";
- // public static String APP_SECRET = "74FE75BEE476496EAF531C2219EC10E57EDCE01D74F64557BADEEC78FBFF3B26";
- // public static String TOKEN_URL = "https://openapi.italent.cn/token";
- // 测试环境
- // public static String APP_KEY = "FFEC5C62AB444567AFC11E8D394CC072";
- // public static String APP_SECRET = "74FE75BEE476496EAF531C2219EC10E57EDCE01D74F64557BADEEC78FBFF3B26";
- // 生产环境
- // public static String APP_KEY = "C16FE3483B4E42FCA97686B6D01F1B3C";
- // public static String APP_SECRET = "DE0EED6E741149A3842BAA89143415B3D5C76FC304AB4FCF8D4D708B8D1F1E04";
- public static String TOKEN_URL = "https://openapi.italent.cn/token";
- public static String APP_KEY = "";
- public static String APP_SECRET = "";
- static {
- // 从配置文件中读取配置
- try {
- BeisenParamByPropertiesUtil beisenParamByProperties = new BeisenParamByPropertiesUtil(BESON_CONFIG_PATH);
- Map<String, String> config = beisenParamByProperties.getConfig();
- // 如果配置文件中存在配置,则覆盖默认配置
- if (config != null) {
- // 如果配置文件中存在appKey,则覆盖默认appKey
- if (config.containsKey("APP_KEY")) {
- APP_KEY = config.get("APP_KEY");
- }
- // 如果配置文件中存在appSecret,则覆盖默认appSecret
- if (config.containsKey("APP_SECRET")) {
- APP_SECRET = config.get("APP_SECRET");
- }
- // 如果配置文件中存在tokenUrl,则覆盖默认tokenUrl
- if (config.containsKey("ACCESSTOKEN_URL")) {
- TOKEN_URL = config.get("ACCESSTOKEN_URL");
- }
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
- }
|