基础服务模块 (base)
基础服务模块提供了系统运行所需的核心基础服务,包括多平台配置管理、支付配置管理、广告配置、账号绑定等功能。
模块结构
base/
├── controller/ # 控制器层
│ ├── AdController.java
│ ├── BindController.java
│ ├── PaymentController.java
│ └── PlatformController.java
├── service/ # 服务层
│ ├── IAdService.java
│ ├── IBindService.java
│ ├── IPaymentService.java
│ └── IPlatformService.java
├── domain/ # 数据模型
│ ├── entity/ # 实体类
│ ├── vo/ # 视图对象
│ └── bo/ # 业务对象
├── mapper/ # 数据访问层
└── authStrategy/ # 认证策略核心功能
🏗️ 平台配置管理
支持多种平台的统一配置管理:
- 微信小程序 (mp-weixin)
- 微信公众号 (mp-official-account)
- 支付宝小程序 (mp-alipay)
- QQ小程序 (mp-qq)
- 其他平台 (mp-jd, mp-kuaishou, mp-lark, mp-baidu, mp-toutiao, mp-xhs)
平台配置实体
java
@Data
@TableName("b_platform")
public class Platform extends TenantEntity {
private Long id; // 平台配置ID
private String type; // 平台类型
private String name; // 平台名称
private String appid; // 应用ID
private String secret; // 应用密钥
private String token; // 接口Token
private String aeskey; // 加密密钥
private String paymentIds; // 关联支付配置
private String templateConfigs; // 模板配置
private String status; // 状态
}核心接口
java
public interface IPlatformService extends IBaseService<Platform, PlatformBo, PlatformVo> {
// 继承基础CRUD操作
}
// 全局平台服务
public interface PlatformService {
List<PlatformDTO> listPlatformsByType(String type, String tenantId);
PlatformDTO getPlatformByAppidAndType(String appid, String type);
PlatformDTO getPlatformByAppid(String appid, String tenantId);
}💳 支付配置管理
统一的支付配置管理,支持多种支付方式:
支付配置实体
java
@Data
@TableName("b_payment")
public class Payment extends TenantEntity {
private Long id; // 支付配置ID
private String type; // 商户类型
private String mchName; // 商户名称
private String mchId; // 商户号
private String mchKey; // 商户密钥
private String apiV3Key; // APIv3密钥
private String certPath; // 证书路径
private String keyPath; // 密钥路径
private String certSerialNo; // 证书序列号
private String status; // 状态
}核心服务
java
public interface PaymentService {
List<PaymentDTO> listPaymentByType(String type, String tenantId);
PaymentDTO getByMchId(String mchId);
PaymentDTO getById(Long paymentId);
boolean existsValidMchId(String mchId);
long countPayments();
}📱 账号绑定管理
管理用户在不同平台的账号绑定关系:
绑定实体
java
@Data
@TableName("b_bind")
public class Bind extends TenantEntity {
private Long id; // 绑定ID
private Long userId; // 用户ID
private String platformType; // 平台类型
private String appid; // 应用ID
private String unionid; // 统一标识
private String openid; // 平台标识
private String extraData; // 扩展数据
}绑定服务
java
public interface IBindService extends IBaseService<Bind, BindBo, BindVo> {
/**
* 根据平台用户信息获取或创建绑定信息
*/
BindVo getOrCreateBind(PlatformUserInfoVo platformUserInfoVo);
/**
* 更新绑定信息的用户ID
*/
void updateBindUserId(BindBo bindBo, Long userId);
}📢 广告配置管理
提供广告位和广告内容的统一管理:
广告实体
java
@Data
@TableName("b_ad")
public class Ad extends TenantEntity {
private Long id; // 广告ID
private String appid; // 应用ID
private String adUnitId; // 广告位ID
private String adName; // 广告名称
private String adType; // 广告类型
private String position; // 投放位置
private String img; // 广告图片
private String description; // 描述
private String jumpAppid; // 跳转应用ID
private String jumpPath; // 跳转路径
private String styleConfig; // 样式配置
private Long sortOrder; // 排序值
private String status; // 状态
}认证策略
多平台认证架构
基于策略模式实现多平台登录认证:
认证策略接口
java
public interface IAuthStrategy {
String BASE_NAME = "AuthStrategy";
AuthTokenVo login(String body);
}小程序认证策略
java
@Service("miniapp" + IAuthStrategy.BASE_NAME)
public class MiniappAuthStrategy implements IAuthStrategy {
@Override
public AuthTokenVo login(String body) {
// 1. 解析请求参数
PlatformLoginBody loginBody = JsonUtils.parseObject(body, PlatformLoginBody.class);
// 2. 获取平台用户信息
PlatformUserInfoVo platformUserInfo = getMiniappUserIdentity(loginBody);
// 3. 加载或创建用户
SysUserVo user = loadOrCreateUser(platformUserInfo);
// 4. 生成登录令牌
LoginUser loginUser = loginService.createLoginUser(user);
loginUser.setPlatform(platformUserInfo.getPlatform());
loginUser.setAppid(platformUserInfo.getAppid());
loginUser.setOpenid(platformUserInfo.getOpenid());
loginUser.setUnionid(platformUserInfo.getUnionid());
// 5. 完成登录
LoginHelper.login(loginUser, loginParameter);
// 6. 返回认证结果
AuthTokenVo authTokenVo = new AuthTokenVo();
authTokenVo.setAccessToken(StpUtil.getTokenValue());
authTokenVo.setExpireIn(StpUtil.getTokenTimeout());
return authTokenVo;
}
}公众号认证策略
java
@Service("mp" + IAuthStrategy.BASE_NAME)
public class MpAuthStrategy implements IAuthStrategy {
// 公众号OAuth2.0认证流程实现
// 支持网页授权登录场景
}认证流程
- 前端授权:用户在前端完成平台授权,获取授权码
- 策略选择:后端根据平台类型自动选择对应认证策略
- 信息获取:通过授权码换取用户基本信息
- 账号绑定:查找或创建用户账号绑定关系
- 令牌生成:生成JWT访问令牌
- 登录完成:返回令牌和用户信息
手机号绑定
微信小程序手机号获取
java
@PostMapping("/bindPhone")
public R<PhoneBindVo> bindPhone(@RequestBody PhoneBindBo bo) {
LoginUser loginUser = LoginHelper.getLoginUser();
wxMaService.switchover(loginUser.getAppid());
try {
WxMaPhoneNumberInfo phoneInfo = wxMaService.getUserService().getPhoneNumber(bo.getCode());
String phone = phoneInfo.getPhoneNumber();
// 更新用户手机号
SysUser sysUser = userMapper.selectById(loginUser.getUserId());
sysUser.setPhone(phone);
userMapper.updateById(sysUser);
return R.ok("绑定成功", PhoneBindVo.of(phone));
} catch (WxErrorException e) {
return R.fail("获取手机号出错");
}
}数据字典服务
支付方式字典
java
@GetMapping("getPaymentDict")
public R<List<DictItemVo>> getPaymentDict() {
// 查询所有可用的支付方式
List<PaymentVo> paymentVoList = paymentService.list(
PlusLambdaQuery.of(Payment.class)
.eq(Payment::getStatus, DictEnableStatus.ENABLE.getValue()));
// 构建字典项列表
List<DictItemVo> dictItems = StreamUtils.toList(paymentVoList, payment ->
DictItemVo.of(payment.getMchName(), payment.getId().toString(), "success")
);
return R.ok(dictItems);
}配置管理
平台配置热更新
java
private void reloadPlatformConfig() {
String tenantId = TenantHelper.getTenantId();
// 重新初始化微信小程序配置
SpringUtils.getBean(WxMaApplicationRunner.class).initByTenant(tenantId);
// 重新初始化微信公众号配置
SpringUtils.getBean(WxMpApplicationRunner.class).initByTenant(tenantId);
// 重新初始化支付配置
SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);
}支付配置热更新
java
private void reloadPaymentConfig() {
String tenantId = TenantHelper.getTenantId();
SpringUtils.getBean(PayApplicationRunner.class).initByTenant(tenantId);
}使用示例
配置微信小程序
java
// 1. 创建平台配置
PlatformBo platformBo = new PlatformBo();
platformBo.setType("mp-weixin");
platformBo.setName("我的小程序");
platformBo.setAppid("wx1234567890");
platformBo.setSecret("your-secret");
platformBo.setStatus("1");
platformService.add(platformBo);
// 2. 配置支付信息
PaymentBo paymentBo = new PaymentBo();
paymentBo.setType("wechat");
paymentBo.setMchName("我的商户");
paymentBo.setMchId("1234567890");
paymentBo.setMchKey("your-mch-key");
paymentBo.setStatus("1");
paymentService.add(paymentBo);用户登录认证
java
// 前端调用登录接口
POST /auth/login
{
"platform": "miniapp",
"body": {
"platform": "mp-weixin",
"appid": "wx1234567890",
"platformCode": "授权码"
}
}
// 返回结果
{
"code": 200,
"msg": "登录成功",
"data": {
"accessToken": "eyJ0eXAiOiJKV1Q...",
"expireIn": 7200
}
}AI助手功能
🤖 功能概述
基础服务模块集成了强大的AI助手功能,基于 LangChain4j 框架实现,支持多种大语言模型(如 DeepSeek、通义千问、OpenAI、Claude等),为业务系统提供智能化能力。
核心特性:
- 多模型支持 - 灵活切换不同的AI模型提供商
- 多场景应用 - 对话、优化、生成、审核、翻译等场景
- 条件启用 - 通过配置开关控制功能启用
- 权限控制 - 完善的权限校验机制
- 上下文传递 - 支持业务上下文信息传递
AI服务接口
AiController 控制器
java
@RestController
@RequestMapping("/base/ai")
@ConditionalOnProperty(
prefix = "langchain4j",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class AiController {
private final IAiService aiService;
}条件启用说明:
- 需要在配置文件中设置
langchain4j.enabled=true - 如果配置项不存在,默认启用 (
matchIfMissing = true)
1. AI对话功能
通用的AI对话接口,支持自由对话场景。
接口定义
java
@PostMapping("/aiChat")
@OpenApi(value = "AI对话")
public R<AiChatVo> aiChat(@Valid @RequestBody AiChatBo bo) {
return R.ok(aiService.aiChat(bo));
}请求示例
java
// 创建对话请求
AiChatBo chatBo = new AiChatBo();
chatBo.setMessage("请帮我解释一下什么是微服务架构");
chatBo.setProvider("deepseek");
chatBo.setModelName("deepseek-chat");
chatBo.setTemperature(0.7);
chatBo.setMaxTokens(2000);
// 调用接口
R<AiChatVo> result = aiController.aiChat(chatBo);
AiChatVo response = result.getData();
System.out.println("AI回复: " + response.getMessage());HTTP 调用示例
bash
POST /base/ai/aiChat
Content-Type: application/json
{
"message": "请帮我解释一下什么是微服务架构",
"provider": "deepseek",
"modelName": "deepseek-chat",
"temperature": 0.7,
"maxTokens": 2000
}2. 文本优化功能
对用户输入的文本进行优化,改善表达和文风。
接口定义
java
@PostMapping("/aiOptimize")
@OpenApi(value = "AI文本优化")
public R<AiChatVo> aiOptimize(@Valid @RequestBody AiChatBo bo) {
return R.ok(aiService.aiOptimize(bo));
}使用场景
- 文章润色和改写
- 产品描述优化
- 邮件内容优化
- 广告文案优化
请求示例
java
AiChatBo optimizeBo = new AiChatBo();
optimizeBo.setMessage("我们公司是做软件开发的,主要业务是给客户做系统");
optimizeBo.setAiFeature("optimize");
optimizeBo.setSystemPrompt("请将下列文本优化为更专业的企业简介");
R<AiChatVo> result = aiController.aiOptimize(optimizeBo);
// 优化后: "我们是一家专业的软件开发公司,致力于为企业客户提供定制化系统解决方案..."3. 数据生成功能
根据用户需求生成结构化数据或内容。
接口定义
java
@PostMapping("/aiGenerate")
@OpenApi(value = "AI数据生成")
public R<AiChatVo> aiGenerate(@Valid @RequestBody AiChatBo bo) {
return R.ok(aiService.aiGenerate(bo));
}使用场景
- 生成测试数据
- 生成产品描述
- 生成代码片段
- 生成用户画像
请求示例
java
AiChatBo generateBo = new AiChatBo();
generateBo.setMessage("生成5个用户的测试数据,包含姓名、年龄、邮箱");
generateBo.setAiFeature("generate");
// 传递表单字段信息作为上下文
Map<String, Object> context = new HashMap<>();
context.put("fields", Arrays.asList("name", "age", "email"));
context.put("count", 5);
generateBo.setContext(context);
R<AiChatVo> result = aiController.aiGenerate(generateBo);生成结果示例:
json
[
{"name": "张三", "age": 28, "email": "zhangsan@example.com"},
{"name": "李四", "age": 32, "email": "lisi@example.com"},
{"name": "王五", "age": 25, "email": "wangwu@example.com"},
{"name": "赵六", "age": 30, "email": "zhaoliu@example.com"},
{"name": "钱七", "age": 27, "email": "qianqi@example.com"}
]4. 内容审核功能
对用户提交的内容进行智能审核,检测违规内容。
接口定义
java
@PostMapping("/aiReview")
@OpenApi(value = "AI内容审核")
public R<AiChatVo> aiReview(@Valid @RequestBody AiChatBo bo) {
return R.ok(aiService.aiReview(bo));
}使用场景
- 评论内容审核
- 文章内容审核
- 用户昵称审核
- 敏感词检测
请求示例
java
AiChatBo reviewBo = new AiChatBo();
reviewBo.setMessage("待审核的用户评论内容...");
reviewBo.setAiFeature("review");
reviewBo.setSystemPrompt("请审核以下内容是否包含违规、敏感、广告等不当信息");
R<AiChatVo> result = aiController.aiReview(reviewBo);
AiChatVo response = result.getData();
// 解析审核结果
if (response.getMessage().contains("通过")) {
// 内容合规,允许发布
} else {
// 内容违规,拒绝发布
}5. 文本翻译功能
提供多语言翻译服务。
接口定义
java
@PostMapping("/aiTranslate")
@OpenApi(value = "AI文本翻译")
public R<AiChatVo> aiTranslate(@Valid @RequestBody AiChatBo bo) {
return R.ok(aiService.aiTranslate(bo));
}使用场景
- 多语言网站内容翻译
- 用户评论翻译
- 产品说明翻译
- 客服消息翻译
请求示例
java
AiChatBo translateBo = new AiChatBo();
translateBo.setMessage("Hello, how are you today?");
translateBo.setAiFeature("translate");
translateBo.setSystemPrompt("请将以下英文翻译成中文");
R<AiChatVo> result = aiController.aiTranslate(translateBo);
// 翻译结果: "你好,你今天怎么样?"AI配置说明
LangChain4j 配置
在 application.yml 中配置 LangChain4j:
yaml
langchain4j:
enabled: true # 启用AI功能
# DeepSeek 配置
deepseek:
api-key: ${DEEPSEEK_API_KEY}
base-url: https://api.deepseek.com/v1
model-name: deepseek-chat
temperature: 0.7
max-tokens: 2000
timeout: 60s
# 通义千问配置
qianwen:
api-key: ${QIANWEN_API_KEY}
base-url: https://dashscope.aliyuncs.com/api/v1
model-name: qwen-plus
temperature: 0.7
max-tokens: 2000
# OpenAI 配置
openai:
api-key: ${OPENAI_API_KEY}
base-url: https://api.openai.com/v1
model-name: gpt-3.5-turbo
temperature: 0.7
max-tokens: 2000环境变量配置
推荐使用环境变量管理敏感的API密钥:
bash
# .env 文件
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx
QIANWEN_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx权限配置
在菜单管理中配置AI功能权限:
sql
-- AI对话权限
INSERT INTO sys_menu (menu_name, parent_id, perms)
VALUES ('AI对话', 1000, 'base:ai:chat');AI功能集成示例
示例1:智能客服回复
java
@Service
public class CustomerServiceImpl implements ICustomerService {
@Autowired
private IAiService aiService;
@Override
public String handleCustomerQuestion(String question) {
AiChatBo chatBo = new AiChatBo();
chatBo.setMessage(question);
chatBo.setProvider("deepseek");
chatBo.setSystemPrompt("你是一个友好的客服助手,请专业地回答客户问题");
AiChatVo response = aiService.aiChat(chatBo);
return response.getMessage();
}
}示例2:文章内容审核
java
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements IArticleService {
@Autowired
private IAiService aiService;
@Override
public boolean publishArticle(Article article) {
// 使用AI审核文章内容
AiChatBo reviewBo = new AiChatBo();
reviewBo.setMessage(article.getContent());
reviewBo.setAiFeature("review");
reviewBo.setSystemPrompt("请审核文章内容是否合规,检查是否包含违规、敏感信息");
AiChatVo reviewResult = aiService.aiReview(reviewBo);
// 判断审核结果
if (reviewResult.getMessage().contains("违规")) {
throw new ServiceException("文章内容审核未通过: " + reviewResult.getMessage());
}
// 审核通过,发布文章
article.setStatus("published");
return this.updateById(article);
}
}示例3:数据智能生成
java
@Service
public class DataGeneratorService {
@Autowired
private IAiService aiService;
@Override
public List<User> generateTestUsers(int count) {
AiChatBo generateBo = new AiChatBo();
generateBo.setMessage(
String.format("生成%d个用户测试数据,包含真实的中文姓名、邮箱、手机号", count)
);
generateBo.setAiFeature("generate");
// 传递数据结构上下文
Map<String, Object> context = new HashMap<>();
context.put("format", "json");
context.put("fields", Arrays.asList("name", "email", "phone", "age", "gender"));
generateBo.setContext(context);
AiChatVo response = aiService.aiGenerate(generateBo);
// 解析生成的JSON数据
return JsonUtils.parseArray(response.getMessage(), User.class);
}
}数据访问层架构
DAO模式说明
基础服务模块采用 DAO(Data Access Object) 模式,将数据访问逻辑与业务逻辑分离,提供更清晰的架构层次。
架构层次
Controller 层
↓
Service 层
↓
DAO 层 (IBaseDao)
↓
Entity 层 (数据库实体)IBaseDao 接口
所有 DAO 接口都继承自 IBaseDao,提供统一的 CRUD 操作:
java
public interface IBaseDao<T> {
// 插入
boolean insert(T entity);
boolean insertBatch(Collection<T> entityList);
// 更新
boolean updateById(T entity);
boolean updateBatchById(Collection<T> entityList);
// 删除
boolean deleteById(Serializable id);
boolean deleteBatchIds(Collection<?> idList);
// 查询
T selectById(Serializable id);
List<T> selectBatchIds(Collection<? extends Serializable> idList);
List<T> selectList(Wrapper<T> queryWrapper);
T selectOne(Wrapper<T> queryWrapper);
Long selectCount(Wrapper<T> queryWrapper);
// 分页查询
Page<T> selectPage(Page<T> page, Wrapper<T> queryWrapper);
}平台配置DAO (IPlatformDao)
java
public interface IPlatformDao extends IBaseDao<Platform> {
/**
* 根据业务对象构建查询条件
*/
PlusLambdaQuery<Platform> buildQueryWrapper(PlatformBo bo);
/**
* 根据appid查询平台配置
*/
Platform getByAppid(String appid);
/**
* 根据appid和平台类型查询平台配置
*/
Platform getByAppidAndType(String appid, String type, String status);
/**
* 根据平台类型和状态查询配置列表
*/
List<Platform> listByTypeAndStatus(String type, String status);
}支付配置DAO (IPaymentDao)
java
public interface IPaymentDao extends IBaseDao<Payment> {
/**
* 根据商户号查询支付配置
*/
Payment getByMchId(String mchId, String status);
/**
* 根据支付类型和状态查询配置列表
*/
List<Payment> listByTypeAndStatus(String type, String status);
/**
* 根据状态统计配置数量
*/
long countByStatus(String status);
/**
* 根据商户号查询是否存在(排除指定ID)
*/
boolean existsByMchId(String mchId, Long excludeId);
/**
* 根据商户号和状态判断是否存在
*/
boolean existsByMchIdAndStatus(String mchId, String status);
/**
* 根据状态查询配置列表
*/
List<Payment> listByStatus(String status);
}DAO层使用示例
java
@Service
public class PlatformServiceImpl implements IPlatformService {
@Autowired
private IPlatformDao platformDao;
@Override
public PlatformVo getWeixinPlatform(String appid) {
// 使用DAO查询微信小程序配置
Platform platform = platformDao.getByAppidAndType(
appid,
"mp-weixin",
DictEnableStatus.ENABLE.getValue()
);
if (platform == null) {
throw new ServiceException("未找到微信小程序配置");
}
return BeanUtil.toBean(platform, PlatformVo.class);
}
@Override
public List<PlatformVo> listActivePlatforms(String type) {
// 使用DAO查询所有启用的平台配置
List<Platform> platforms = platformDao.listByTypeAndStatus(
type,
DictEnableStatus.ENABLE.getValue()
);
return BeanUtil.copyToList(platforms, PlatformVo.class);
}
}高级功能
多租户支持
基础服务模块所有实体类都继承自 TenantEntity,自动支持多租户数据隔离。
租户实体基类
java
@Data
public class TenantEntity extends BaseEntity {
/**
* 租户ID
*/
@TableField(value = "tenant_id")
private String tenantId;
/**
* 创建部门
*/
@TableField(value = "create_dept")
private Long createDept;
}自动租户隔离
java
// 查询时自动添加租户条件
Platform platform = platformDao.selectById(platformId);
// SQL: SELECT * FROM b_platform WHERE id = ? AND tenant_id = '当前租户ID'
// 新增时自动填充租户ID
Platform newPlatform = new Platform();
newPlatform.setType("mp-weixin");
platformDao.insert(newPlatform);
// SQL: INSERT INTO b_platform (..., tenant_id) VALUES (..., '当前租户ID')数据缓存机制
Redis缓存配置
平台配置和支付配置支持Redis缓存,提升查询性能:
java
@Service
public class PlatformCacheService {
private static final String PLATFORM_CACHE_KEY = "platform:config:";
private static final Duration CACHE_EXPIRE = Duration.ofHours(1);
@Autowired
private RedisTemplate<String, Platform> redisTemplate;
@Autowired
private IPlatformDao platformDao;
public Platform getPlatformWithCache(String appid) {
String cacheKey = PLATFORM_CACHE_KEY + appid;
// 尝试从缓存获取
Platform platform = redisTemplate.opsForValue().get(cacheKey);
if (platform != null) {
return platform;
}
// 缓存未命中,查询数据库
platform = platformDao.getByAppid(appid);
if (platform != null) {
// 写入缓存
redisTemplate.opsForValue().set(cacheKey, platform, CACHE_EXPIRE);
}
return platform;
}
public void clearPlatformCache(String appid) {
String cacheKey = PLATFORM_CACHE_KEY + appid;
redisTemplate.delete(cacheKey);
}
}事件监听机制
配置变更事件
java
@Component
public class PlatformConfigEventListener {
@Autowired
private WxMaApplicationRunner wxMaRunner;
@Autowired
private WxMpApplicationRunner wxMpRunner;
/**
* 监听平台配置变更事件
*/
@EventListener
public void handlePlatformConfigChange(PlatformConfigChangeEvent event) {
String tenantId = event.getTenantId();
String platformType = event.getPlatformType();
// 根据平台类型重新初始化配置
if ("mp-weixin".equals(platformType)) {
wxMaRunner.initByTenant(tenantId);
} else if ("mp-official-account".equals(platformType)) {
wxMpRunner.initByTenant(tenantId);
}
log.info("平台配置已更新: tenantId={}, platformType={}", tenantId, platformType);
}
}自定义事件
java
@Data
public class PlatformConfigChangeEvent extends ApplicationEvent {
private String tenantId;
private String platformType;
private String action; // create, update, delete
public PlatformConfigChangeEvent(Object source, String tenantId, String platformType, String action) {
super(source);
this.tenantId = tenantId;
this.platformType = platformType;
this.action = action;
}
}
// 发布事件
@Service
public class PlatformServiceImpl implements IPlatformService {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Override
@Transactional
public boolean updatePlatform(PlatformBo bo) {
boolean result = platformDao.updateById(BeanUtil.toBean(bo, Platform.class));
if (result) {
// 发布配置变更事件
eventPublisher.publishEvent(
new PlatformConfigChangeEvent(this, TenantHelper.getTenantId(), bo.getType(), "update")
);
}
return result;
}
}常见问题
Q1: 平台配置不生效?
问题原因:
- 配置状态未启用
- 租户ID不匹配
- 缓存未更新
- appid配置错误
解决方案:
java
// 1. 检查配置状态
Platform platform = platformDao.getByAppid(appid);
if (!"1".equals(platform.getStatus())) {
throw new ServiceException("平台配置未启用");
}
// 2. 检查租户ID
String currentTenantId = TenantHelper.getTenantId();
if (!currentTenantId.equals(platform.getTenantId())) {
throw new ServiceException("平台配置不属于当前租户");
}
// 3. 清除缓存重新加载
wxMaApplicationRunner.initByTenant(currentTenantId);Q2: 第三方登录失败?
问题原因:
- appid或secret配置错误
- 授权码已过期
- 平台配置未找到
- 网络连接问题
解决方案:
java
try {
// 使用授权码登录
AuthTokenVo authToken = authStrategy.login(loginBody);
} catch (WxErrorException e) {
// 微信接口调用失败
log.error("微信登录失败: errCode={}, errMsg={}", e.getError().getErrorCode(), e.getError().getErrorMsg());
if (e.getError().getErrorCode() == 40029) {
throw new ServiceException("授权码无效或已过期,请重新授权");
} else if (e.getError().getErrorCode() == 40013) {
throw new ServiceException("appid配置错误");
} else {
throw new ServiceException("登录失败: " + e.getError().getErrorMsg());
}
}Q3: 支付配置重复?
问题原因:
- 同一商户号被多次配置
- 未进行唯一性校验
解决方案:
java
@Service
public class PaymentServiceImpl implements IPaymentService {
@Override
public boolean addPayment(PaymentBo bo) {
// 检查商户号是否已存在
boolean exists = paymentDao.existsByMchIdAndStatus(
bo.getMchId(),
DictEnableStatus.ENABLE.getValue()
);
if (exists) {
throw new ServiceException("该商户号已存在有效配置");
}
Payment payment = BeanUtil.toBean(bo, Payment.class);
return paymentDao.insert(payment);
}
@Override
public boolean updatePayment(PaymentBo bo) {
// 检查商户号是否与其他记录重复(排除当前记录)
boolean exists = paymentDao.existsByMchId(bo.getMchId(), bo.getId());
if (exists) {
throw new ServiceException("该商户号已被其他配置使用");
}
Payment payment = BeanUtil.toBean(bo, Payment.class);
return paymentDao.updateById(payment);
}
}Q4: AI功能无法使用?
问题原因:
- LangChain4j未启用
- API密钥配置错误
- 网络连接问题
- 权限未配置
解决方案:
yaml
# 1. 确保配置已启用
langchain4j:
enabled: true # 必须为 true
# 2. 检查API密钥
deepseek:
api-key: ${DEEPSEEK_API_KEY} # 确保环境变量已设置
# 3. 测试网络连接
curl -X POST https://api.deepseek.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"Hello"}]}'
# 4. 配置权限
INSERT INTO sys_menu (menu_name, perms) VALUES ('AI对话', 'base:ai:chat');故障排查
日志配置
启用详细日志
yaml
logging:
level:
plus.ruoyi.business.base: DEBUG
plus.ruoyi.business.base.controller: DEBUG
plus.ruoyi.business.base.service: DEBUG
plus.ruoyi.business.base.dao: DEBUG
plus.ruoyi.business.base.authStrategy: DEBUG常见错误及解决方案
错误1: 平台配置未找到
错误信息: ServiceException: 未找到平台配置排查步骤:
- 检查数据库中是否存在配置记录
- 检查appid是否正确
- 检查配置状态是否启用
- 检查租户ID是否匹配
java
// 调试代码
Platform platform = platformDao.selectOne(
new LambdaQueryWrapper<Platform>()
.eq(Platform::getAppid, appid)
);
System.out.println("查询到的平台配置: " + JsonUtils.toJsonString(platform));错误2: 认证策略未找到
错误信息: No bean named 'miniappAuthStrategy' available排查步骤:
- 检查认证策略类是否标注
@Service注解 - 检查策略名称是否正确
- 检查Spring扫描路径是否包含策略类
java
// 正确的策略命名
@Service("miniapp" + IAuthStrategy.BASE_NAME) // miniappAuthStrategy
public class MiniappAuthStrategy implements IAuthStrategy {
// ...
}错误3: 多租户数据泄露
错误信息: 查询到了其他租户的数据排查步骤:
- 检查实体类是否继承
TenantEntity - 检查租户拦截器是否生效
- 检查数据表是否包含
tenant_id字段
java
// 确保实体类正确继承
@TableName("b_platform")
public class Platform extends TenantEntity {
// 自动支持租户隔离
}API参考
Controller接口清单
| 控制器 | 路径 | 功能说明 |
|---|---|---|
| PlatformController | /base/platform/* | 平台配置管理 |
| PaymentController | /base/payment/* | 支付配置管理 |
| BindController | /base/bind/* | 账号绑定管理 |
| AdController | /base/ad/* | 广告配置管理 |
| AiController | /base/ai/* | AI助手功能 |
核心接口详情
平台配置接口
java
GET /base/platform/list 查询平台配置列表
GET /base/platform/{id} 查询平台配置详情
POST /base/platform 新增平台配置
PUT /base/platform 更新平台配置
DELETE /base/platform/{ids} 删除平台配置
GET /base/platform/dict 获取平台字典支付配置接口
java
GET /base/payment/list 查询支付配置列表
GET /base/payment/{id} 查询支付配置详情
POST /base/payment 新增支付配置
PUT /base/payment 更新支付配置
DELETE /base/payment/{ids} 删除支付配置
GET /base/payment/dict 获取支付方式字典账号绑定接口
java
GET /base/bind/list 查询绑定列表
POST /base/bind/bindPhone 绑定手机号
POST /base/bind/unbind 解除绑定AI助手接口
java
POST /base/ai/aiChat AI对话
POST /base/ai/aiOptimize 文本优化
POST /base/ai/aiGenerate 数据生成
POST /base/ai/aiReview 内容审核
POST /base/ai/aiTranslate 文本翻译最佳实践
📋 配置管理
- 敏感信息(如密钥)使用环境变量或加密存储
- 支持配置热更新,通过事件机制通知相关服务
- 按租户隔离配置,确保数据安全
- 使用Redis缓存常用配置,提升性能
🔐 安全考虑
- 登录令牌设置合理的过期时间(建议2小时)
- 敏感API添加
@SaCheckPermission权限校验 - 支付配置访问权限严格控制
- AI接口调用添加频率限制,防止滥用
- API密钥使用环境变量管理,不提交到代码仓库
🚀 性能优化
- 平台配置和支付配置使用Redis缓存,有效期1小时
- 异步处理配置更新,使用Spring事件机制
- 合理使用数据库索引(appid、mchId等字段)
- AI接口调用使用连接池,复用HTTP连接
- 批量查询使用
selectBatchIds而不是循环查询
🔧 扩展建议
- 新增平台时,实现对应的
IAuthStrategy认证策略 - 支付方式扩展遵循统一的 DAO 接口规范
- 配置项变更通过
ApplicationEventPublisher发布事件 - AI功能扩展可添加新的服务方法,保持接口一致性
- 建议为每个租户配置独立的平台和支付配置
