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);
|
}
|
}
|
}
|