feat(mqtt): 关闭MQTT服务并添加微信小程序token服务
- 将application-glt.yml中的mqtt.enabled设置为false - 重构ShopDealerOrder实体类的导入顺序 - 在ShopDealerOrder中新增isUnfreeze字段表示佣金冻结状态 - 在ShopDealerOrder中新增unfreezeTime字段表示解冻时间 - 新增WxMiniappAccessTokenService接口用于获取微信小程序access_token - 实现WxMiniappAccessTokenServiceImpl服务支持按租户获取access_token - 集成Redis缓存机制支持access_token的缓存管理 - 实现微信API调用逻辑支持token获取和异常处理
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package com.gxwebsoft.common.system.service;
|
||||
|
||||
/**
|
||||
* 微信小程序 access_token 获取服务(按租户)。
|
||||
*
|
||||
* <p>用于调用微信小程序开放接口(例如:上传发货信息)。</p>
|
||||
*/
|
||||
public interface WxMiniappAccessTokenService {
|
||||
|
||||
/**
|
||||
* 获取指定租户的小程序 access_token(内部带缓存)。
|
||||
*
|
||||
* @param tenantId 租户ID
|
||||
* @return access_token
|
||||
*/
|
||||
String getAccessToken(Integer tenantId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.gxwebsoft.common.system.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.gxwebsoft.common.core.exception.BusinessException;
|
||||
import com.gxwebsoft.common.core.utils.RedisUtil;
|
||||
import com.gxwebsoft.common.system.service.WxMiniappAccessTokenService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.gxwebsoft.common.core.constants.RedisConstants.ACCESS_TOKEN_KEY;
|
||||
import static com.gxwebsoft.common.core.constants.RedisConstants.MP_WX_KEY;
|
||||
|
||||
/**
|
||||
* 微信小程序 access_token 获取实现(按租户)。
|
||||
*
|
||||
* <p>复用现有缓存结构:
|
||||
* <ul>
|
||||
* <li>小程序配置:Redis key = {@code mp-weixin:{tenantId}},value 为 JSON,包含 appId/appSecret</li>
|
||||
* <li>access_token:Redis key = {@code access-token:{tenantId}},value 为微信返回的 JSON 字符串</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class WxMiniappAccessTokenServiceImpl implements WxMiniappAccessTokenService {
|
||||
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Override
|
||||
public String getAccessToken(Integer tenantId) {
|
||||
if (tenantId == null) {
|
||||
throw new BusinessException("tenantId 不能为空");
|
||||
}
|
||||
|
||||
final String tokenCacheKey = ACCESS_TOKEN_KEY + ":" + tenantId;
|
||||
|
||||
// 1) 优先从缓存取(兼容 JSON 或纯字符串 token 的历史格式)
|
||||
String cachedValue = redisUtil.get(tokenCacheKey);
|
||||
if (StrUtil.isNotBlank(cachedValue)) {
|
||||
try {
|
||||
JSONObject cachedJson = JSON.parseObject(cachedValue);
|
||||
String accessToken = cachedJson.getString("access_token");
|
||||
if (StrUtil.isNotBlank(accessToken)) {
|
||||
return accessToken;
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
// 旧格式:直接存 token
|
||||
return cachedValue;
|
||||
}
|
||||
}
|
||||
|
||||
// 2) 缓存没有则从租户配置获取 appId/appSecret
|
||||
final String wxConfigKey = MP_WX_KEY + tenantId;
|
||||
final String wxConfigValue = redisUtil.get(wxConfigKey);
|
||||
if (StrUtil.isBlank(wxConfigValue)) {
|
||||
throw new BusinessException("未找到微信小程序配置,请检查缓存key: " + wxConfigKey);
|
||||
}
|
||||
|
||||
JSONObject wxConfig;
|
||||
try {
|
||||
wxConfig = JSON.parseObject(wxConfigValue);
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException("微信小程序配置格式错误: " + e.getMessage());
|
||||
}
|
||||
|
||||
final String appId = wxConfig.getString("appId");
|
||||
final String appSecret = wxConfig.getString("appSecret");
|
||||
if (StrUtil.isBlank(appId) || StrUtil.isBlank(appSecret)) {
|
||||
throw new BusinessException("微信小程序配置不完整(appId/appSecret)");
|
||||
}
|
||||
|
||||
// 3) 调用微信接口获取 token
|
||||
final String apiUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential"
|
||||
+ "&appid=" + appId + "&secret=" + appSecret;
|
||||
String result = HttpUtil.get(apiUrl);
|
||||
|
||||
JSONObject json = JSON.parseObject(result);
|
||||
if (json.containsKey("errcode") && json.getIntValue("errcode") != 0) {
|
||||
Integer errcode = json.getInteger("errcode");
|
||||
String errmsg = json.getString("errmsg");
|
||||
throw new BusinessException("获取小程序access_token失败: " + errmsg + " (errcode: " + errcode + ")");
|
||||
}
|
||||
|
||||
String accessToken = json.getString("access_token");
|
||||
Integer expiresIn = json.getInteger("expires_in");
|
||||
if (StrUtil.isBlank(accessToken)) {
|
||||
throw new BusinessException("获取小程序access_token失败: access_token为空");
|
||||
}
|
||||
|
||||
// 4) 缓存微信原始 JSON(与现有实现保持一致),提前5分钟过期
|
||||
long ttlSeconds = 7000L;
|
||||
if (expiresIn != null && expiresIn > 300) {
|
||||
ttlSeconds = expiresIn - 300L;
|
||||
}
|
||||
redisUtil.set(tokenCacheKey, result, ttlSeconds, TimeUnit.SECONDS);
|
||||
|
||||
log.info("获取小程序access_token成功 - tenantId={}, ttlSeconds={}", tenantId, ttlSeconds);
|
||||
return accessToken;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
package com.gxwebsoft.shop.entity;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import cn.afterturn.easypoi.excel.annotation.Excel;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.time.LocalDateTime;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.io.Serializable;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分销商订单记录表
|
||||
*
|
||||
@@ -120,9 +119,15 @@ public class ShopDealerOrder implements Serializable {
|
||||
@Schema(description = "佣金结算(0未结算 1已结算)")
|
||||
private Integer isSettled;
|
||||
|
||||
@Schema(description = "佣金冻结(1解冻中 0已解冻)")
|
||||
private Integer isUnfreeze;
|
||||
|
||||
@Schema(description = "结算时间")
|
||||
private LocalDateTime settleTime;
|
||||
|
||||
@Schema(description = "解冻时间")
|
||||
private LocalDateTime unfreezeTime;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String comments;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ socketio:
|
||||
|
||||
# MQTT配置
|
||||
mqtt:
|
||||
enabled: true # 启用MQTT服务
|
||||
enabled: false # 启用MQTT服务
|
||||
host: tcp://132.232.214.96:1883
|
||||
username: swdev
|
||||
password: Sw20250523
|
||||
|
||||
Reference in New Issue
Block a user