Files
StoreWeb/Modules/Store.Users/README.md
T

7.8 KiB
Raw Blame History

用户模块迁移与运行

本模块参考 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;商铺续费继续走专用接口。

运行与部署

  1. 检查现有 MySQL DefaultConnection 配置和已有表。确认 wxxd.user 中存在可登录的 sa_level=1 管理员。
  2. 审阅并执行 Database/prepare-user-module.sql。应用不自动建表或改表;资金表必须是 InnoDB,用户名必须有唯一索引。
  3. 构建:dotnet build Store.API/Store.Api.csproj。
  4. 验证:dotnet run --project Tests/UserManagementSmoke/UserManagementSmoke.csproj,以及原有 dotnet run --project Tests/ShopRenewSmoke/ShopRenewSmoke.csproj。
  5. 启动: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 仅非空”的约定不改变公共校验器能力。该工具不递归验证嵌套对象。