package com.ruoyi.system.service.impl; import com.ruoyi.common.config.WechatConfig; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.WechatUtils; import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.IWechatAccessTokenService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * 微信AccessToken服务实现 * 提供应用级AccessToken的统一管理,使用sys_config表缓存 * * @author ruoyi * @date 2025-12-04 */ @Service public class WechatAccessTokenServiceImpl implements IWechatAccessTokenService { private static final Logger log = LoggerFactory.getLogger(WechatAccessTokenServiceImpl.class); @Autowired private WechatConfig wechatConfig; @Autowired private ISysConfigService configService; @Autowired private SysConfigMapper configMapper; /** * 获取应用级微信AccessToken(带缓存) * 优先从sys_config读取并判断有效期;过期则重新获取并写回sys_config */ @Override public String getAppAccessToken() { try { String appId = wechatConfig.getAppId(); String tokenKey = "weixin.access_token." + appId; String expireKey = "weixin.access_token_expires." + appId; String cachedToken = configService.selectConfigByKey(tokenKey); String cachedExpireStr = configService.selectConfigByKey(expireKey); long now = System.currentTimeMillis(); long expireTs = 0L; if (StringUtils.isNotEmpty(cachedExpireStr)) { try { expireTs = Long.parseLong(cachedExpireStr); } catch (NumberFormatException e) { expireTs = 0L; } } // 缓存有效且未过期(预留60秒安全边界) if (StringUtils.isNotEmpty(cachedToken) && expireTs > now + 60000L) { log.debug("使用缓存的AccessToken,剩余有效期:{}秒", (expireTs - now) / 1000); return cachedToken; } // 重新获取,并写入sys_config log.info("AccessToken已过期或不存在,重新获取"); return refreshAppAccessToken(); } catch (Exception e) { log.error("获取应用级微信AccessToken失败", e); return null; } } /** * 强制刷新AccessToken * 忽略缓存,直接从微信获取新Token并更新缓存 */ @Override public String refreshAppAccessToken() { try { String appId = wechatConfig.getAppId(); String appSecret = wechatConfig.getAppSecret(); String tokenKey = "weixin.access_token." + appId; String expireKey = "weixin.access_token_expires." + appId; String newToken = WechatUtils.getAccessToken(appId, appSecret); if (StringUtils.isEmpty(newToken)) { log.error("从微信获取AccessToken失败"); return null; } long now = System.currentTimeMillis(); long newExpireTs = now + 7200L * 1000L; // 7200秒 upsertConfig(tokenKey, newToken); upsertConfig(expireKey, String.valueOf(newExpireTs)); log.info("AccessToken刷新成功,有效期:7200秒"); return newToken; } catch (Exception e) { log.error("刷新应用级微信AccessToken失败", e); return null; } } /** * 根据configKey写入或更新sys_config */ private void upsertConfig(String key, String value) { SysConfig exist = configMapper.checkConfigKeyUnique(key); if (exist != null && exist.getConfigId() != null) { exist.setConfigValue(value); configMapper.updateConfig(exist); } else { SysConfig cfg = new SysConfig(); cfg.setConfigKey(key); cfg.setConfigName(key); cfg.setConfigValue(value); cfg.setConfigType("Y"); // 内置参数 configMapper.insertConfig(cfg); } } }