7.8 KiB
用户模块迁移与运行
本模块参考 D:/Works/KJD_WebService/KJD_WebService/BLL/WXXD/WXUserManage.cs 重写,保留旧表映射,采用 ASP.NET Core 控制器、DTO、服务、FreeSql 仓储和现有 JWT 身份体系。所有新代码均含中文用途或关键规则注释。
文件与职责
- 文件:
Controllers/UserController.cs:/user/[action]接口,统一要求 Bearer Token。 - 文件:
Services/UserManagementService.cs:主子账号管理、权限检查、分页、密码修改和流水查询。 - 文件:
Services/UserManagementService.TopUp.cs:充值备注与代理二维码。 - 文件:
Services/UserFundsService.cs:积分充值、积分转移、余额充值/消费;事务、行锁、请求去重与流水写入。 - 文件:
Services/UserQueryService.cs、Repositories/UserRepository.cs:认证和查询、主子账号有效配置继承。 - 文件:
Services/UserPassword.cs:带盐哈希密码与旧明文密码兼容。 - 文件:
../Store.Users.Contracts/Dtos/UserManagementRequests.cs、UserFundsRequest.cs、UserTopUpRequests.cs:输入验证与响应契约。 - 文件:
Database/prepare-user-module.sql:上线前密码列、唯一用户名、事务引擎及请求号列检查。 - 文件:
../../Store.API/Controllers/AuthController.cs:登录签发 JWT 前调用真实密码验证,不再接受任意密码。 - 文件:
../../Tests/UserManagementSmoke/Program.cs:临时 SQLite 集成验证,避免访问业务数据库。
接口
HTTP 方法约定:控制器通过 [DefaultHttpPost] 启用默认 POST。所有操作只接受 POST,无需逐个标记 [HttpPost]。该约定同时生成路由约束和端点元数据,接口文档也显示 POST。
| 方法 | 路径 | 访问与行为 |
|---|---|---|
| POST | /user/GetUser?userName=... | 本人、直属主账号或管理员;省略用户名读取本人 |
| POST | /user/GetAllUser | 管理员分页查询,支持 Keyword、GroupId |
| POST | /user/GetSubUser | 当前主账号直属子账号分页查询 |
| POST | /user/AddUser | 管理员新增主账号 |
| POST | /user/AddSubUser | 当前主账号新增直属子账号 |
| POST | /user/UpdateUser | 管理员修改资料 |
| POST | /user/UpdateSubUser | 主账号修改直属子账号 |
| POST | /user/DelUser?id=... | 管理员或直属主账号删除空账户 |
| POST | /user/ChangePassword | 本人校验旧密码后修改,会话立即失效 |
| POST | /user/GetUserPoints | 授权账户积分流水,支持起止时间、操作类型、店铺过滤 |
| POST | /user/GetUserBalance | 授权账户余额流水,支持起止时间、支付类型、订单过滤 |
| POST | /user/UpdateUserPoints | 管理员充值;本人向其他账户转移自己的积分 |
| POST | /user/UpdateUserBalance | 管理员充值或消费调整 |
| POST | /user/AddUserTopUpMsg | 本人提交充值备注 |
| POST | /user/UpdateUserTopUpMsg | 管理员填写处理结果,不自动充值 |
| POST | /user/GetUserTopUpMsg | 本人备注或管理员查看全部 |
| POST | /user/UpdateTopUpQrcode | 管理员维护代理二维码 |
| POST | /user/GetTopUpQrcode?agentCode=... | 登录用户读取代理二维码 |
| POST | /user/ShopRenew | 保留原有 MediatR 事务续费用例 |
分页查询与流水查询通过 JSON 请求体提交;流水查询的 userName 与筛选字段放在同一对象中。UpdateUser、UpdateSubUser 使用 JSON 请求体,例如 {"id":123,"nickName":"新昵称"}。仅有单个业务参数的 GetUser、DelUser、GetTopUpQrcode 仍使用查询参数。
分页 Page 从 1 开始,PageSize 默认 50,最大 200。流水时间参数为 StartTime、EndTime(包含边界)。资料更新 null 表示保留原值,空字符串清空文本字段。账户名不可修改,以免破坏历史关联。SaLevel 仅管理员可设置为 0/1,子账号不能成为管理员。普通主账号不能授予自己没有的权限,也不能修改计费配置。子账号积分用户权限、OEM 和每单费用继承主账号,保留 2.2/2.5 元费用下限。
资金请求示例:
{"userName":"target","requestId":"客户端生成的唯一请求号","amount":100,"operation":"充值","remark":"人工充值已核实"}
积分 Operation 支持“充值”“转移”;余额支持“充值”“消费”。Amount 始终为正数,最多两位小数。转移仅从当前登录账户转出,不支持负金额拉取对方积分。相同目标账户和资金类型下,重复 RequestId 返回已处理错误,不再次记账;调用失败重试必须保留请求号。不同请求号视作不同业务,调用方需确保业务唯一性。积分转入累计充值口径沿用旧系统。余额流水类型沿用旧系统充值 1、人工消费 0;商铺续费继续走专用接口。
运行与部署
- 检查现有 MySQL
DefaultConnection配置和已有表。确认wxxd.user中存在可登录的sa_level=1管理员。 - 审阅并执行
Database/prepare-user-module.sql。应用不自动建表或改表;资金表必须是 InnoDB,用户名必须有唯一索引。 - 构建:
dotnet build Store.API/Store.Api.csproj。 - 验证:
dotnet run --project Tests/UserManagementSmoke/UserManagementSmoke.csproj,以及原有dotnet run --project Tests/ShopRenewSmoke/ShopRenewSmoke.csproj。 - 启动:
dotnet run --project Store.API/Store.Api.csproj。先调用宿主/api/v1.0/Auth/Login,再携带 Bearer Token 调用用户接口。
认证兼容 WXUserManage 的旧明文密码和 Identity 带盐哈希,登录时仅验证,不修改密码;新建和修改密码直接保存哈希。旧项目按 SQL 明文比较密码的登录接口无法识别哈希密码,共用数据库时需同步切换相关调用方。新接口采用结构化 JSON,不兼容旧 inputData 拼接字符串及 time/code 签名。UserInfo 保留 Password 属性用于源码兼容,但不映射值、不向 JSON 序列化。
迁移边界与验证限制
旧文件中的 E57 第三方令牌、微信销售助手 Cookie、淘宝买手管理属于外部系统或独立业务,未加入用户账户模块。本次未修改旧项目或调用第三方服务。
集成验证使用临时 SQLite 库,覆盖认证、登录不修改密码、主子账号、越权、计费、资金写入、重复请求、超扣、强制流水失败的事务回滚、删除边界、备注和二维码更新。MySQL 的真实并发、行锁、历史表结构和旧客户端迁移仍需在测试库联调。可使用“代码审查”继续检查实现质量。
输入校验约定
User 模块的请求 DTO 只保留 [Required],校验必填、null、空字符串和纯空白字符串。服务使用 MAX.Framework.Validation.RequestValidator.Validate(request) 统一执行这类非空校验,防止内部调用绕过 HTTP 模型验证。
using MAX.Framework.Validation;
RequestValidator.Validate(request);
// 非空之外的规则由服务继续手动判断。
长度、数值范围、金额精度、操作类型、字段组合、日期顺序和二维码 Base64 格式在服务层手动检查。可复用检查集中于 Services/UserInputChecks.cs,资金金额与操作类型直接由 UserFundsService 判断;续费的非空输入由 ShopRenewRequest 声明,其余规则通过命令验证管道调用服务层检查后执行事务。
权限、账户归属、数据库记录是否存在、余额是否足够、重复请求等业务规则继续在服务或业务管道中判断。不合法的参数抛出 ValidationException,权限和业务错误沿用现有业务异常;现有过滤器将它们转换为 HTTP 200 和对应业务码。
公共 RequestValidator 位于 Core/MAX.Framework/Validation/RequestValidator.cs。它仍支持标准 DataAnnotations 及 IValidatableObject,其他模块可以直接复用;User 模块“DTO 仅非空”的约定不改变公共校验器能力。该工具不递归验证嵌套对象。