Просмотр исходного кода

feat(applet): 实现小程序订单取消功能并优化用户认证流程

- 添加订单主动取消接口,支持用户取消未支付订单
- 优化小程序用户认证逻辑,支持直接操作c_user_info表
- 完善JWT令牌验证流程,增加详细的日志记录
- 更新安全配置,注入UserInfoService用于小程序认证
- 修改数据权限处理器,支持小程序用户无数据权限场景
- 调整控制器路径和接口文档扫描配置
- 修复令牌验证异常处理和黑名单检查逻辑
wzq 2 дней назад
Родитель
Сommit
9fd8e0c9da

+ 2 - 2
src/main/java/com/zsElectric/boot/business/controller/applet/AppletHomeController.java

@@ -13,9 +13,9 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-@Tag(name = "v2.0 主页相关接口")
+@Tag(name = "小程序主页相关接口")
 @RestController
-@RequestMapping("/applet/v1/home")
+@RequestMapping("/applet/v1/homePage")
 @RequiredArgsConstructor
 public class AppletHomeController {
 

+ 12 - 0
src/main/java/com/zsElectric/boot/business/controller/applet/AppletOrderController.java

@@ -91,4 +91,16 @@ public class AppletOrderController {
     public Result<String> orderQuery(@PathVariable("orderNo") String orderNo) throws IOException {
         return Result.success(userOrderInfoService.orderQuery(orderNo));
     }
+
+    /**
+     * 订单主动取消
+     *
+     * @param orderId
+     * @return
+     */
+    @Operation(summary = "订单主动取消")
+    @PutMapping("/cancelOrder/{orderId}")
+    public Result<String> cancelOrder(@PathVariable(name = "orderId") String orderId) {
+        return Result.success(userOrderInfoService.cancelOrder(orderId));
+    }
 }

+ 19 - 0
src/main/java/com/zsElectric/boot/business/service/UserInfoService.java

@@ -64,4 +64,23 @@ public interface UserInfoService extends IService<UserInfo> {
      */
     UserInfoVO getCurrentUserInfo();
 
+    /**
+     * 根据手机号获取用户信息
+     *
+     * @param phone 手机号
+     * @return 用户信息,不存在返回null
+     */
+    UserInfo getUserInfoByPhone(String phone);
+
+    /**
+     * 根据手机号注册或更新用户(小程序用)
+     * <p>
+     * 如果用户不存在则创建,存在则更新openid
+     *
+     * @param phone 手机号
+     * @param openId 微信openid(可为null)
+     * @return 用户信息
+     */
+    UserInfo registerOrUpdateUserByPhone(String phone, String openId);
+
 }

+ 2 - 0
src/main/java/com/zsElectric/boot/business/service/UserOrderInfoService.java

@@ -68,4 +68,6 @@ public interface UserOrderInfoService extends IService<UserOrderInfo> {
     String orderQuery(String orderNo);
 
     Map<String, String> wechatPayNotify(HttpServletRequest request, HttpServletResponse response);
+
+    String cancelOrder(String orderId);
 }

+ 85 - 6
src/main/java/com/zsElectric/boot/business/service/impl/UserInfoServiceImpl.java

@@ -107,33 +107,112 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> i
     /**
      * 获取当前登录用户信息(小程序用)
      * <p>
-     * 根据当前登录用户的手机号获取用户信息
-     * 注意:由于小程序登录创建的是 UserInfo,需要通过手机号查询
+     * 根据当前登录用户的userId获取用户信息
+     * 注意:小程序登录后,token中的userId就是c_user_info表的ID
      *
      * @return 当前用户信息
      */
     @Override
     public UserInfoVO getCurrentUserInfo() {
-        // 从 Spring Security 上下文获取当前登录用户的用户名(即手机号)
+        // 从 Spring Security 上下文获取当前登录用户的ID
+        // 注意:小程序用户token中的userId就是c_user_info表的ID
         Long userId = SecurityUtils.getUserId();
         
         log.info("获取当前用户信息,userId: {}", userId);
         
         if (ObjectUtil.isNull(userId)) {
-            log.warn("未获取到当前登录用户信息");
+            log.warn("未获取到当前登录用户ID");
             return null;
         }
 
-        UserInfo userInfo = this.getById(userId);
+        // 直接通过ID查询c_user_info表
+        UserInfo userInfo = null;
+        try {
+            log.info("准备查询用户信息,userId: {}", userId);
+            userInfo = this.getById(userId);
+            log.info("查询结果: {}", userInfo != null ? "找到用户" : "未找到用户");
+        } catch (Exception e) {
+            log.error("查询用户信息异常,userId: {}, 错误: {}", userId, e.getMessage(), e);
+            throw e;
+        }
         
         if (userInfo == null) {
+            log.warn("未找到用户信息,userId: {}", userId);
             return null;
         }
         
-        log.info("获取用户信息成功,ID: {}, 昵称: {}", userInfo.getId(), userInfo.getNickName());
+        log.info("获取用户信息成功,ID: {}, 昵称: {}, 手机号: {}", 
+                userInfo.getId(), userInfo.getNickName(), userInfo.getPhone());
         
         // 实体转换为VO
         return userInfoConverter.toVO(userInfo);
     }
 
+    /**
+     * 根据手机号获取用户信息
+     *
+     * @param phone 手机号
+     * @return 用户信息,不存在返回null
+     */
+    @Override
+    public UserInfo getUserInfoByPhone(String phone) {
+        if (StrUtil.isBlank(phone)) {
+            return null;
+        }
+        return this.getOne(
+                new LambdaQueryWrapper<UserInfo>()
+                        .eq(UserInfo::getPhone, phone)
+        );
+    }
+
+    /**
+     * 根据手机号注册或更新用户(小程序用)
+     * <p>
+     * 如果用户不存在则创建,存在则更新openid
+     *
+     * @param phone 手机号
+     * @param openId 微信openid(可为null)
+     * @return 用户信息
+     */
+    @Override
+    public UserInfo registerOrUpdateUserByPhone(String phone, String openId) {
+        if (StrUtil.isBlank(phone)) {
+            log.warn("注册用户失败:手机号为空");
+            return null;
+        }
+
+        // 查询用户是否已存在
+        UserInfo existingUser = getUserInfoByPhone(phone);
+
+        if (existingUser != null) {
+            log.info("用户已存在,ID: {}, 手机号: {}", existingUser.getId(), phone);
+            
+            // 如果提供了openId且与现有openId不同,则更新
+            if (StrUtil.isNotBlank(openId) && !openId.equals(existingUser.getOpenid())) {
+                log.info("更新用户openId,ID: {}", existingUser.getId());
+                existingUser.setOpenid(openId);
+                this.updateById(existingUser);
+            }
+            
+            return existingUser;
+        }
+
+        // 用户不存在,创建新用户
+        log.info("创建新用户,手机号: {}, openId: {}", phone, openId);
+        UserInfo newUser = new UserInfo();
+        newUser.setPhone(phone);
+        newUser.setOpenid(openId);
+        newUser.setNickName("微信用户_" + phone.substring(phone.length() - 4));
+        newUser.setIntegralNum(java.math.BigDecimal.ZERO);
+        
+        boolean saved = this.save(newUser);
+        if (!saved) {
+            log.error("保存用户失败,手机号: {}", phone);
+            return null;
+        }
+        
+        log.info("用户创建成功,ID: {}, 手机号: {}", newUser.getId(), phone);
+        return newUser;
+    }
+
 }

