Browse Source

```feat(redis): 微信小程序配置从缓存获取并支持Redis存储

- 新增 RedisConstants.MP_WX_KEY 常量用于微信小程序配置缓存键
- 修改 WxLoginController 中多处配置获取逻辑,使用 getWxConfigFromCache 方法替代原 DB 查询
- 移除 SettingMapper 和 SettingServiceImpl 中的跨租户数据库查询方法及相关逻辑
- 新增 getWxConfigFromCache 方法用于从 Redis 缓存中获取微信小程序配置
- 调整微信配置创建逻辑,直接写入 Redis 缓存而非数据库
- 优化错误提示信息,引导用户检查 Redis 缓存配置
- 同步更新 ShopDealerApply 实体及 Mapper XML,增加 phone 字段查询
```
dev
科技小王子 6 days ago
parent
commit
1da96e7ff3
  1. 2
      src/main/java/com/gxwebsoft/common/core/constants/RedisConstants.java
  2. 92
      src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java
  3. 8
      src/main/java/com/gxwebsoft/common/system/mapper/SettingMapper.java
  4. 9
      src/main/java/com/gxwebsoft/common/system/mapper/xml/SettingMapper.xml
  5. 93
      src/main/java/com/gxwebsoft/common/system/service/impl/SettingServiceImpl.java
  6. 4
      src/main/java/com/gxwebsoft/shop/entity/ShopDealerApply.java
  7. 2
      src/main/java/com/gxwebsoft/shop/mapper/xml/ShopDealerApplyMapper.xml

2
src/main/java/com/gxwebsoft/common/core/constants/RedisConstants.java

