diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/API接口文档.md b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/API接口文档.md deleted file mode 100644 index 06fc2c6..0000000 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/API接口文档.md +++ /dev/null @@ -1,357 +0,0 @@ -# 小程序登录API接口文档 - -## 概述 -本文档描述小程序登录模块的API接口,包括登录、用户管理、token管理等功能。 - -## 基础信息 -- **基础URL**: `http://your-domain/applet/login` -- **请求方式**: GET/POST -- **数据格式**: JSON -- **字符编码**: UTF-8 - -## 通用响应格式 -```json -{ - "success": true, - "message": "操作成功", - "code": 200, - "result": {} -} -``` - -## 接口列表 - -### 1. 微信小程序登录 - -**接口地址**: `POST /wxLogin` - -**请求参数**: -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| code | String | 是 | 微信登录code | - -**请求示例**: -```bash -curl -X POST "http://your-domain/applet/login/wxLogin" \ - -H "Content-Type: application/x-www-form-urlencoded" \ - -d "code=wx_login_code_here" -``` - -**响应示例**: -```json -{ - "success": true, - "message": "登录成功", - "code": 200, - "result": { - "token": "eyJhbGciOiJIUzI1NiJ9...", - "userInfo": { - "id": "applet_user_123", - "name": "微信用户12345678", - "openid": "wx_openid_123", - "phone": "13800138000", - "avatar": "https://example.com/avatar.jpg", - "bmi": 22.5, - "fat": 15.2 - }, - "openid": "wx_openid_123", - "sessionKey": "session_key_123" - } -} -``` - -### 2. 获取用户手机号 - -**接口地址**: `POST /getPhoneNumber` - -**请求参数**: -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| code | String | 是 | 手机号获取code | - -**请求示例**: -```bash -curl -X POST "http://your-domain/applet/login/getPhoneNumber" \ - -H "Content-Type: application/x-www-form-urlencoded" \ - -d "code=phone_code_here" -``` - -**响应示例**: -```json -{ - "success": true, - "message": "获取成功", - "code": 200, - "result": "13800138000" -} -``` - -### 3. 绑定手机号到用户 - -**接口地址**: `POST /bindPhoneNumber` - -**请求参数**: -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| token | String | 是 | 用户token | -| phoneCode | String | 是 | 手机号获取code | - -**请求示例**: -```bash -curl -X POST "http://your-domain/applet/login/bindPhoneNumber" \ - -H "Content-Type: application/x-www-form-urlencoded" \ - -d "token=user_token_here&phoneCode=phone_code_here" -``` - -**响应示例**: -```json -{ - "success": true, - "message": "绑定成功", - "code": 200, - "result": "绑定成功" -} -``` - -### 4. 刷新token - -**接口地址**: `POST /refreshToken` - -**请求参数**: -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| token | String | 是 | 原token | - -**请求示例**: -```bash -curl -X POST "http://your-domain/applet/login/refreshToken" \ - -H "Content-Type: application/x-www-form-urlencoded" \ - -d "token=old_token_here" -``` - -**响应示例**: -```json -{ - "success": true, - "message": "刷新成功", - "code": 200, - "result": "eyJhbGciOiJIUzI1NiJ9..." -} -``` - -### 5. 退出登录 - -**接口地址**: `POST /logout` - -**请求参数**: -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| token | String | 是 | 用户token | - -**请求示例**: -```bash -curl -X POST "http://your-domain/applet/login/logout" \ - -H "Content-Type: application/x-www-form-urlencoded" \ - -d "token=user_token_here" -``` - -**响应示例**: -```json -{ - "success": true, - "message": "退出成功", - "code": 200, - "result": "退出成功" -} -``` - -### 6. 检查登录状态 - -**接口地址**: `GET /checkLogin` - -**请求参数**: -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| token | String | 是 | 用户token | - -**请求示例**: -```bash -curl -X GET "http://your-domain/applet/login/checkLogin?token=user_token_here" -``` - -**响应示例**: -```json -{ - "success": true, - "message": "登录有效", - "code": 200, - "result": { - "id": "applet_user_123", - "name": "微信用户12345678", - "openid": "wx_openid_123", - "phone": "13800138000", - "avatar": "https://example.com/avatar.jpg", - "bmi": 22.5, - "fat": 15.2 - } -} -``` - -### 7. 获取用户信息 - -**接口地址**: `GET /getUserInfo` - -**请求参数**: -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| token | String | 是 | 用户token | - -**请求示例**: -```bash -curl -X GET "http://your-domain/applet/login/getUserInfo?token=user_token_here" -``` - -**响应示例**: -```json -{ - "success": true, - "message": "获取成功", - "code": 200, - "result": { - "id": "applet_user_123", - "name": "微信用户12345678", - "openid": "wx_openid_123", - "phone": "13800138000", - "avatar": "https://example.com/avatar.jpg", - "bmi": 22.5, - "fat": 15.2 - } -} -``` - -### 8. 更新用户信息 - -**接口地址**: `POST /updateUserInfo` - -**请求参数**: -| 参数名 | 类型 | 必填 | 说明 | -|--------|------|------|------| -| token | String | 是 | 用户token | -| userInfo | Object | 是 | 用户信息对象 | - -**请求示例**: -```bash -curl -X POST "http://your-domain/applet/login/updateUserInfo" \ - -H "Content-Type: application/json" \ - -d '{ - "token": "user_token_here", - "userInfo": { - "name": "新昵称", - "avatar": "https://example.com/new_avatar.jpg", - "bmi": 23.0, - "fat": 16.0 - } - }' -``` - -**响应示例**: -```json -{ - "success": true, - "message": "更新成功", - "code": 200, - "result": "更新成功" -} -``` - -## 错误码说明 - -| 错误码 | 说明 | -|--------|------| -| 200 | 成功 | -| 400 | 请求参数错误 | -| 401 | 未授权/token无效 | -| 403 | 禁止访问 | -| 404 | 资源不存在 | -| 500 | 服务器内部错误 | - -## 常见错误响应 - -### 1. token无效 -```json -{ - "success": false, - "message": "token无效", - "code": 401, - "result": null -} -``` - -### 2. 用户不存在 -```json -{ - "success": false, - "message": "用户不存在", - "code": 404, - "result": null -} -``` - -### 3. 微信登录失败 -```json -{ - "success": false, - "message": "微信登录失败: code无效", - "code": 400, - "result": null -} -``` - -### 4. 手机号已被绑定 -```json -{ - "success": false, - "message": "该手机号已被其他用户绑定", - "code": 400, - "result": null -} -``` - -## 使用流程 - -### 1. 小程序登录流程 -1. 小程序端调用 `wx.login()` 获取code -2. 调用 `/wxLogin` 接口进行登录 -3. 保存返回的token用于后续请求 - -### 2. 手机号绑定流程 -1. 小程序端调用 `wx.getPhoneNumber()` 获取手机号code -2. 调用 `/getPhoneNumber` 接口获取手机号 -3. 调用 `/bindPhoneNumber` 接口绑定手机号到用户 - -### 3. token管理流程 -1. 定期调用 `/refreshToken` 刷新token -2. 退出时调用 `/logout` 接口 -3. 使用 `/checkLogin` 检查登录状态 - -## 安全注意事项 - -1. **token安全**: token应该安全存储,不要暴露给第三方 -2. **HTTPS**: 生产环境必须使用HTTPS -3. **参数验证**: 客户端应该验证所有参数 -4. **错误处理**: 客户端应该妥善处理各种错误情况 -5. **日志记录**: 重要操作应该记录日志 - -## 性能优化建议 - -1. **缓存**: 用户信息可以适当缓存 -2. **连接池**: 数据库和Redis连接池配置合理 -3. **异步处理**: 非关键操作可以使用异步处理 -4. **监控**: 添加接口调用监控和性能指标 - -## 测试建议 - -1. **单元测试**: 为每个接口编写单元测试 -2. **集成测试**: 测试完整的登录流程 -3. **压力测试**: 测试高并发场景 -4. **安全测试**: 测试各种异常情况 \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/AppletShiroRealm触发问题分析.md b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/AppletShiroRealm触发问题分析.md deleted file mode 100644 index f557a5e..0000000 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/AppletShiroRealm触发问题分析.md +++ /dev/null @@ -1,224 +0,0 @@ -# AppletShiroRealm 触发问题分析 - -## 问题原因分析 - -### 1. 主要问题 -`AppletShiroRealm` 没有被触发的主要原因是: - -1. **Shiro配置问题**: 在 `ShiroConfig.java` 中,`shiroFilter` 方法使用的是 `SecurityManager` 参数,但这个参数绑定的是 `securityManager` Bean,而不是 `appletSecurityManager`。 - -2. **过滤器配置问题**: 虽然配置了 `AppletJwtFilter`,但它没有正确关联到 `AppletShiroRealm`。 - -3. **用户服务接口问题**: `IAppletUserService` 的包路径发生了变化,导致依赖注入失败。 - -### 2. 具体问题点 - -#### 2.1 Shiro配置问题 -```java -// 原来的配置 -@Bean("shiroFilterFactoryBean") -public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { - // 这里使用的是 securityManager,而不是 appletSecurityManager -} -``` - -#### 2.2 过滤器链配置问题 -```java -// 小程序请求应该使用 appletApi 过滤器 -filterChainDefinitionMap.put("/appletApi/**", "appletApi"); -``` - -#### 2.3 用户服务依赖问题 -```java -// 原来的包路径 -import org.jeecg.modules.appletBackground.appletUser.service.IAppletUserService; - -// 修改后的包路径 -import org.jeecg.common.api.IAppletUserService; -``` - -## 解决方案 - -### 1. 修复Shiro配置 - -#### 1.1 修改ShiroConfig.java -- 在 `shiroFilter` 方法中添加小程序登录接口的匿名访问配置 -- 确保小程序请求使用正确的过滤器 - -```java -// 小程序登录相关接口不需要认证 -filterChainDefinitionMap.put("/appletApi/login/wxLogin", "anon"); -filterChainDefinitionMap.put("/appletApi/login/getPhoneNumber", "anon"); - -// applet专用过滤器,只处理/applet开头的请求 -filterChainDefinitionMap.put("/appletApi/**", "appletApi"); -``` - -#### 1.2 修复AppletJwtFilter -- 添加登录接口的匿名访问检查 -- 完善token验证逻辑 -- 增加详细的错误日志 - -```java -// 检查是否是登录相关接口,这些接口不需要认证 -if (requestPath.startsWith("/appletApi/login/wxLogin") || - requestPath.startsWith("/appletApi/login/getPhoneNumber")) { - return true; -} -``` - -### 2. 修复用户服务接口 - -#### 2.1 创建统一的IAppletUserService接口 -```java -package org.jeecg.common.api; - -public interface IAppletUserService { - AppletUser getByOpenid(String openid); - AppletUser getByPhone(String phone); - boolean save(AppletUser user); - boolean updateById(AppletUser user); -} -``` - -#### 2.2 实现服务类 -```java -@Service -public class AppletUserServiceImpl extends ServiceImpl - implements IAppletUserService { - // 实现具体方法 -} -``` - -### 3. 修复AppletShiroRealm - -#### 3.1 完善用户获取逻辑 -```java -private AppletUser getAppletUser(String openid) { - try { - // 从数据库查询用户信息 - AppletUser appletUser = appletUserService.getByOpenid(openid); - if (appletUser != null) { - log.debug("从数据库获取到小程序用户: {}", appletUser.getName()); - return appletUser; - } - - log.warn("未找到小程序用户,openid: {}", openid); - return null; - - } catch (Exception e) { - log.error("获取小程序用户信息异常,openid: {}", openid, e); - return null; - } -} -``` - -#### 3.2 完善权限配置 -```java -@Override -protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { - SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); - - // 小程序用户默认权限 - info.addRole("applet_user"); - info.addStringPermission("applet:user:*"); - - return info; -} -``` - -### 4. 修复服务层方法 - -#### 4.1 使用AppletUserUtil获取当前用户 -```java -public Result bindPhoneNumber(String phoneCode) { - try { - // 获取当前登录用户 - AppletUser currentUser = AppletUserUtil.getCurrentAppletUser(); - if (currentUser == null) { - return Result.error("用户未登录"); - } - - // 其他逻辑... - } catch (Exception e) { - log.error("绑定手机号异常", e); - return Result.error("绑定失败: " + e.getMessage()); - } -} -``` - -#### 4.2 简化控制器方法 -```java -@GetMapping("/getUserInfo") -public Result getUserInfo() { - log.info("收到获取用户信息请求"); - return appletApiLoginService.getUserInfo(); -} -``` - -## 测试验证 - -### 1. 创建测试控制器 -```java -@RestController -@RequestMapping("/appletApi/test") -public class AppletTestController { - - @GetMapping("/getCurrentUser") - public Result getCurrentUser() { - AppletUser currentUser = AppletUserUtil.getCurrentAppletUser(); - if (currentUser == null) { - return Result.error("用户未登录"); - } - return Result.OK("获取成功", currentUser); - } -} -``` - -### 2. 测试步骤 -1. 先调用登录接口获取token -2. 使用token调用测试接口 -3. 检查日志中是否有 `AppletShiroRealm` 的调试信息 -4. 验证用户信息是否正确返回 - -## 关键修复点总结 - -### 1. 配置层面 -- ✅ 修复了Shiro配置中的过滤器链 -- ✅ 添加了小程序登录接口的匿名访问 -- ✅ 确保小程序请求使用正确的过滤器 - -### 2. 代码层面 -- ✅ 修复了用户服务接口的包路径问题 -- ✅ 完善了AppletShiroRealm的用户获取逻辑 -- ✅ 添加了详细的日志记录 -- ✅ 使用AppletUserUtil简化用户获取 - -### 3. 测试层面 -- ✅ 创建了测试控制器验证功能 -- ✅ 提供了完整的测试步骤 - -## 预期效果 - -修复后,当访问 `/appletApi/**` 路径的请求时: - -1. **AppletJwtFilter** 会被触发 -2. **AppletShiroRealm** 会进行用户认证 -3. **AppletUserUtil** 可以正确获取当前用户 -4. 日志中会显示相关的调试信息 - -## 注意事项 - -1. **包路径**: 确保所有相关的import语句都使用正确的包路径 -2. **Bean注入**: 确保 `IAppletUserService` 的实现类被正确注册为Spring Bean -3. **数据库**: 确保 `applet_user` 表存在且有数据 -4. **Redis**: 确保Redis服务正常运行 -5. **日志级别**: 建议将 `AppletShiroRealm` 的日志级别设置为DEBUG,便于调试 - -## 调试建议 - -1. 在 `AppletShiroRealm` 的关键方法中添加日志 -2. 检查Spring Bean是否正确注入 -3. 验证数据库连接和查询是否正常 -4. 确认Redis缓存是否正常工作 -5. 使用测试接口逐步验证功能 \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/README-Applet-API.md b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/README-Applet-API.md deleted file mode 100644 index 54ca6bd..0000000 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/README-Applet-API.md +++ /dev/null @@ -1,201 +0,0 @@ -# 小程序基础查询接口文档 - -## 概述 - -本文档描述了小程序基础的不需要登录的查询接口,包括产品、Banner、配置信息等模块的查询功能。 - -## 接口列表 - -### 1. 产品模块 (Product) - -#### 1.1 产品列表查询 -- **接口地址**: `GET /applet/product/list` -- **接口描述**: 分页查询产品,支持按分类、关键词筛选 -- **请求参数**: - - `type` (必填): 产品类型 - - `pageNo` (可选): 页码,默认1 - - `pageSize` (可选): 每页大小,默认10 - - `classId` (可选): 分类ID - - `keyword` (可选): 关键词,支持产品名称、描述、详情模糊搜索 -- **响应示例**: -```json -{ - "success": true, - "message": "操作成功!", - "code": 200, - "result": { - "records": [ - { - "id": "xxx", - "name": "产品名称", - "info": "产品描述", - "type": "产品类型", - "classId": "分类ID", - "originalPrice": 100.00, - "currentPrice": 80.00, - "unit": "单位", - "detail": "产品详情", - "sold": 100, - "content": "产品内容" - } - ], - "total": 100, - "size": 10, - "current": 1 - } -} -``` - -#### 1.2 产品详情查询 -- **接口地址**: `GET /applet/product/detail` -- **接口描述**: 获取单个产品详细信息 -- **请求参数**: - - `id` (必填): 产品ID -- **响应示例**: -```json -{ - "success": true, - "message": "操作成功!", - "code": 200, - "result": { - "id": "xxx", - "name": "产品名称", - "info": "产品描述", - "type": "产品类型", - "classId": "分类ID", - "originalPrice": 100.00, - "currentPrice": 80.00, - "unit": "单位", - "detail": "产品详情", - "sold": 100, - "content": "产品内容" - } -} -``` - -#### 1.3 产品分类查询 -- **接口地址**: `GET /applet/product/category` -- **接口描述**: 根据类型查询产品分类 -- **请求参数**: - - `type` (必填): 产品类型 -- **响应示例**: -```json -{ - "success": true, - "message": "操作成功!", - "code": 200, - "result": [ - { - "id": "xxx", - "name": "分类名称", - "description": "分类描述", - "sortOrder": 1, - "type": "产品类型" - } - ] -} -``` - -### 2. Banner模块 (Banner) - -#### 2.1 Banner列表查询 -- **接口地址**: `GET /applet/banner/list` -- **接口描述**: 获取Banner列表,按类型分组,按排序字段排序 -- **请求参数**: 无 -- **响应示例**: -```json -{ - "success": true, - "message": "操作成功!", - "code": 200, - "result": { - "home": [ - { - "id": "xxx", - "imageUrl": "图片地址", - "linkUrl": "跳转链接", - "sortOrder": 1, - "type": "home" - } - ], - "product": [ - { - "id": "xxx", - "imageUrl": "图片地址", - "linkUrl": "跳转链接", - "sortOrder": 1, - "type": "product" - } - ] - } -} -``` - -### 3. 配置信息模块 (Config) - -#### 3.1 配置列表查询 -- **接口地址**: `GET /applet/config/list` -- **接口描述**: 查询所有配置信息 -- **请求参数**: 无 -- **响应示例**: -```json -{ - "success": true, - "message": "操作成功!", - "code": 200, - "result": [ - { - "id": "xxx", - "code": "配置编码", - "info": "配置描述", - "content": "配置内容", - "type": "配置类型" - } - ] -} -``` - -## 技术特点 - -1. **Lambda查询**: 所有数据库查询都使用MyBatis-Plus的LambdaQueryWrapper,提供类型安全的查询 -2. **模块化设计**: 按业务模块分类,每个模块独立的Controller和Service -3. **复用性高**: 数据库操作复用demo模块的Mapper,避免重复代码 -4. **统一响应**: 使用统一的Result响应格式 -5. **参数校验**: 必填参数校验,可选参数支持默认值 -6. **日志记录**: 所有接口都有详细的日志记录 - -## 使用示例 - -### 查询产品列表 -```bash -curl -X GET "http://localhost:8080/applet/product/list?type=1&pageNo=1&pageSize=10&keyword=测试" -``` - -### 查询产品详情 -```bash -curl -X GET "http://localhost:8080/applet/product/detail?id=xxx" -``` - -### 查询产品分类 -```bash -curl -X GET "http://localhost:8080/applet/product/category?type=1" -``` - -### 查询Banner列表 -```bash -curl -X GET "http://localhost:8080/applet/banner/list" -``` - -### 查询配置列表 -```bash -curl -X GET "http://localhost:8080/applet/config/list" -``` - -## 注意事项 - -1. 所有接口都不需要登录认证 -2. 产品列表查询的type参数为必填项 -3. 分页参数pageNo从1开始 -4. 关键词搜索支持产品名称、描述、详情的模糊匹配 -5. Banner按类型分组返回,便于前端按需使用 -6. 配置信息按编码排序返回 \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/README-Applet-Module.md b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/README-Applet-Module.md deleted file mode 100644 index 62f48c8..0000000 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/README-Applet-Module.md +++ /dev/null @@ -1,272 +0,0 @@ -# 小程序模块使用说明 - -## 概述 - -本模块为健康管理小程序提供后端服务支持,包含登录、用户管理、微信功能等核心功能。 - -## 目录结构 - -``` -jeecgboot-boot-applet/ -├── src/main/java/org/jeecg/modules/ -│ ├── applet/ # 小程序核心模块 -│ │ ├── controller/ # 控制器层 -│ │ │ ├── AppletLoginController.java # 登录控制器 -│ │ │ ├── AppletUserController.java # 用户控制器 -│ │ │ └── WxAppletController.java # 微信控制器 -│ │ └── service/ # 服务层 -│ │ ├── AppletLoginService.java # 登录服务 -│ │ ├── AppletUserService.java # 用户服务 -│ │ └── WxAppletService.java # 微信服务 -│ └── common/ -│ └── wxUtils/ # 微信工具类 -│ ├── WxHttpUtils.java # 微信HTTP工具 -│ └── WxHttpClientUtil.java # 微信HTTP客户端 -└── src/main/resources/ - └── application-applet.yml # 小程序配置文件 -``` - -## 功能模块 - -### 1. 登录模块 (AppletLoginController) - -#### 接口列表 - -- `POST /applet/login/wxLogin` - 微信小程序登录 -- `POST /applet/login/getPhoneNumber` - 获取用户手机号 -- `POST /applet/login/refreshToken` - 刷新token -- `POST /applet/login/logout` - 退出登录 -- `GET /applet/login/checkLogin` - 检查登录状态 - -#### 使用示例 - -```javascript -// 小程序登录 -wx.login({ - success: (res) => { - if (res.code) { - // 发送 res.code 到后台换取 openId, sessionKey, unionId - wx.request({ - url: 'http://your-domain/applet/login/wxLogin', - method: 'POST', - data: { - code: res.code - }, - success: (result) => { - console.log('登录成功', result.data); - // 保存token - wx.setStorageSync('token', result.data.result.token); - } - }); - } - } -}); -``` - -### 2. 用户模块 (AppletUserController) - -#### 接口列表 - -- `GET /applet/user/info` - 获取用户信息 -- `POST /applet/user/update` - 更新用户信息 -- `GET /applet/user/health` - 获取健康信息 -- `POST /applet/user/health/update` - 更新健康信息 -- `GET /applet/user/member` - 获取会员信息 - -#### 使用示例 - -```javascript -// 获取用户信息 -wx.request({ - url: 'http://your-domain/applet/user/info', - method: 'GET', - data: { - userId: 'applet_user_id' - }, - header: { - 'Authorization': 'Bearer ' + wx.getStorageSync('token') - }, - success: (result) => { - console.log('用户信息', result.data); - } -}); -``` - -### 3. 微信模块 (WxAppletController) - -#### 接口列表 - -- `POST /applet/wx/qrcode` - 获取小程序码 -- `POST /applet/wx/subscribe/send` - 发送订阅消息 -- `GET /applet/wx/config` - 获取小程序配置 -- `GET /applet/wx/check` - 检查微信服务器 -- `GET /applet/wx/user/info` - 获取微信用户信息 - -#### 使用示例 - -```javascript -// 获取小程序码 -wx.request({ - url: 'http://your-domain/applet/wx/qrcode', - method: 'POST', - data: { - scene: 'user_id_123', - page: 'pages/index/index' - }, - success: (result) => { - console.log('小程序码', result.data); - } -}); -``` - -## 配置说明 - -### 1. 微信配置 - -在 `application-applet.yml` 中配置微信小程序信息: - -```yaml -applet: - wechat: - mpAppId: your_applet_appid - mpAppSecret: your_applet_secret - pay: - mchId: your_mch_id - mchKey: your_mch_key -``` - -### 2. 环境变量 - -可以通过环境变量覆盖配置: - -```bash -export WECHAT_MP_APPID=your_applet_appid -export WECHAT_MP_APPSECRET=your_applet_secret -export WECHAT_MCH_ID=your_mch_id -export WECHAT_MCH_KEY=your_mch_key -``` - -### 3. 功能开关 - -可以通过配置文件控制功能模块的启用: - -```yaml -applet: - features: - login: true # 登录功能 - userInfo: true # 用户信息功能 - healthInfo: true # 健康信息功能 - member: true # 会员功能 - subscribe: true # 订阅消息功能 - qrcode: true # 小程序码功能 -``` - -## 安全配置 - -### 1. Token配置 - -```yaml -applet: - security: - tokenExpireTime: 7200 # token过期时间(秒) - refreshTokenExpireTime: 604800 # 刷新token过期时间(秒) - enableTokenBlacklist: true # 启用token黑名单 -``` - -### 2. 接口权限 - -所有小程序接口都使用了 `@IgnoreAuth` 注解,表示不需要登录验证。在实际使用中,可以根据需要添加token验证。 - -## 日志配置 - -```yaml -applet: - logging: - level: INFO - logWxApi: true # 记录微信API调用日志 - logUserAction: true # 记录用户操作日志 -``` - -## 缓存配置 - -```yaml -applet: - cache: - accessTokenExpire: 7000 # 微信access_token缓存时间(秒) - userInfoExpire: 3600 # 用户信息缓存时间(秒) - qrcodeExpire: 86400 # 小程序码缓存时间(秒) -``` - -## 开发说明 - -### 1. 数据库集成 - -当前版本使用模拟数据,实际使用时需要: - -1. 创建用户表 `applet_user` -2. 创建健康信息表 `applet_health_info` -3. 创建会员信息表 `applet_member_info` -4. 在Service层实现数据库操作 - -### 2. 微信API集成 - -已集成以下微信API: - -- 登录:`/sns/jscode2session` -- 获取手机号:`/wxa/business/getuserphonenumber` -- 获取access_token:`/cgi-bin/token` -- 获取小程序码:`/wxa/getwxacodeunlimit` -- 发送订阅消息:`/cgi-bin/message/subscribe/send` - -### 3. 错误处理 - -所有接口都包含完整的异常处理: - -- 微信API调用失败 -- 参数验证失败 -- 数据库操作失败 -- 网络连接失败 - -### 4. 扩展开发 - -如需添加新功能,可以: - -1. 在 `service` 包下创建新的服务类 -2. 在 `controller` 包下创建对应的控制器 -3. 在配置文件中添加相关配置 -4. 更新本文档 - -## 部署说明 - -### 1. 打包 - -```bash -mvn clean package -Dmaven.test.skip=true -``` - -### 2. 运行 - -```bash -java -jar jeecgboot-boot-applet.jar --spring.profiles.active=prod -``` - -### 3. Docker部署 - -```dockerfile -FROM openjdk:8-jre-alpine -COPY jeecgboot-boot-applet.jar app.jar -EXPOSE 8080 -ENTRYPOINT ["java", "-jar", "/app.jar"] -``` - -## 注意事项 - -1. **安全性**:生产环境中请务必配置正确的微信小程序密钥 -2. **性能**:建议对微信API调用结果进行缓存 -3. **监控**:建议添加接口调用监控和日志收集 -4. **测试**:请在小程序开发工具中充分测试所有功能 -5. **文档**:接口文档可通过Swagger UI查看:`http://your-domain/swagger-ui.html` - -## 技术支持 - -如有问题,请联系开发团队或查看项目文档。 \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/controller/AppletApiAddressController.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/controller/AppletApiAddressController.java index 10d6bc3..f366b84 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/controller/AppletApiAddressController.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/controller/AppletApiAddressController.java @@ -101,66 +101,20 @@ public class AppletApiAddressController { return Result.OK("编辑成功!"); } + /** + * 设置默认地址 + * + * @param addressId 地址ID + * @return + */ + @Operation(summary="小程序收货地址-设置默认地址") + @PutMapping(value = "/setDefault") + @IgnoreAuth + public Result setDefaultAddress(@RequestParam String addressId) { + appletAddressService.setDefaultAddress(addressId); + return Result.OK("设置默认地址成功!"); + } - -// /** -// * 通过id删除 -// * -// * @param id -// * @return -// */ -// @Operation(summary="小程序收货地址-通过id删除") -// @DeleteMapping(value = "/delete") -// public Result delete(@RequestParam(name="id",required=true) String id) { -// appletAddressService.removeById(id); -// return Result.OK("删除成功!"); -// } - - - - -// /** -// * 批量删除 -// * -// * @param ids -// * @return -// */ -// @AutoLog(value = "小程序收货地址-批量删除") -// @Operation(summary="小程序收货地址-批量删除") -// @RequiresPermissions("appletShippingAddress:applet_shipping_address:deleteBatch") -// @DeleteMapping(value = "/deleteBatch") -// public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { -// this.appletAddressService.removeByIds(Arrays.asList(ids.split(","))); -// return Result.OK("批量删除成功!"); -// } - - - -// /** -// * 导出excel -// * -// * @param request -// * @param appletShippingAddress -// */ -// @RequiresPermissions("appletShippingAddress:applet_shipping_address:exportXls") -// @RequestMapping(value = "/exportXls") -// public ModelAndView exportXls(HttpServletRequest request, AppletShippingAddress appletShippingAddress) { -// return super.exportXls(request, appletShippingAddress, AppletShippingAddress.class, "小程序收货地址"); -// } -// -// /** -// * 通过excel导入数据 -// * -// * @param request -// * @param response -// * @return -// */ -// @RequiresPermissions("appletShippingAddress:applet_shipping_address:importExcel") -// @RequestMapping(value = "/importExcel", method = RequestMethod.POST) -// public Result importExcel(HttpServletRequest request, HttpServletResponse response) { -// return super.importExcel(request, response, AppletShippingAddress.class); -// } - } diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/controller/AppletApiCarController.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/controller/AppletApiCarController.java index d4ef222..c11541d 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/controller/AppletApiCarController.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/controller/AppletApiCarController.java @@ -72,22 +72,7 @@ public class AppletApiCarController { return Result.OK("添加成功!"); } - /** - * 通过id查询 - * - * @param id - * @return - */ - //@AutoLog(value = "购物车-通过id查询") - @Operation(summary = "购物车-通过id查询") - @GetMapping(value = "/queryById") - public Result queryById(@RequestParam(name = "id", required = true) String id) { - AppletCar appletCar = appletApiCarService.getById(id); - if (appletCar == null) { - return Result.error("未找到对应数据"); - } - return Result.OK(appletCar); - } + /** * 编辑 @@ -101,6 +86,8 @@ public class AppletApiCarController { appletApiCarService.updateById(appletCar); return Result.OK("编辑购物车!"); } + + /** * 批量删除 * @@ -109,8 +96,8 @@ public class AppletApiCarController { */ @Operation(summary="购物车-批量删除") @DeleteMapping(value = "/deleteBatch") - public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { - this.appletApiCarService.removeById(Arrays.asList(ids.split(",")).toString()); + public Result deleteBatch(@RequestParam(name="ids") String ids) { + appletApiCarService.removeByIds(Arrays.asList(ids.split(","))); return Result.OK("批量删除成功!"); } diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/AppletApiAddressService.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/AppletApiAddressService.java index d329afa..e4f1134 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/AppletApiAddressService.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/AppletApiAddressService.java @@ -39,6 +39,13 @@ public interface AppletApiAddressService { */ void updateById(AppletShippingAddress appletShippingAddress); + /** + * 设置默认地址 + * + * @param addressId 地址ID + */ + void setDefaultAddress(String addressId); + // /** // * 通过id删除 diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/AppletApiCarService.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/AppletApiCarService.java index c8d6e2b..0163b0f 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/AppletApiCarService.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/AppletApiCarService.java @@ -1,6 +1,5 @@ package org.jeecg.modules.applet.service; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.jeecg.modules.demo.appletCar.entity.AppletCar; @@ -13,7 +12,7 @@ public interface AppletApiCarService { * 查询购物车列表 * * @param page - * @param queryWrapper + * @param appletCar * @return */ IPage page(Page page, AppletCar appletCar); @@ -25,13 +24,6 @@ public interface AppletApiCarService { */ void save(AppletCar appletCar); - /** - * 根据id查询购物车 - * - * @param id - * @return - */ - AppletCar getById(String id); /** * 修改购物车 diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiAddressServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiAddressServiceImpl.java index 8ad9b2e..e4cd962 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiAddressServiceImpl.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiAddressServiceImpl.java @@ -15,6 +15,7 @@ import org.springframework.stereotype.Service; @Service @Slf4j public class AppletApiAddressServiceImpl implements AppletApiAddressService { + @Autowired private IAppletShippingAddressService appletShippingAddressService; @@ -32,12 +33,11 @@ public class AppletApiAddressServiceImpl implements AppletApiAddressService { Page page1 = appletShippingAddressService .lambdaQuery() - .eq(AppletShippingAddress::getUserId, userId)//getId -> getUserId + .eq(AppletShippingAddress::getUserId, userId) .orderByDesc(AppletShippingAddress::getDefaultFlag) - //如果你要写查询条件,这样写 - //.eq(AppletShippingAddress::getCity, address.getCity())//这个是 等于 - //.eq(StrUtil.isNotBlank((address.getCity()), AppletShippingAddress::getCity, address.getCity())//这样加条件不为空 .page(page); + + return page1; } @@ -105,4 +105,31 @@ public class AppletApiAddressServiceImpl implements AppletApiAddressService { appletShippingAddressService.updateById(appletShippingAddress); } + /** + * 设置默认地址 + * + * @param addressId 地址ID + */ + @Override + public void setDefaultAddress(String addressId) { + if (StrUtil.isBlank(addressId)) { + throw new IllegalArgumentException("地址ID不能为空"); + } + + String userId = AppletUserUtil.getCurrentAppletUserId(); + + // 先取消该用户所有地址的默认状态 + appletShippingAddressService.lambdaUpdate() + .eq(AppletShippingAddress::getUserId, userId) + .set(AppletShippingAddress::getDefaultFlag, 0) + .update(); + + // 设置指定地址为默认地址 + appletShippingAddressService.lambdaUpdate() + .eq(AppletShippingAddress::getId, addressId) + .eq(AppletShippingAddress::getUserId, userId) + .set(AppletShippingAddress::getDefaultFlag, 1) + .update(); + } + } diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiCarServiceImpl.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiCarServiceImpl.java index a86be74..55415fc 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiCarServiceImpl.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/applet/service/impl/AppletApiCarServiceImpl.java @@ -3,10 +3,12 @@ package org.jeecg.modules.applet.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.jeecg.common.exception.JeecgBootException; import org.jeecg.common.system.util.AppletUserUtil; import org.jeecg.modules.applet.service.AppletApiCarService; import org.jeecg.modules.demo.appletCar.entity.AppletCar; import org.jeecg.modules.demo.appletCar.service.IAppletCarService; +import org.jeecg.modules.demo.appletProduct.service.IAppletProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -15,9 +17,13 @@ import java.util.stream.Collectors; @Service public class AppletApiCarServiceImpl implements AppletApiCarService { + @Autowired private IAppletCarService appletCarService; + @Autowired + private IAppletProductService appletProductService; + /** * 购物车列表查询 * @@ -32,6 +38,11 @@ public class AppletApiCarServiceImpl implements AppletApiCarService { .lambdaQuery() .eq(AppletCar::getUserId, userId) .page(page); + + for (AppletCar record : page1.getRecords()) { + record.setProduct(appletProductService.getById(record.getProductId())); + } + return page1; } @@ -43,28 +54,22 @@ public class AppletApiCarServiceImpl implements AppletApiCarService { @Override public void save(AppletCar appletCar) { - appletCarService.save(appletCar); - } - - /** - * 根据id查询购物车 - * - * @param id 购物车id - * @return 购物车对象 - */ - @Override - public AppletCar getById(String id) { // 获取当前登录的小程序用户ID String userId = AppletUserUtil.getCurrentAppletUserId(); - // 使用LambdaQuery构造查询条件,同时匹配购物车ID和用户ID,确保数据隔离 - AppletCar appletCar = appletCarService - .lambdaQuery() - .eq(AppletCar::getId, id) // 匹配购物车ID - .eq(AppletCar::getUserId, userId) // 匹配用户ID - .one(); // 查询单个结果 - return appletCar; + // 验证该购物车是否属于当前用户 +// AppletCar existingCar = appletCarService +// .lambdaQuery() +// .eq(AppletCar::getProductId, appletCar.getProductId()) // 匹配购物车ID +// .eq(AppletCar::getSkuId, appletCar.getSkuId()) // 匹配购物车ID +// .eq(AppletCar::getUserId, userId) // 匹配用户ID +// .one(); + + appletCar.setUserId(userId); + + appletCarService.save(appletCar); } + /** * 修改购物车 * @@ -93,21 +98,9 @@ public class AppletApiCarServiceImpl implements AppletApiCarService { */ @Override public void removeByIds(List ids) { - // 获取当前登录的小程序用户ID - String userId = AppletUserUtil.getCurrentAppletUserId(); - // 查询这些ID中属于当前用户的购物车项 - List appletCars = appletCarService - .lambdaQuery() - .in(AppletCar::getId, ids) // 匹配购物车ID列表 - .eq(AppletCar::getUserId, userId) // 匹配用户ID - .list(); - // 提取属于当前用户的购物车ID列表 - List userCarIds = appletCars.stream() - .map(AppletCar::getId) - .collect(Collectors.toList()); // 执行删除操作(只会删除属于当前用户的购物车项) - if (!userCarIds.isEmpty()) { - appletCarService.removeByIds(userCarIds); + if (!ids.isEmpty()) { + appletCarService.removeByIds(ids); } } } \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletCar/entity/AppletCar.java b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletCar/entity/AppletCar.java index 45096d0..610435b 100644 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletCar/entity/AppletCar.java +++ b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/src/main/java/org/jeecg/modules/demo/appletCar/entity/AppletCar.java @@ -4,14 +4,13 @@ import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.util.Date; import java.math.BigDecimal; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.annotation.TableLogic; + +import com.baomidou.mybatisplus.annotation.*; import org.jeecg.common.constant.ProvinceCityArea; import org.jeecg.common.util.SpringContextUtils; import lombok.Data; import com.fasterxml.jackson.annotation.JsonFormat; +import org.jeecg.modules.demo.appletProduct.entity.AppletProduct; import org.springframework.format.annotation.DateTimeFormat; import org.jeecgframework.poi.excel.annotation.Excel; import org.jeecg.common.aspect.annotation.Dict; @@ -68,4 +67,7 @@ public class AppletCar implements Serializable { @Excel(name = "商品规格", width = 15) @Schema(description = "商品规格") private java.lang.String skuId; + + @TableField(exist = false) + private AppletProduct product; } diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/小程序登录修复说明.md b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/小程序登录修复说明.md deleted file mode 100644 index 0160bb5..0000000 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/小程序登录修复说明.md +++ /dev/null @@ -1,202 +0,0 @@ -# 小程序登录修复说明 - -## 修复的问题 - -### 1. 用户信息获取问题 -**原问题**: `AppletShiroRealm` 中的 `getAppletUser` 方法返回null,导致无法正确获取用户信息。 - -**修复方案**: -- 完善了 `getAppletUser` 方法,支持从数据库和Redis缓存获取用户信息 -- 添加了用户信息缓存机制,提高性能 -- 增加了异常处理和日志记录 - -### 2. Token验证逻辑不完整 -**原问题**: Token验证缺少黑名单检查和刷新机制。 - -**修复方案**: -- 添加了token黑名单检查 -- 完善了token刷新逻辑 -- 统一了token管理机制 - -### 3. Shiro认证体系集成问题 -**原问题**: 小程序登录没有正确集成到Shiro认证体系。 - -**修复方案**: -- 创建了专用的 `AppletShiroConfig` 配置类 -- 完善了 `AppletShiroRealm` 的认证和授权逻辑 -- 添加了小程序用户默认权限配置 - -### 4. 控制器参数验证不足 -**原问题**: 控制器缺少参数验证和错误处理。 - -**修复方案**: -- 添加了完整的参数验证 -- 增加了Swagger API文档注解 -- 完善了错误处理和日志记录 - -## 新增功能 - -### 1. 用户工具类 -创建了 `AppletUserUtil` 工具类,提供以下功能: -- `getCurrentAppletUser()`: 获取当前登录的小程序用户 -- `getCurrentAppletUserId()`: 获取当前用户ID -- `getCurrentAppletUserOpenid()`: 获取当前用户openid -- `isAppletUserLoggedIn()`: 检查用户是否已登录 -- `hasPermission()`: 检查用户权限 -- `hasRole()`: 检查用户角色 - -### 2. 缓存机制 -- 用户信息缓存(30分钟) -- Token缓存(JWT过期时间的2倍) -- Session_key缓存(7天) -- 手机号临时缓存(5分钟) -- Token黑名单缓存(24小时) - -### 3. 权限控制 -- 小程序用户默认角色:`applet_user` -- 小程序用户默认权限:`applet:user:*` -- 支持细粒度权限控制 - -## 使用示例 - -### 1. 在控制器中获取当前用户 -```java -@GetMapping("/getCurrentUser") -public Result getCurrentUser() { - AppletUser currentUser = AppletUserUtil.getCurrentAppletUser(); - if (currentUser == null) { - return Result.error("用户未登录"); - } - return Result.OK("获取成功", currentUser); -} -``` - -### 2. 权限检查 -```java -@PostMapping("/sensitiveOperation") -public Result sensitiveOperation() { - if (!AppletUserUtil.hasPermission("applet:user:edit")) { - return Result.error("权限不足"); - } - // 执行敏感操作 - return Result.OK("操作成功"); -} -``` - -### 3. 角色检查 -```java -@GetMapping("/adminOnly") -public Result adminOnly() { - if (!AppletUserUtil.hasRole("applet_admin")) { - return Result.error("需要管理员权限"); - } - return Result.OK("管理员操作成功"); -} -``` - -## 配置要求 - -### 1. 数据库配置 -确保 `applet_user` 表已创建,包含以下字段: -- `id`: 主键 -- `openid`: 微信openid(唯一索引) -- `phone`: 手机号(唯一索引) -- `name`: 用户昵称 -- `avatar`: 头像 -- `bmi`: 体总指数 -- `fat`: 脂肪 -- `create_time`: 创建时间 -- `update_time`: 更新时间 - -### 2. Redis配置 -确保Redis服务正常运行,用于缓存: -- 用户信息 -- Token缓存 -- Session_key -- 黑名单 - -### 3. 微信配置 -在 `application.yml` 中配置: -```yaml -wechat: - mpAppId: your_applet_appid - mpAppSecret: your_applet_secret -``` - -### 4. JWT配置 -确保JWT工具类能正确读取配置: -```yaml -jeecg: - jwt: - secret: your_jwt_secret_key - expire: 604800 -``` - -## 安全改进 - -### 1. Token安全 -- 生产环境不返回session_key -- Token自动刷新机制 -- Token黑名单管理 -- 支持token主动失效 - -### 2. 参数验证 -- 所有接口都添加了参数验证 -- 防止空参数和恶意参数 -- 统一的错误处理 - -### 3. 权限控制 -- 基于Shiro的权限控制 -- 支持角色和权限检查 -- 细粒度权限管理 - -## 性能优化 - -### 1. 缓存策略 -- 用户信息缓存减少数据库查询 -- Token缓存提高验证速度 -- 合理的缓存过期时间 - -### 2. 异常处理 -- 完善的异常捕获和处理 -- 详细的日志记录 -- 友好的错误提示 - -### 3. 并发处理 -- 线程安全的用户信息获取 -- 原子性的token操作 -- 避免并发冲突 - -## 测试建议 - -### 1. 功能测试 -- 测试完整的登录流程 -- 测试token刷新机制 -- 测试权限控制功能 -- 测试异常情况处理 - -### 2. 性能测试 -- 测试高并发登录 -- 测试缓存命中率 -- 测试数据库连接池 - -### 3. 安全测试 -- 测试token伪造防护 -- 测试权限绕过防护 -- 测试参数注入防护 - -## 注意事项 - -1. **生产环境配置**: 确保生产环境使用HTTPS,不要暴露敏感信息 -2. **日志管理**: 合理配置日志级别,避免敏感信息泄露 -3. **监控告警**: 添加关键操作的监控和告警 -4. **备份策略**: 定期备份用户数据和配置信息 -5. **版本兼容**: 注意API版本兼容性,避免影响现有客户端 - -## 后续优化建议 - -1. **多租户支持**: 如果需要支持多租户,可以扩展用户表结构 -2. **第三方登录**: 可以扩展支持其他第三方登录方式 -3. **消息推送**: 集成消息推送功能,支持实时通知 -4. **数据分析**: 添加用户行为分析功能 -5. **自动化测试**: 编写完整的自动化测试用例 \ No newline at end of file diff --git a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/小程序配置说明.md b/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/小程序配置说明.md deleted file mode 100644 index 02e3697..0000000 --- a/jeecg-boot/jeecg-boot-module/jeecgboot-boot-applet/小程序配置说明.md +++ /dev/null @@ -1,278 +0,0 @@ -# 小程序模块配置说明 - -## 概述 -本文档说明小程序登录服务需要配置的内容,包括数据库、Redis、微信配置等。 - -## 1. 数据库配置 - -### 1.1 数据库表结构 -需要确保 `applet_user` 表已创建,表结构如下: - -```sql -CREATE TABLE `applet_user` ( - `id` varchar(32) NOT NULL COMMENT '主键', - `create_by` varchar(50) DEFAULT NULL COMMENT '创建人', - `create_time` datetime DEFAULT NULL COMMENT '创建日期', - `update_by` varchar(50) DEFAULT NULL COMMENT '更新人', - `update_time` datetime DEFAULT NULL COMMENT '更新日期', - `sys_org_code` varchar(64) DEFAULT NULL COMMENT '所属部门', - `name` varchar(100) DEFAULT NULL COMMENT '昵称', - `openid` varchar(100) DEFAULT NULL COMMENT '第三方认证id', - `phone` varchar(20) DEFAULT NULL COMMENT '手机号', - `bmi` decimal(10,2) DEFAULT NULL COMMENT '体总指数', - `fat` decimal(10,2) DEFAULT NULL COMMENT '脂肪', - `avatar` varchar(500) DEFAULT NULL COMMENT '头像', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_openid` (`openid`), - UNIQUE KEY `uk_phone` (`phone`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='小程序用户表'; -``` - -### 1.2 数据库连接配置 -在 `application.yml` 中配置数据库连接: - -```yaml -spring: - datasource: - url: jdbc:mysql://localhost:3306/jeecg-boot?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 - username: root - password: root - driver-class-name: com.mysql.cj.jdbc.Driver -``` - -## 2. Redis配置 - -### 2.1 Redis连接配置 -在 `application.yml` 中配置Redis: - -```yaml -spring: - redis: - host: localhost - port: 6379 - password: - database: 0 - timeout: 10000ms - lettuce: - pool: - max-active: 8 - max-wait: -1ms - max-idle: 8 - min-idle: 0 -``` - -### 2.2 Redis配置类 -需要创建Redis配置类: - -```java -@Configuration -public class RedisConfig { - - @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory factory) { - RedisTemplate template = new RedisTemplate<>(); - template.setConnectionFactory(factory); - - // 设置key的序列化方式 - template.setKeySerializer(new StringRedisSerializer()); - // 设置value的序列化方式 - template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); - // 设置hash key的序列化方式 - template.setHashKeySerializer(new StringRedisSerializer()); - // 设置hash value的序列化方式 - template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); - - template.afterPropertiesSet(); - return template; - } -} -``` - -## 3. 微信小程序配置 - -### 3.1 微信配置 -在 `application.yml` 中配置微信小程序信息: - -```yaml -wechat: - mpAppId: your_applet_appid - mpAppSecret: your_applet_secret - merchantId: your_merchant_id # 如果需要支付功能 -``` - -### 3.2 微信配置类 -确保 `WxHttpUtils` 类能正确读取配置: - -```java -@Component -public class WxHttpUtils { - @Value("${wechat.mpAppId}") - private String appid; - - @Value("${wechat.mpAppSecret}") - private String secret; -} -``` - -## 4. JWT配置 - -### 4.1 JWT密钥配置 -在 `application.yml` 中配置JWT密钥: - -```yaml -jeecg: - jwt: - secret: your_jwt_secret_key - expire: 604800 # 7天,单位秒 -``` - -### 4.2 JWT工具类配置 -确保 `JwtUtil` 类能正确读取配置: - -```java -@Component -public class JwtUtil { - @Value("${jeecg.jwt.secret}") - private String secret; - - @Value("${jeecg.jwt.expire}") - private long expire; -} -``` - -## 5. 日志配置 - -### 5.1 日志级别配置 -在 `application.yml` 中配置日志级别: - -```yaml -logging: - level: - org.jeecg.modules.applet: DEBUG - org.jeecg.modules.common.wxUtils: DEBUG -``` - -## 6. 安全配置 - -### 6.1 CORS配置 -如果需要跨域访问,需要配置CORS: - -```java -@Configuration -public class CorsConfig { - - @Bean - public CorsFilter corsFilter() { - CorsConfiguration config = new CorsConfiguration(); - config.addAllowedOrigin("*"); - config.addAllowedHeader("*"); - config.addAllowedMethod("*"); - - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", config); - - return new CorsFilter(source); - } -} -``` - -## 7. 依赖配置 - -### 7.1 Maven依赖 -确保 `pom.xml` 中包含以下依赖: - -```xml - - - org.springframework.boot - spring-boot-starter-data-redis - - - - - org.apache.httpcomponents - httpclient - - - - - com.alibaba - fastjson - - - - - com.baomidou - mybatis-plus-boot-starter - -``` - -## 8. 环境变量配置 - -### 8.1 生产环境配置 -在生产环境中,建议使用环境变量或配置中心来管理敏感信息: - -```yaml -wechat: - mpAppId: ${WECHAT_MP_APPID:default_appid} - mpAppSecret: ${WECHAT_MP_SECRET:default_secret} - -spring: - redis: - host: ${REDIS_HOST:localhost} - port: ${REDIS_PORT:6379} - password: ${REDIS_PASSWORD:} -``` - -## 9. 监控配置 - -### 9.1 健康检查 -可以添加健康检查端点: - -```yaml -management: - endpoints: - web: - exposure: - include: health,info,metrics - endpoint: - health: - show-details: always -``` - -## 10. 注意事项 - -1. **安全性**:生产环境中不要将敏感信息硬编码在代码中 -2. **性能**:Redis连接池配置要根据实际负载调整 -3. **监控**:建议添加应用监控和日志收集 -4. **备份**:定期备份数据库和Redis数据 -5. **测试**:在部署前进行充分的测试 - -## 11. 常见问题 - -### 11.1 Redis连接失败 -- 检查Redis服务是否启动 -- 检查网络连接和防火墙设置 -- 检查Redis配置是否正确 - -### 11.2 微信API调用失败 -- 检查微信小程序配置是否正确 -- 检查网络连接是否正常 -- 检查微信API调用频率限制 - -### 11.3 数据库连接失败 -- 检查数据库服务是否启动 -- 检查数据库连接配置 -- 检查数据库用户权限 - -## 12. 部署检查清单 - -- [ ] 数据库表已创建 -- [ ] Redis服务已启动 -- [ ] 微信小程序配置正确 -- [ ] JWT密钥已配置 -- [ ] 日志配置正确 -- [ ] 网络连接正常 -- [ ] 安全配置已设置 -- [ ] 监控已配置 -- [ ] 备份策略已制定 \ No newline at end of file