# 会员注册登录 — 技术方案(C 端) > **依据:** 平台《会员管理功能需求.md》v1.1 §2.1、《商城服务协议功能需求.md》v1.0 > **关联:** 平台《会员管理技术方案.md》v1.3(表结构/平台端)、《商城服务协议技术方案.md》v1.0、《商品详情内页功能需求.md》v1.1(GD3 登录引导)、《关联需求分析.md》v1.6 > **范围:** C 端 **注册、登录** 及注册/登录页依赖的 **`/api/member/serviceAgreement/**`**;**资料/地址** 见同模块 `MemberAppController` 另节或「我的」专册。 > **原则:** **无短信验证码**;**手机号 + 密码 + 确认密码** 注册;**手机号或会员名称 + 密码** 登录;账号复用 **`sys_user`**(`member_id = user_id`);Token 与平台 Token **隔离**。 --- ## 1. 技术架构 | 项 | 选型 | |----|------| | 基础框架 | RuoYi **v3.9.2**(`springboot2` 分支) | | 数据库 | **MySQL 5.7.39** | | ORM / 响应 | MyBatis;`AjaxResult`(`code`、`msg`、`data`) | | 密码 | BCrypt(`SecurityUtils.encryptPassword`);存 **`sys_user.password`** | | C 端鉴权 | `MemberWebConfig` + `MemberAuthInterceptor`;登录成功后框架 **`TokenService#createToken(LoginUser)`**(与 `SysLoginController` 一致,JWT + Redis) | | 服务协议 | `IMallServiceAgreementFacade` 注册/登录勾选校验 | ### 1.1 术语(C 端登录) | 产品用语 | 技术字段 | 存储 | |----------|----------|------| | **会员名称** / **会员 ID**(登录账号) | `memberCode` | `sys_user.user_name` | | 手机号(登录账号) | `mobile` | `sys_user.phonenumber` | | 系统主键(**非** 登录账号) | `memberId` | `sys_user.user_id` = `biz_member.member_id` | > **说明:** 本文及 C 端 UI 所称 **「会员 ID」= 会员名称**(`user_name`),**不是** 数字型 `member_id`。 ### 1.2 模块落位 ```text baqing-shop/src/main/java/com/ruoyi/web/modules/account/ ├── controller/MemberAppController.java # POST /register、/login ├── service/impl/MemberAppServiceImpl.java ├── support/MemberRegistrationSupport.java # 注册事务 ├── dto/MemberRegisterDTO、MemberLoginDTO └── mapper/BizMemberMapper.xml # selectByMobile、selectByMemberCode content 模块: └── controller/MallServiceAgreementAppController.java # GET /api/member/serviceAgreement ``` ### 1.3 业务流程 ```text 【注册 · 无验证码】 用户输入 mobile + password + confirmPassword [+ memberCode 可选] → 协议勾选(若启用) → 校验两次密码一致、手机号未注册 → insertUser(role=member;user_name=memberCode)+ insert biz_member → 返回 memberId(系统主键) 【登录】 用户输入 account(手机号 或 会员名称)+ password → 协议勾选(协议启用时) → 解析 account → selectByMobile / selectByMemberCode → status=0、密码匹配 → createLoginUser + TokenService.createToken(同 SysLoginController) → 返回根级 token + memberId ``` | 关联模块 | 协作 | |----------|------| | **商城服务协议** | 注册/登录页拉协议;`agreementAccepted` | | **商品详情 / 购物车** | 未登录加购 → 跳转本模块注册/登录 | | **平台会员管理** | 平台禁用 → C 端 login 失败 | --- ## 2. 数据库设计 复用平台会员表,**不新建表**。权威 DDL:[`sql/biz_member.sql`](../../../sql/biz_member.sql)。 | 表 | 注册/登录相关字段 | |----|-------------------| | `sys_user` | `user_name`(**会员名称**,登录账号)、`phonenumber`(手机号)、`password`、`status` | | `biz_member` | `member_id`(系统主键,**非** C 端登录账号)、`register_time` | | `sys_user_role` | 注册时绑定 **`role_key=member`** | | 规则 | 说明 | |------|------| | M2 | 手机号 `del_flag=0` **唯一** | | 会员名称 | `user_name` **唯一**(`checkUserNameUnique`) | | M4 | `status=1` **禁止登录** | --- ## 3. C 端接口设计 **基路径:** `/api/member` ### 3.1 鉴权 | 路径 | 鉴权 | |------|------| | `POST /register`、`POST /login` | **`@Anonymous`**;**不** 经过 `MemberAuthInterceptor`,**不** 写入 `MemberContext` | | `GET /serviceAgreement`、`/serviceAgreement/status` | **`@Anonymous`** | | `/profile`、`/address/**` | 须 Token(**非本文**) | **`MemberContext` 约定(v1.4):** ```text POST /login → 仅返回 token + memberId;不在本请求内 MemberContext.setMemberId 后续请求 → MemberAuthInterceptor 解析 Token → MemberContext.setMemberId(userId) 请求结束 → afterCompletion → MemberContext.clear() ``` **`MemberWebConfig`(与实现对齐):** ```java registry.addInterceptor(memberAuthInterceptor) .addPathPatterns("/api/member/**", "/api/merchant/entry/**", "/api/shop/*/follow", "/api/cart/**", "/api/checkout/**", "/api/order/**") .excludePathPatterns("/api/member/register", "/api/member/login", "/api/member/sms/send", "/api/member/serviceAgreement", "/api/member/serviceAgreement/**", "/api/merchant/entry/agreement", "/api/merchant/entry/status"); ``` ### 3.2 接口一览(注册/登录) | 方法 | 路径 | 说明 | 状态 | |------|------|------|------| | POST | `/register` | 手机号 + 密码 + 确认密码注册 | **已实现** | | POST | `/login` | 手机号或 **会员名称** + 密码登录 | **已实现** | | GET | `/serviceAgreement` | 买家服务协议 | **已实现** | | GET | `/serviceAgreement/status` | 注册/登录开放状态 | **已实现** | | 项 | 说明 | |----|------| | **`POST /sms/send`** | **非本期**;注册 **不依赖** 短信验证码 | --- ### 3.3 注册 `POST /api/member/register` | Body 字段 | 必填 | 说明 | |-----------|:----:|------| | mobile | 是 | 11 位手机号 | | password | 是 | 登录密码 | | confirmPassword | 是 | 确认密码;须与 `password` **一致** | | memberCode | 否 | **会员名称**(`user_name`);未填则注册逻辑 **自动生成** 唯一名称 | | nickName | 否 | 昵称 | | agreementAccepted | 是* | 协议 **启用** 时须 `true` | **流程:** ```text validateRegister(mobile、password、confirmPassword 非空;两次密码一致) → assertAcceptedForRegister → countByMobile(已注册 → 失败) → MemberRegistrationSupport.createMember(无 verifyCode) ``` | 场景 | msg | |------|-----| | 缺手机号 | 请输入手机号 | | 缺密码 | 请输入密码 | | 缺确认密码 | 请输入确认密码 | | 两次密码不一致 | 两次输入的密码不一致 | | 手机号已注册 | 手机号已注册 | | 协议未勾选 | Facade 统一文案 | | 注册关闭 | 会员注册暂未开放 | **成功 `data`:** `memberId`(long,**系统主键**;登录请使用 **手机号** 或注册的 **会员名称**)。 **请求示例:** ```json { "mobile": "13800138000", "password": "Pass1234", "confirmPassword": "Pass1234", "memberCode": "农资买家001", "agreementAccepted": true } ``` --- ### 3.4 登录 `POST /api/member/login` | Body 字段 | 必填 | 说明 | |-----------|:----:|------| | account | 是 | **手机号** 或 **会员名称**(`user_name` / `memberCode`) | | password | 是 | 登录密码 | | agreementAccepted | 条件 | 协议 **启用** 时须 `true`;未启用 **忽略**(SP4) | > **兼容:** 若请求仍传 `mobile` 且 `account` 为空,Service **等同** `account=mobile`(旧客户端过渡)。 **account 解析规则:** ```text trim(account) → 若匹配大陆手机号格式(11 位、1 开头)→ selectByMobile → 否则 → selectByMemberCode(精确匹配 sys_user.user_name) → 未命中 → 统一提示「账号或密码错误」 ``` **流程:** ```text 校验 account、password 非空 → assertAcceptedForLogin → resolveMemberByAccount → status=0;matchesPassword → createToken → 返回根级 token + memberId(不写 MemberContext;见 §3.1) ``` **成功响应(与平台 `/login` 一致,`token` 在根级):** ```json { "code": 200, "msg": "操作成功", "token": "eyJhbGciOiJIUzUxMiJ9...", "memberId": 1001 } ``` > `memberId` 为系统主键;后续请求 Header:`Authorization: Bearer {token}`(`token.header` 配置,默认 30 分钟有效,不足 20 分钟自动续期)。 | 场景 | msg | |------|-----| | 缺账号/密码 | 请输入账号和密码 | | 账号不存在或密码错 | 账号或密码错误 | | 禁用 | 账号已禁用,请联系客服 | **请求示例(手机号):** ```json { "account": "13800138000", "password": "Pass1234", "agreementAccepted": true } ``` **请求示例(会员名称 / 产品所称会员 ID):** ```json { "account": "农资买家001", "password": "Pass1234" } ``` --- ### 3.5 服务协议(注册/登录页) > 详述见《商城服务协议技术方案.md》§4。 | 方法 | 路径 | 用途 | |------|------|------| | GET | `/api/member/serviceAgreement` | 协议正文 + `registrationOpen` / `requireAgreementOnLogin` | | GET | `/api/member/serviceAgreement/status` | 仅拉开关 | --- ## 4. Service 要点 ```text MemberAppServiceImpl.register → 校验 password === confirmPassword → 不调用 IMemberSmsService.verifyCode MemberAppServiceImpl.login → resolveMemberByAccount(account) → SysUser + UserDetailsServiceImpl.createLoginUser → TokenService.createToken(loginUser) ``` --- ## 5. 业务规则 | 编号 | 规则 | |------|------| | **RL1** | 注册 **仅需手机号 + 密码 + 确认密码**;**无** 短信验证码 | | **RL2** | 确认密码与密码 **必须一致** | | **RL3** | 登录账号 = **手机号** 或 **会员名称**(`user_name`);产品 **「会员 ID」即会员名称** | | **RL4** | 登录失败 **统一** 提示「账号或密码错误」 | | **RL5** | 禁用会员 **不可** 登录 | | **RL6** | 协议启用时注册/登录须 **勾选** `agreementAccepted` | | **RL7** | 与商户经营账号 **分表**,互不影响(M7) | | **RL8** | 响应中的 `memberId` 为 **系统主键**;**不可** 当作登录账号 | --- ## 6. 前端调用建议 | 场景 | 调用 | |------|------| | 注册/登录页初始化 | `GET /api/member/serviceAgreement` | | 注册提交 | `POST /register`(mobile、password、confirmPassword、agreementAccepted) | | 登录提交 | `POST /login`(account、password) | | 登录成功 | 存根级 `token`;Header `Authorization: Bearer {token}` | | 跳转资料/地址 | 登录后调 `/profile`、`/address/*` | **注册页表单:** ```text 手机号 → 密码 → 确认密码 → [会员名称 可选] → [协议勾选] → 注册 (无「获取验证码」步骤) ``` **登录页表单:** ```text 账号(手机号或会员名称/会员ID)→ 密码 → [协议勾选] → 登录 ``` --- ## 7. 实现状态 | 项 | 状态 | |----|------| | `POST /register`(无验证码 + confirmPassword) | **已实现** | | `POST /login`(account:手机号/会员名称) | **已实现** | | `BizMemberMapper.selectByMemberCode` | **已实现** | | `POST /sms/send` | **保留代码、非本期** | | C 端注册/登录 **前端** | **已实现**(见《会员注册登录前端技术方案.md》v1.1,含根级 token 解析) | --- ## 8. 非本期 | 项 | 说明 | |------|------| | 短信验证码注册/登录 | **明确不做** | | 以数字 `member_id` 作为登录账号 | **不做** | | 微信/支付宝 OAuth | — | | 忘记密码 / 换绑手机 | — | --- ## 9. 与平台文档关系 | 文档 | 关系 | |------|------| | [平台《会员管理技术方案》](../../平台后台/会员管理/会员管理技术方案.md) | 表结构、平台端、Facade | | [《商城服务协议技术方案》](../../平台后台/内容管理/商城服务协议/商城服务协议技术方案.md) | 协议接口 | --- ## 10. 修订记录 | 版本 | 说明 | |------|------| | **v1.0** | 首版(含短信验证码) | | **v1.1** | 取消短信验证码;注册 confirmPassword;登录 account | | **v1.2** | **会员 ID = 会员名称**(`user_name`);登录 `selectByMemberCode`;**非** 数字 member_id | | **v1.3** | Token 与平台一致:`TokenService` + `LoginUser`;响应根级 `token` | | **v1.4** | 明确:`/login` **不** 设置 `MemberContext`;`MemberWebConfig` 拦截 `/api/merchant/entry/**`(排除 agreement/status) | --- *文档版本:v1.4 · MySQL 5.7.39 · RuoYi v3.9.2-springboot2*