package com.walker.wxtools; import com.walker.infrastructure.utils.StringUtils; import com.walker.wxtools.util.AccessTokenUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class AbstractOfficialAccountEngine implements OfficialAccountEngine{ protected final transient Logger logger = LoggerFactory.getLogger(this.getClass()); @Override public WxUserInfo getUserInfoSub(String openId) throws AccessTokenNotFoundException{ String basicAccessToken = null; try { basicAccessToken = this.getBasicAccessToken(); if(StringUtils.isEmpty(basicAccessToken)){ throw new Exception("basicAccessToken为空", null); } } catch (Exception ex){ throw new AccessTokenNotFoundException(ex.getMessage(), ex); } try { return this.acquireRemoteUserInfoSub(openId, basicAccessToken); } catch (WxRemoteException e) { throw new RuntimeException("远程调用'获取微信用户接口'失败:" + e.getError(), e); } } @Override public WxUserInfo getUserInfo(String openId) { throw new UnsupportedOperationException(); } @Override public String getAuthAccessToken(String code) { throw new UnsupportedOperationException(); } @Override public String getJsApiTicket() { String basicAccessToken = this.getBasicAccessToken(); if(StringUtils.isEmpty(basicAccessToken)){ logger.error("getJsApiTicket:获取'basicAccessToken'为空!"); return null; } return this.getJsApiTicket(basicAccessToken); } @Override public String getJsApiTicket(String basicAccessToken) { JsTicket jsTicket = this.acquireCachedJsTicket(Constants.CACHE_PREFIX_JS_TICKET + this.getAppId()); if(jsTicket != null){ if(!AccessTokenUtils.isExpiredCache(jsTicket.getCreateTime(), this.maxCachedAccessTokenSeconds)){ return jsTicket.getTicket(); } } // 重新获取:jsTicket try { jsTicket = this.acquireRemoteJsTicket(basicAccessToken); logger.debug("远程获取'jsTicket'..........{}", jsTicket); this.writeJsTicketToCache(Constants.CACHE_PREFIX_JS_TICKET + this.getAppId(), jsTicket); return jsTicket.getTicket(); } catch (WxRemoteException e) { throw new RuntimeException(e.getError(), e); } } @Override public String getJsApiTicket4Card(String basicAccessToken) { throw new UnsupportedOperationException(); } @Override public String getBasicAccessToken() { BasicAccessToken accessToken = this.acquireCachedBasicAccessToken(Constants.CACHE_PREFIX_ACCESS_TOKEN + this.getAppId()); if(accessToken != null){ if(!AccessTokenUtils.isExpiredCache(accessToken.getCreateTime(), this.maxCachedAccessTokenSeconds)){ // 缓存未过期,直接返回 return accessToken.getAccessToken(); } } // 重新获取:access_token try { accessToken = this.acquireRemoteBasicAccessToken(this.getAppId(), this.getSecret()); logger.debug("远程获取'access_token'..........{}", accessToken); this.writeBasicAccessTokenToCache(Constants.CACHE_PREFIX_ACCESS_TOKEN + this.getAppId(), accessToken); return accessToken.getAccessToken(); } catch (WxRemoteException e) { throw new RuntimeException(e.getError(), e); } } protected abstract JsTicket acquireCachedJsTicket(String cacheKey); protected abstract void writeJsTicketToCache(String cacheKey, JsTicket jsTicket); protected abstract JsTicket acquireRemoteJsTicket(String basicAccessToken) throws WxRemoteException; /** * 从缓存中获取appId对应的基础'access_token'对象。 * @param cacheKey * @return * @date 2023-04-20 */ protected abstract BasicAccessToken acquireCachedBasicAccessToken(String cacheKey); /** * 把基础'access_token'写入缓存中。
默认基于内存,业务可以重写方法,写入redis中
* @param cacheKey 缓存的key = access_token:appId * @param basicAccessToken 缓存的对象 * @date 2023-04-20 */ protected abstract void writeBasicAccessTokenToCache(String cacheKey, BasicAccessToken basicAccessToken); /** * 远程调用微信,获取一个新的基础'access_token'数据。 * @param appId * @param secret * @return * @throws WxRemoteException * @date 2023-04-20 */ protected abstract BasicAccessToken acquireRemoteBasicAccessToken(String appId, String secret) throws WxRemoteException; protected abstract WxUserInfo acquireRemoteUserInfoSub(String openId, String basicAccessToken) throws WxRemoteException; @Override public void setAppId(String appId) { if(StringUtils.isEmpty(appId)){ throw new IllegalArgumentException("'appId'必须提供"); } this.appId = appId; } @Override public void setSecret(String secret) { if(StringUtils.isEmpty(secret)){ throw new IllegalArgumentException("'secret'必须提供"); } this.secret = secret; } @Override public String getAppId() { return appId; } protected String getSecret() { return secret; } public long getMaxCachedAccessTokenSeconds() { return maxCachedAccessTokenSeconds; } /** * 设置:access_token 缓存最大时间(秒),默认:5400秒 * @param maxCachedAccessTokenSeconds * @date 2023-04-20 */ public void setMaxCachedAccessTokenSeconds(long maxCachedAccessTokenSeconds) { this.maxCachedAccessTokenSeconds = maxCachedAccessTokenSeconds; } private long maxCachedAccessTokenSeconds = 5400; private String appId; private String secret; }