1
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
package com.ruoyi.jarvis.service;
|
||||
|
||||
/**
|
||||
* 腾讯文档Token管理服务接口
|
||||
* 用于自动获取和管理访问令牌
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
public interface ITencentDocTokenService {
|
||||
|
||||
/**
|
||||
* 获取有效的访问令牌
|
||||
* 如果当前token不存在或已过期,会自动获取新的token
|
||||
*
|
||||
* @return 访问令牌
|
||||
*/
|
||||
String getValidAccessToken();
|
||||
|
||||
/**
|
||||
* 刷新访问令牌
|
||||
*
|
||||
* @return 新的访问令牌
|
||||
*/
|
||||
String refreshAccessToken();
|
||||
|
||||
/**
|
||||
* 清除缓存的token
|
||||
*/
|
||||
void clearToken();
|
||||
}
|
||||
|
||||
@@ -1364,7 +1364,16 @@ private String handleTF(String input) {
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
order.setAddress(fields.getOrDefault("地址", null));
|
||||
order.setLogisticsLink(extractFirstUrl(fields.getOrDefault("物流链接", "")));
|
||||
// 保留完整的物流链接,不做清理
|
||||
String logisticsLink = fields.getOrDefault("物流链接", null);
|
||||
if (logisticsLink != null) {
|
||||
logisticsLink = logisticsLink.trim();
|
||||
// 如果为空字符串,设置为null
|
||||
if (logisticsLink.isEmpty()) {
|
||||
logisticsLink = null;
|
||||
}
|
||||
}
|
||||
order.setLogisticsLink(logisticsLink);
|
||||
order.setOrderId(fields.getOrDefault("订单号", null));
|
||||
order.setBuyer(fields.getOrDefault("下单人", null));
|
||||
// 京粉实际价格不从表单解析,而是从数据库order_rows表中查询获取
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
package com.ruoyi.jarvis.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import com.ruoyi.jarvis.config.TencentDocConfig;
|
||||
import com.ruoyi.jarvis.service.ITencentDocTokenService;
|
||||
import com.ruoyi.jarvis.util.TencentDocApiUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 腾讯文档Token管理服务实现
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Service
|
||||
public class TencentDocTokenServiceImpl implements ITencentDocTokenService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TencentDocTokenServiceImpl.class);
|
||||
|
||||
/** Redis key前缀 */
|
||||
private static final String TOKEN_KEY_PREFIX = "tendoc:token:";
|
||||
private static final String REFRESH_TOKEN_KEY_PREFIX = "tendoc:refresh_token:";
|
||||
private static final String TOKEN_EXPIRE_TIME_KEY_PREFIX = "tendoc:token_expire:";
|
||||
|
||||
@Autowired
|
||||
private TencentDocConfig tencentDocConfig;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Override
|
||||
public String getValidAccessToken() {
|
||||
String tokenKey = TOKEN_KEY_PREFIX + tencentDocConfig.getAppId();
|
||||
|
||||
// 从Redis获取缓存的token
|
||||
if (redisCache.hasKey(tokenKey)) {
|
||||
Object cachedToken = redisCache.getCacheObject(tokenKey);
|
||||
if (cachedToken != null) {
|
||||
String token = cachedToken.toString();
|
||||
|
||||
// 检查token是否即将过期(提前5分钟刷新)
|
||||
String expireTimeKey = TOKEN_EXPIRE_TIME_KEY_PREFIX + tencentDocConfig.getAppId();
|
||||
if (redisCache.hasKey(expireTimeKey)) {
|
||||
Object expireTimeObj = redisCache.getCacheObject(expireTimeKey);
|
||||
if (expireTimeObj != null) {
|
||||
Long expireTime = Long.valueOf(expireTimeObj.toString());
|
||||
long currentTime = System.currentTimeMillis();
|
||||
// 如果还有5分钟以上有效期,直接返回
|
||||
if (expireTime > currentTime + 5 * 60 * 1000) {
|
||||
log.debug("使用缓存的访问令牌");
|
||||
return token;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 如果没有过期时间记录,直接使用(可能是旧数据)
|
||||
return token;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Token不存在或已过期,尝试刷新
|
||||
log.info("访问令牌不存在或已过期,尝试刷新...");
|
||||
return refreshAccessToken();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String refreshAccessToken() {
|
||||
try {
|
||||
String refreshTokenKey = REFRESH_TOKEN_KEY_PREFIX + tencentDocConfig.getAppId();
|
||||
|
||||
// 先尝试使用refresh_token刷新
|
||||
if (redisCache.hasKey(refreshTokenKey)) {
|
||||
String refreshToken = redisCache.getCacheObject(refreshTokenKey).toString();
|
||||
try {
|
||||
JSONObject tokenInfo = TencentDocApiUtil.refreshAccessToken(
|
||||
tencentDocConfig.getAppId(),
|
||||
tencentDocConfig.getAppSecret(),
|
||||
refreshToken,
|
||||
tencentDocConfig.getRefreshTokenUrl()
|
||||
);
|
||||
|
||||
if (tokenInfo != null && tokenInfo.containsKey("access_token")) {
|
||||
String newAccessToken = tokenInfo.getString("access_token");
|
||||
String newRefreshToken = tokenInfo.getString("refresh_token");
|
||||
Integer expiresIn = tokenInfo.getIntValue("expires_in");
|
||||
|
||||
// 保存新的token
|
||||
saveToken(newAccessToken, newRefreshToken, expiresIn);
|
||||
|
||||
log.info("成功刷新访问令牌");
|
||||
return newAccessToken;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("使用refresh_token刷新失败,尝试重新获取授权: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有refresh_token或刷新失败,需要重新获取授权
|
||||
// 注意:服务端应用需要使用应用级授权,这里需要根据实际情况调整
|
||||
log.warn("无法自动刷新token,需要手动授权或配置应用级token");
|
||||
throw new RuntimeException("无法获取访问令牌,请检查配置或手动授权");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("刷新访问令牌失败", e);
|
||||
throw new RuntimeException("刷新访问令牌失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存token到Redis
|
||||
*/
|
||||
private void saveToken(String accessToken, String refreshToken, Integer expiresIn) {
|
||||
String tokenKey = TOKEN_KEY_PREFIX + tencentDocConfig.getAppId();
|
||||
String refreshTokenKey = REFRESH_TOKEN_KEY_PREFIX + tencentDocConfig.getAppId();
|
||||
String expireTimeKey = TOKEN_EXPIRE_TIME_KEY_PREFIX + tencentDocConfig.getAppId();
|
||||
|
||||
// 保存access_token(有效期比实际少5分钟,确保提前刷新)
|
||||
int cacheExpireTime = expiresIn != null ? expiresIn - 300 : 6900; // 默认2小时减5分钟
|
||||
redisCache.setCacheObject(tokenKey, accessToken, cacheExpireTime, TimeUnit.SECONDS);
|
||||
|
||||
// 保存refresh_token(有效期30天)
|
||||
if (refreshToken != null) {
|
||||
redisCache.setCacheObject(refreshTokenKey, refreshToken, 30, TimeUnit.DAYS);
|
||||
}
|
||||
|
||||
// 保存过期时间戳
|
||||
long expireTime = System.currentTimeMillis() + (expiresIn != null ? expiresIn * 1000L : 7200000L);
|
||||
redisCache.setCacheObject(expireTimeKey, expireTime, cacheExpireTime, TimeUnit.SECONDS);
|
||||
|
||||
log.info("访问令牌已保存到缓存,有效期: {} 秒", expiresIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动设置token(用于从外部获取的token)
|
||||
* 注意:此方法需要public,供控制器调用
|
||||
*/
|
||||
public void setToken(String accessToken, String refreshToken, Integer expiresIn) {
|
||||
saveToken(accessToken, refreshToken, expiresIn);
|
||||
log.info("手动设置访问令牌成功");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearToken() {
|
||||
String tokenKey = TOKEN_KEY_PREFIX + tencentDocConfig.getAppId();
|
||||
String refreshTokenKey = REFRESH_TOKEN_KEY_PREFIX + tencentDocConfig.getAppId();
|
||||
String expireTimeKey = TOKEN_EXPIRE_TIME_KEY_PREFIX + tencentDocConfig.getAppId();
|
||||
|
||||
redisCache.deleteObject(tokenKey);
|
||||
redisCache.deleteObject(refreshTokenKey);
|
||||
redisCache.deleteObject(expireTimeKey);
|
||||
|
||||
log.info("已清除访问令牌缓存");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user