+ 14 - 0
src/main/java/com/zsElectric/boot/business/service/impl/UserOrderInfoServiceImpl.java

@@ -265,6 +265,20 @@ public class UserOrderInfoServiceImpl extends ServiceImpl<UserOrderInfoMapper, U
         }
     }
 
+    @Override
+    public String cancelOrder(String orderId) {
+        UserOrderInfo orderInfo = this.getById(orderId);
+        if (ObjectUtil.isNotEmpty(orderInfo)) {
+            if (orderInfo.getOrderStatus() == 1) {
+                log.info("修改订单:{},支付状态为已取消", orderId);
+                orderInfo.setOrderStatus(SystemConstants.STATUS_THREE);
+                this.updateById(orderInfo);
+            }
+            return "取消成功!";
+        }
+        return "取消失败,请刷新后重试!";
+    }
+
     /**
      * 通过商户订单号查询订单在微信侧支付状态
      *

+ 6 - 1
src/main/java/com/zsElectric/boot/config/SecurityConfig.java

@@ -63,6 +63,9 @@ public class SecurityConfig {
     private final ConfigService configService;
     private final SecurityProperties securityProperties;
     private final ThirdPartyJwtAuthFilter thirdPartyAuthFilter;
+    
+    // 注入 UserInfoService 用于小程序认证
+    private final com.zsElectric.boot.business.service.UserInfoService userInfoService;
 
     // 仅针对第三方URL的安全过滤链,只挂第三方认证过滤器
     @Bean
@@ -199,10 +202,12 @@ public class SecurityConfig {
 
     /**
      * 微信小程序手机号Code认证Provider(新版接口)
+     * <p>
+     * 使用 UserInfoService 直接操作 c_user_info 表
      */
     @Bean
     public WxMiniAppPhoneCodeAuthenticationProvider wxMiniAppPhoneCodeAuthenticationProvider() {
-        return new WxMiniAppPhoneCodeAuthenticationProvider(userService, wxMaService);
+        return new WxMiniAppPhoneCodeAuthenticationProvider(userInfoService, wxMaService);
     }
 
     /**

+ 4 - 0
src/main/java/com/zsElectric/boot/plugin/mybatis/MyDataPermissionHandler.java

@@ -39,6 +39,10 @@ public class MyDataPermissionHandler implements DataPermissionHandler {
         }
         // 获取当前用户的数据权限
         Integer dataScope = SecurityUtils.getDataScope();
+        // 小程序用户没有数据权限,直接返回
+        if (dataScope == null) {
+            return where;
+        }
         DataScopeEnum dataScopeEnum = IBaseEnum.getEnumByValue(dataScope, DataScopeEnum.class);
         // 如果是全部数据权限,直接返回
         if (DataScopeEnum.ALL.equals(dataScopeEnum)) {

+ 13 - 0
src/main/java/com/zsElectric/boot/security/filter/TokenAuthenticationFilter.java

@@ -9,6 +9,7 @@ import jakarta.servlet.FilterChain;
 import jakarta.servlet.ServletException;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.http.HttpHeaders;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.context.SecurityContextHolder;
@@ -25,6 +26,7 @@ import java.util.List;
  * @author wangtao
  * @since 2025/3/6 16:50
  */