@ -24,6 +24,8 @@ public class RedisConstants {
public static final String TEN_ANT_SETTING_KEY = "setting";
// 排行榜Key
public static final String USER_RANKING_BY_APPS_5 = "cache5:userRankingByApps";
// 微信小程序Key
public static final String MP_WX_KEY = "mp-weixin:";

92
src/main/java/com/gxwebsoft/common/system/controller/WxLoginController.java

@ -44,6 +44,7 @@ import java.util.concurrent.TimeUnit;
import static com.gxwebsoft.common.core.constants.PlatformConstants.MP_WEIXIN;
import static com.gxwebsoft.common.core.constants.RedisConstants.ACCESS_TOKEN_KEY;
import static com.gxwebsoft.common.core.constants.RedisConstants.MP_WX_KEY;
@RestController
@RequestMapping("/api/wx-login")
@ -224,8 +225,8 @@ public class WxLoginController extends BaseController {
// 获取openid
private JSONObject getOpenIdByCode(UserParam userParam) {
// 获取微信小程序配置信息
JSONObject setting = settingService.getBySettingKey("mp-weixin", getTenantId());
// 从缓存获取微信小程序配置信息
JSONObject setting = getWxConfigFromCache(getTenantId());
// 获取openId
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=" + setting.getString("appId") + "&secret=" + setting.getString("appSecret") + "&js_code=" + userParam.getCode() + "&grant_type=authorization_code";
// 执行get请求
@ -282,8 +283,8 @@ public class WxLoginController extends BaseController {
Integer tenantId = getTenantId();
String key = ACCESS_TOKEN_KEY.concat(":").concat(tenantId.toString());
// 使用跨租户方式获取微信小程序配置信息
JSONObject setting = settingService.getBySettingKeyIgnoreTenant("mp-weixin", tenantId);
// 从缓存获取微信小程序配置信息
JSONObject setting = getWxConfigFromCache(tenantId);
if (setting == null) {
throw new BusinessException("请先配置小程序");
}
@ -332,7 +333,7 @@ public class WxLoginController extends BaseController {
// 请求微信接口获取openid
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session";
final HashMap<String, Object> map = new HashMap<>();
final JSONObject setting = settingService.getBySettingKey("mp-weixin", getTenantId());
final JSONObject setting = getWxConfigFromCache(getTenantId());
final String appId = setting.getString("appId");
final String appSecret = setting.getString("appSecret");
map.put("appid", appId);
@ -360,7 +361,7 @@ public class WxLoginController extends BaseController {
String apiUrl = "https://api.weixin.qq.com/sns/jscode2session";
final HashMap<String, Object> map = new HashMap<>();
final JSONObject setting = settingService.getBySettingKey("mp-weixin", getTenantId());
final JSONObject setting = getWxConfigFromCache(getTenantId());
final String appId = setting.getString("appId");
final String appSecret = setting.getString("appSecret");
map.put("appid", appId);
@ -548,9 +549,9 @@ public class WxLoginController extends BaseController {
}
}
// 使用跨租户方式获取微信小程序配置信息
// 从缓存获取微信小程序配置信息
Integer tenantId = getTenantId();
JSONObject setting = settingService.getBySettingKeyIgnoreTenant("mp-weixin", tenantId);
JSONObject setting = getWxConfigFromCache(tenantId);
if (setting == null) {
throw new IOException("请先配置小程序");
}
@ -576,7 +577,7 @@ public class WxLoginController extends BaseController {
if (json.has("access_token")) {
String token = json.get("access_token").asText();
long expiresIn = json.get("expires_in").asInt(7200);
// 缓存完整的JSON响应,与其他方法保持一致
redisUtil.set(key, body, expiresIn, TimeUnit.SECONDS);
tokenExpireEpoch = now + expiresIn;
@ -603,18 +604,20 @@ public class WxLoginController extends BaseController {
result.put("tenantId", tenantId);
try {
// 尝试获取配置
JSONObject setting = settingService.getBySettingKeyIgnoreTenant("mp-weixin", tenantId);
// 尝试从缓存获取配置
JSONObject setting = getWxConfigFromCache(tenantId);
result.put("hasConfig", true);
result.put("config", setting);
result.put("cacheKey", MP_WX_KEY + tenantId);
} catch (Exception e) {
result.put("hasConfig", false);
result.put("error", e.getMessage());
result.put("cacheKey", MP_WX_KEY + tenantId);
// 提供创建配置的建议
Map<String, Object> suggestion = new HashMap<>();
suggestion.put("message", "请在系统设置中创建微信小程序配置");
suggestion.put("configKey", "mp-weixin");
suggestion.put("message", "请在Redis中创建微信小程序配置");
suggestion.put("cacheKey", MP_WX_KEY + tenantId);
suggestion.put("tenantId", tenantId);
suggestion.put("sampleConfig", createSampleWxConfig());
result.put("suggestion", suggestion);
@ -636,23 +639,21 @@ public class WxLoginController extends BaseController {
}
try {
// 创建配置对象
Setting setting = new Setting();
setting.setSettingKey("mp-weixin");
setting.setTenantId(tenantId);
// 直接在Redis中创建配置
String key = MP_WX_KEY + tenantId;
// 创建配置内容
Map<String, String> config = new HashMap<>();
config.put("appId", appId);
config.put("appSecret", appSecret);
setting.setContent(JSON.toJSONString(config));
setting.setComments("微信小程序配置");
setting.setSortNumber(1);
// 保存配置
settingService.save(setting);
config.put("tenantId", tenantId.toString());
config.put("settingKey", "mp-weixin");
config.put("settingId", "301");
// 保存到Redis缓存
redisUtil.set(key, JSON.toJSONString(config));
return success("微信小程序配置创建成功", setting);
return success("微信小程序配置创建成功", config);
} catch (Exception e) {
return fail("创建配置失败: " + e.getMessage(), null);
}
@ -674,15 +675,15 @@ public class WxLoginController extends BaseController {
if (tenantId == null) {
tenantId = 10550; // 默认租户
}
System.out.println("=== 开始调试获取AccessToken,租户ID: " + tenantId + " ===");
// 手动调用获取AccessToken
String accessToken = getAccessTokenForTenant(tenantId);
String result = "获取AccessToken成功: " + (accessToken != null ? accessToken.substring(0, Math.min(10, accessToken.length())) + "..." : "null");
System.out.println("调试结果: " + result);
return success(result);
} catch (Exception e) {
System.err.println("调试获取AccessToken异常: " + e.getMessage());
@ -691,6 +692,24 @@ public class WxLoginController extends BaseController {
}
}
/**
* 从Redis缓存中获取微信小程序配置
* @param tenantId 租户ID
* @return 微信配置信息
*/
private JSONObject getWxConfigFromCache(Integer tenantId) {
String key = MP_WX_KEY + tenantId;
String cacheValue = redisUtil.get(key);
if (StrUtil.isBlank(cacheValue)) {
throw new BusinessException("未找到微信小程序配置,请检查缓存key: " + key);
}
try {
return JSON.parseObject(cacheValue);
} catch (Exception e) {
throw new BusinessException("微信小程序配置格式错误: " + e.getMessage());
}
}
/**
* 从scene参数中提取租户ID
* scene格式可能是: uid_33103 或其他包含用户ID的格式
@ -732,12 +751,6 @@ public class WxLoginController extends BaseController {
try {
String key = ACCESS_TOKEN_KEY.concat(":").concat(tenantId.toString());
// 使用跨租户方式获取微信小程序配置信息
JSONObject setting = settingService.getBySettingKeyIgnoreTenant("mp-weixin", tenantId);
if (setting == null) {
throw new RuntimeException("租户 " + tenantId + " 的小程序未配置");
}
// 从缓存获取access_token
String value = redisUtil.get(key);
if (value != null) {
@ -757,8 +770,9 @@ public class WxLoginController extends BaseController {
}
// 缓存中没有,重新获取
String appId = setting.getString("appId");
String appSecret = setting.getString("appSecret");
JSONObject wxConfig = getWxConfigFromCache(tenantId);
String appId = wxConfig.getString("appId");
String appSecret = wxConfig.getString("appSecret");
String apiUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
System.out.println("调用微信API获取token - 租户ID: " + tenantId + ", AppID: " + (appId != null ? appId.substring(0, Math.min(8, appId.length())) + "..." : "null"));
@ -766,13 +780,13 @@ public class WxLoginController extends BaseController {
String result = HttpUtil.get(apiUrl);
System.out.println("微信API响应: " + result);
JSONObject json = JSON.parseObject(result);
// 检查是否有错误
if (json.containsKey("errcode")) {
Integer errcode = json.getInteger("errcode");
String errmsg = json.getString("errmsg");
System.err.println("微信API错误 - errcode: " + errcode + ", errmsg: " + errmsg);
if (errcode == 40125) {
throw new RuntimeException("微信AppSecret配置错误,请检查并更新正确的AppSecret");
} else if (errcode == 40013) {

8
src/main/java/com/gxwebsoft/common/system/mapper/SettingMapper.java

@ -38,12 +38,4 @@ public interface SettingMapper extends BaseMapper<Setting> {
@InterceptorIgnore(tenantLine = "true")
Setting getBySettingKeyIgnore(@Param("param") SettingParam param);
/**
* 跨库查询指定租户的设置配置
* @param settingKey 设置键
* @param tenantId 租户ID
* @return Setting
*/
@InterceptorIgnore(tenantLine = "true")
Setting getCrossDbSetting(@Param("settingKey") String settingKey, @Param("tenantId") Integer tenantId);
}

9
src/main/java/com/gxwebsoft/common/system/mapper/xml/SettingMapper.xml

@ -30,13 +30,4 @@
<include refid="selectSql"></include>
</select>
<!-- 跨库查询指定租户的设置配置 -->
<select id="getCrossDbSetting" resultType="com.gxwebsoft.common.system.entity.Setting">
SELECT a.*
FROM gxwebsoft_core.sys_setting a
WHERE a.setting_key = #{settingKey}
AND a.tenant_id = #{tenantId}
AND a.deleted = 0
</select>
</mapper>

93
src/main/java/com/gxwebsoft/common/system/service/impl/SettingServiceImpl.java

@ -113,47 +113,7 @@ public class SettingServiceImpl extends ServiceImpl<SettingMapper, Setting> impl
@Override
@IgnoreTenant("跨租户获取指定租户的设置配置")
public JSONObject getBySettingKeyIgnoreTenant(String key, Integer tenantId) {
System.out.println("跨租户查询设置 - key: " + key + ", tenantId: " + tenantId);
final List<Setting> list = list(new LambdaQueryWrapper<Setting>().eq(Setting::getTenantId, tenantId));
System.out.println("跨租户获取指定租户的设置配置 list = " + list);
// 使用跨租户查询,指定租户ID - 通过XML方式查询跨库数据(方式二:更简洁的方法)
Setting setting = baseMapper.getCrossDbSetting(key, tenantId);
System.out.println("跨租户查询结果: " + setting);
if(setting == null){
if ("mp-weixin".equals(key)) {
// 尝试从cms_website_field表中读取微信小程序配置
JSONObject websiteFieldConfig = getWeixinConfigFromWebsiteField(tenantId);
if (websiteFieldConfig != null) {
System.out.println("从cms_website_field表获取到微信小程序配置: " + websiteFieldConfig);
return websiteFieldConfig;
}
throw new BusinessException("租户 " + tenantId + " 的小程序未配置,请先在系统设置中配置微信小程序信息");
}
if ("payment".equals(key)) {
throw new BusinessException("租户 " + tenantId + " 的支付未配置");
}
if ("sms".equals(key)) {
throw new BusinessException("租户 " + tenantId + " 的短信未配置");
}
if ("wx-work".equals(key)){
throw new BusinessException("租户 " + tenantId + " 的企业微信未配置");
}
if ("setting".equals(key)) {
throw new BusinessException("租户 " + tenantId + " 的基本信息未配置");
}
if ("wx-official".equals(key)) {
throw new BusinessException("租户 " + tenantId + " 的微信公众号未配置");
}
if ("printer".equals(key)) {
throw new BusinessException("租户 " + tenantId + " 的打印机未配置");
}
throw new BusinessException("租户 " + tenantId + " 的配置项 " + key + " 未找到");
}
return JSON.parseObject(setting.getContent());
throw new BusinessException("此方法已废弃,请使用缓存方式获取配置:mp-weixin:" + tenantId);
}
@Override
@ -235,55 +195,4 @@ public class SettingServiceImpl extends ServiceImpl<SettingMapper, Setting> impl
return configMap.get(tenantId.toString());
}
/**
* 从cms_website_field表中获取微信小程序配置
* @param tenantId 租户ID
* @return 微信小程序配置JSON对象
*/
private JSONObject getWeixinConfigFromWebsiteField(Integer tenantId) {
try {
System.out.println("尝试从cms_website_field表获取微信小程序配置 - 租户ID: " + tenantId);
// 查询AppID
CmsWebsiteField appIdField = cmsWebsiteFieldService.getOne(
new LambdaQueryWrapper<CmsWebsiteField>()
.eq(CmsWebsiteField::getName, "AppID")
.eq(CmsWebsiteField::getTenantId, tenantId)
.eq(CmsWebsiteField::getDeleted, 0)
);
// 查询AppSecret
CmsWebsiteField appSecretField = cmsWebsiteFieldService.getOne(
new LambdaQueryWrapper<CmsWebsiteField>()
.eq(CmsWebsiteField::getName, "AppSecret")
.eq(CmsWebsiteField::getTenantId, tenantId)
.eq(CmsWebsiteField::getDeleted, 0)
);
System.out.println("AppID字段查询结果: " + appIdField);
System.out.println("AppSecret字段查询结果: " + appSecretField);
if (appIdField != null && appSecretField != null
&& appIdField.getValue() != null && !appIdField.getValue().trim().isEmpty()
&& appSecretField.getValue() != null && !appSecretField.getValue().trim().isEmpty()) {
// 构建微信小程序配置JSON
JSONObject config = new JSONObject();
config.put("appId", appIdField.getValue().trim());
config.put("appSecret", appSecretField.getValue().trim());
System.out.println("成功从cms_website_field表构建微信小程序配置: " + config);
return config;
} else {
System.out.println("cms_website_field表中未找到完整的AppID和AppSecret配置");
return null;
}
} catch (Exception e) {
System.err.println("从cms_website_field表获取微信小程序配置异常: " + e.getMessage());
e.printStackTrace();
return null;
}
}
}

4
src/main/java/com/gxwebsoft/shop/entity/ShopDealerApply.java

@ -38,6 +38,10 @@ public class ShopDealerApply implements Serializable {
@TableField(exist = false)
private String nickName;
@Schema(description = "手机号码")
@TableField(exist = false)
private String phone;
@Schema(description = "姓名")
private String realName;

2
src/main/java/com/gxwebsoft/shop/mapper/xml/ShopDealerApplyMapper.xml

@ -4,7 +4,7 @@
<!-- 关联查询sql -->
<sql id="selectSql">
SELECT a.*, b.nickname as nickName, c.nickname as refereeName
SELECT a.*, b.nickname as nickName, b.phone, c.nickname as refereeName
FROM shop_dealer_apply a
LEFT JOIN gxwebsoft_core.sys_user b ON a.user_id = b.user_id
LEFT JOIN gxwebsoft_core.sys_user c ON a.referee_id = c.user_id

Loading…
Cancel
Save