+@Slf4j
 public class TokenAuthenticationFilter extends OncePerRequestFilter {
 
     /**
@@ -43,7 +45,11 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
     @Override
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
 
+        String requestURI = request.getRequestURI();
         String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
+        
+        log.debug("[Token验证] 请求路径: {}, Authorization头: {}", requestURI, 
+                authorizationHeader != null ? authorizationHeader.substring(0, Math.min(20, authorizationHeader.length())) + "..." : "无");
 
         try {
             if (StrUtil.isNotBlank(authorizationHeader)
@@ -51,10 +57,12 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
 
                 // 剥离Bearer前缀获取原始令牌
                 String rawToken = authorizationHeader.substring(SecurityConstants.BEARER_TOKEN_PREFIX.length());
+                log.debug("[Token验证] 开始验证token, 路径: {}", requestURI);
 
                 // 执行令牌有效性检查(包含密码学验签和过期时间验证)
                 boolean isValidToken = tokenManager.validateToken(rawToken);
                 if (!isValidToken) {
+                    log.warn("[Token验证失败] token无效或已过期, 路径: {}", requestURI);
                     WebResponseHelper.writeError(response, ResultCode.ACCESS_TOKEN_INVALID);
                     return;
                 }
@@ -62,9 +70,14 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
                 // 将令牌解析为 Spring Security 上下文认证对象
                 Authentication authentication = tokenManager.parseToken(rawToken);
                 SecurityContextHolder.getContext().setAuthentication(authentication);
+                log.debug("[Token验证成功] 用户: {}, 路径: {}", authentication.getName(), requestURI);
+            } else if (StrUtil.isNotBlank(authorizationHeader)) {
+                log.warn("[Token格式错误] Authorization头不是以'Bearer '开头, 路径: {}, 头部内容: {}", 
+                        requestURI, authorizationHeader.substring(0, Math.min(30, authorizationHeader.length())));
             }
         } catch (Exception ex) {
             // 安全上下文清除保障(防止上下文残留)
+            log.error("[Token验证异常] 路径: {}, 错误: {}", requestURI, ex.getMessage(), ex);
             SecurityContextHolder.clearContext();
             WebResponseHelper.writeError(response, ResultCode.ACCESS_TOKEN_INVALID);
             return;

+ 21 - 31
src/main/java/com/zsElectric/boot/security/provider/WxMiniAppPhoneCodeAuthenticationProvider.java

@@ -2,17 +2,15 @@ package com.zsElectric.boot.security.provider;
 
 import cn.binarywang.wx.miniapp.api.WxMaService;
 import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
-import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
-import com.zsElectric.boot.security.model.SysUserDetails;
-import com.zsElectric.boot.security.model.UserAuthCredentials;
+import com.zsElectric.boot.business.model.entity.UserInfo;
+import com.zsElectric.boot.business.service.UserInfoService;
+import com.zsElectric.boot.security.model.AppletUserDetails;
 import com.zsElectric.boot.security.model.WxMiniAppPhoneCodeAuthenticationToken;
-import com.zsElectric.boot.system.service.UserService;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import org.springframework.security.authentication.AuthenticationProvider;
 import org.springframework.security.authentication.CredentialsExpiredException;
-import org.springframework.security.authentication.DisabledException;
 import org.springframework.security.core.Authentication;
 import org.springframework.security.core.AuthenticationException;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -26,11 +24,11 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
 @Slf4j
 public class WxMiniAppPhoneCodeAuthenticationProvider implements AuthenticationProvider {
 
-    private final UserService userService;
+    private final UserInfoService userInfoService;
     private final WxMaService wxMaService;
 
-    public WxMiniAppPhoneCodeAuthenticationProvider(UserService userService, WxMaService wxMaService) {
-        this.userService = userService;
+    public WxMiniAppPhoneCodeAuthenticationProvider(UserInfoService userInfoService, WxMaService wxMaService) {
+        this.userInfoService = userInfoService;
         this.wxMaService = wxMaService;
     }
 
@@ -55,32 +53,24 @@ public class WxMiniAppPhoneCodeAuthenticationProvider implements AuthenticationP
         String phoneNumber = phoneNumberInfo.getPhoneNumber();
         log.info("通过code获取到手机号: {}", phoneNumber);
 
-        // 2. 根据手机号查询用户,不存在则创建新用户
-        UserAuthCredentials userAuthCredentials = userService.getAuthCredentialsByMobile(phoneNumber);
-
-        if (userAuthCredentials == null) {
-            // 用户不存在,注册新用户(仅手机号,不绑定openId)
-            boolean registered = userService.registerUserByMobileAndOpenId(phoneNumber, null);
-            if (!registered) {
-                throw new UsernameNotFoundException("用户注册失败");
-            }
-            // 重新获取用户信息
-            userAuthCredentials = userService.getAuthCredentialsByMobile(phoneNumber);
-            
-            if (userAuthCredentials == null) {
-                throw new UsernameNotFoundException("用户注册失败");
-            }
-        }
-
-        // 3. 检查用户状态
-        if (ObjectUtil.notEqual(userAuthCredentials.getStatus(), 1)) {
-            throw new DisabledException("用户已被禁用");
+        // 2. 根据手机号注册或更新用户(c_user_info表)
+        UserInfo userInfo = userInfoService.registerOrUpdateUserByPhone(phoneNumber, null);
+        
+        if (userInfo == null) {
+            throw new UsernameNotFoundException("用户注册失败");
         }
+        
+        log.info("用户信息获取成功,ID: {}, 手机号: {}", userInfo.getId(), userInfo.getPhone());
 
-        // 4. 构建认证后的用户详情
-        SysUserDetails userDetails = new SysUserDetails(userAuthCredentials);
+        // 3. 构建小程序用户详情
+        AppletUserDetails userDetails = new AppletUserDetails();
+        userDetails.setUserId(userInfo.getId());
+        userDetails.setPhone(userInfo.getPhone());
+        userDetails.setOpenid(userInfo.getOpenid());
+        userDetails.setNickname(userInfo.getNickName());
+        userDetails.setEnabled(true);
 
-        // 5. 创建已认证的Token
+        // 4. 创建已认证的Token
         return WxMiniAppPhoneCodeAuthenticationToken.authenticated(
                 userDetails,
                 userDetails.getAuthorities()

+ 41 - 7
src/main/java/com/zsElectric/boot/security/token/JwtTokenManager.java

@@ -14,7 +14,9 @@ import com.zsElectric.boot.common.constant.SecurityConstants;
 import com.zsElectric.boot.core.exception.BusinessException;
 import com.zsElectric.boot.core.web.ResultCode;
 import com.zsElectric.boot.config.property.SecurityProperties;
+import com.zsElectric.boot.security.model.AppletUserDetails;
 import com.zsElectric.boot.security.model.AuthenticationToken;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import com.zsElectric.boot.security.model.SysUserDetails;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -40,6 +42,7 @@ import java.util.stream.Collectors;
  * @author Ray.Hao
  * @since 2024/11/15
  */
+@Slf4j
 @ConditionalOnProperty(value = "security.session.type", havingValue = "jwt")
 @Service
 public class JwtTokenManager implements TokenManager {
@@ -136,26 +139,39 @@ public class JwtTokenManager implements TokenManager {
             JWT jwt = JWTUtil.parseToken(token);
             // 检查 Token 是否有效(验签 + 是否过期)
             boolean isValid = jwt.setKey(secretKey).validate(0);
+            
+            log.debug("[JWT验证] Token基础验证结果: {}", isValid);
 
             if (isValid) {
                 // 检查 Token 是否已被加入黑名单(注销、修改密码等场景)
                 JSONObject payloads = jwt.getPayloads();
                 String jti = payloads.getStr(JWTPayload.JWT_ID);
+                String username = payloads.getStr(JWTPayload.SUBJECT);
+                Date expiresAt = payloads.getDate(JWTPayload.EXPIRES_AT);
+                
+                log.debug("[JWT验证] 用户: {}, jti: {}, 过期时间: {}", username, jti, expiresAt);
+                
                 if(validateRefreshToken) {
                     //刷新token需要校验token类别
                     boolean isRefreshToken = payloads.getBool(JwtClaimConstants.TOKEN_TYPE);
                     if (!isRefreshToken) {
+                        log.warn("[JWT验证失败] Token类型不是刷新令牌");
                         return false;
                     }
                 }
                 // 判断是否在黑名单中,如果在,则返回 false 标识Token无效
-                if (Boolean.TRUE.equals(redisTemplate.hasKey(StrUtil.format(RedisConstants.Auth.BLACKLIST_TOKEN, jti)))) {
+                String blacklistKey = StrUtil.format(RedisConstants.Auth.BLACKLIST_TOKEN, jti);
+                if (Boolean.TRUE.equals(redisTemplate.hasKey(blacklistKey))) {
+                    log.warn("[JWT验证失败] Token已在黑名单中, jti: {}", jti);
                     return false;
                 }
+                log.debug("[JWT验证成功] 用户: {}", username);
+            } else {
+                log.warn("[JWT验证失败] Token验签失败或已过期");
             }
             return isValid;
-        } catch (Exception gitignore) {
-            // token 验证
+        } catch (Exception ex) {
+            log.error("[JWT验证异常] 异常信息: {}", ex.getMessage());
         }
         return false;
     }
@@ -240,11 +256,29 @@ public class JwtTokenManager implements TokenManager {
      * @return JWT Token
      */
     private String generateToken(Authentication authentication, int ttl, boolean isRefreshToken) {
-        SysUserDetails userDetails = (SysUserDetails) authentication.getPrincipal();
+        Object principal = authentication.getPrincipal();
         Map<String, Object> payload = new HashMap<>();
-        payload.put(JwtClaimConstants.USER_ID, userDetails.getUserId()); // 用户ID
-        payload.put(JwtClaimConstants.DEPT_ID, userDetails.getDeptId()); // 部门ID
-        payload.put(JwtClaimConstants.DATA_SCOPE, userDetails.getDataScope()); // 数据权限范围
+        
+        // 根据不同的用户类型设置payload
+        if (principal instanceof AppletUserDetails) {
+            // 小程序用户
+            AppletUserDetails appletUser = (AppletUserDetails) principal;
+            payload.put(JwtClaimConstants.USER_ID, appletUser.getUserId()); // 用户ID (c_user_info表)
+            payload.put(JwtClaimConstants.DEPT_ID, null); // 小程序用户无部门
+            payload.put(JwtClaimConstants.DATA_SCOPE, null); // 小程序用户无数据权限范围
+            
+            log.debug("生成小程序用户Token, userId: {}, phone: {}", appletUser.getUserId(), appletUser.getPhone());
+        } else if (principal instanceof SysUserDetails) {
+            // 系统用户
+            SysUserDetails sysUser = (SysUserDetails) principal;
+            payload.put(JwtClaimConstants.USER_ID, sysUser.getUserId()); // 用户ID (sys_user表)
+            payload.put(JwtClaimConstants.DEPT_ID, sysUser.getDeptId()); // 部门ID
+            payload.put(JwtClaimConstants.DATA_SCOPE, sysUser.getDataScope()); // 数据权限范围
+            
+            log.debug("生成系统用户Token, userId: {}, username: {}", sysUser.getUserId(), sysUser.getUsername());
+        } else {
+            throw new BusinessException("不支持的用户类型: " + principal.getClass().getName());
+        }
 
         // claims 中添加角色信息
         Set<String> roles = authentication.getAuthorities().stream()

+ 17 - 1
src/main/java/com/zsElectric/boot/security/util/SecurityUtils.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.StrUtil;
 import com.zsElectric.boot.common.constant.SecurityConstants;
 import com.zsElectric.boot.common.constant.SystemConstants;
+import com.zsElectric.boot.security.model.AppletUserDetails;
 import com.zsElectric.boot.security.model.SysUserDetails;
 import jakarta.servlet.http.HttpServletRequest;
 import org.springframework.http.HttpHeaders;
@@ -43,11 +44,26 @@ public class SecurityUtils {
 
     /**
      * 获取用户ID
+     * <p>
+     * 支持系统用户和小程序用户
      *
      * @return Long
      */
     public static Long getUserId() {
-        return getUser().map(SysUserDetails::getUserId).orElse(null);
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (authentication != null && authentication.getPrincipal() != null) {
+            Object principal = authentication.getPrincipal();
+            
+            // 小程序用户
+            if (principal instanceof AppletUserDetails) {
+                return ((AppletUserDetails) principal).getUserId();
+            }
+            // 系统用户
+            if (principal instanceof SysUserDetails) {
+                return ((SysUserDetails) principal).getUserId();
+            }
+        }
+        return null;
     }
 
 

+ 1 - 0
src/main/resources/application-dev.yml

@@ -215,6 +215,7 @@ springdoc:
         - com.zsElectric.boot.platform.codegen.controller
         - com.zsElectric.boot.charging.controller
         - com.zsElectric.boot.business.controller
+        - com.zsElectric.boot.business.controller.applet
   default-flat-param-object: true
 
 # knife4j 接口文档配置

+ 2 - 0
src/main/resources/application-prod.yml

@@ -175,6 +175,8 @@ springdoc:
         - com.zsElectric.boot.platform.file.controller
         - com.zsElectric.boot.platform.codegen.controller
         - com.zsElectric.boot.charging.controller
+        - com.zsElectric.boot.business.controller
+        - com.zsElectric.boot.business.controller.applet
   default-flat-param-object: true
 
 # knife4j 接口文档配置