# Web端检查支付密码接口文档 ## 模块概述 本模块提供商户用户支付密码检查功能,支持检查用户是否设置了支付密码,以及可选的密码验证功能。 --- ## 接口信息 ### 检查是否设置支付密码 #### 接口详情 - **接口名称**: 检查是否设置支付密码 - **接口路径**: `GET /merchantUser/checkPayPassword` - **请求方式**: GET - **接口描述**: 检查指定商户用户是否设置了支付密码,并可选择验证密码是否正确 - **登录验证**: ❌ 不需要(公开接口) --- ## 请求参数 | 参数名 | 类型 | 必填 | 说明 | 示例值 | |--------|------|------|------|--------| | storeUserId | String | 是 | 用户ID | "114" | | password | String | 否 | 支付密码(如果提供则验证密码是否正确) | "123456" | **参数说明**: - `storeUserId`: 商户用户的唯一标识ID - `password`: - 如果不提供,只检查用户是否设置了支付密码 - 如果提供,除了检查是否设置,还会验证密码是否正确 --- ## 请求示例 ### 示例1: 只检查是否设置支付密码 ```http GET /merchantUser/checkPayPassword?storeUserId=114 ``` ```bash curl "http://localhost:8080/merchantUser/checkPayPassword?storeUserId=114" ``` ### 示例2: 检查并验证支付密码 ```http GET /merchantUser/checkPayPassword?storeUserId=114&password=123456 ``` ```bash curl "http://localhost:8080/merchantUser/checkPayPassword?storeUserId=114&password=123456" ``` --- ## 响应参数 ### 成功响应(通用格式) ```json { "code": 200, "success": true, "data": { "code": 200, "message": "...", "data": "true/false" }, "msg": "操作成功" } ``` ### 响应字段说明 | 字段名 | 类型 | 说明 | |--------|------|------| | code | Integer | HTTP状态码 | | success | Boolean | 是否成功 | | data | Map | 详细结果数据 | | data.code | Integer | 业务状态码(固定为200) | | data.message | String | 结果描述信息 | | data.data | String | 验证结果("true"或"false") | | msg | String | 提示信息 | **data.data 字段值说明**: - `"true"`: 用户已设置支付密码(且密码验证通过,如果提供了password参数) - `"false"`: 用户未设置支付密码或密码验证失败 --- ## 响应示例 ### 场景1: 用户已设置支付密码(不验证密码) **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114 ``` **响应**: ```json { "code": 200, "success": true, "data": { "code": 200, "message": "用户已设置支付密码", "data": "true" }, "msg": "操作成功" } ``` --- ### 场景2: 用户未设置支付密码 **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114 ``` **响应**: ```json { "code": 200, "success": true, "data": { "code": 200, "message": "用户未设置支付密码", "data": "false" }, "msg": "操作成功" } ``` --- ### 场景3: 用户不存在 **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=999999 ``` **响应**: ```json { "code": 200, "success": true, "data": { "code": 200, "message": "未查询到用户", "data": "false" }, "msg": "操作成功" } ``` --- ### 场景4: 密码验证成功 **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114&password=123456 ``` **响应**: ```json { "code": 200, "success": true, "data": { "code": 200, "message": "用户已设置支付密码", "data": "true" }, "msg": "操作成功" } ``` --- ### 场景5: 密码验证失败 **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114&password=wrong_password ``` **响应**: ```json { "code": 200, "success": true, "data": { "code": 200, "message": "密码错误", "data": "false" }, "msg": "操作成功" } ``` --- ### 场景6: 系统异常 **响应**: ```json { "code": 500, "success": false, "data": null, "msg": "查询失败:{异常信息}" } ``` --- ## 业务逻辑说明 ### 处理流程 ``` ┌─────────────────────────────────────────────┐ │ 1. 接收请求参数 │ │ - storeUserId (必填) │ │ - password (可选) │ └─────────────────┬───────────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ 2. 根据用户ID查询用户信息 │ │ storeUserMapper.selectById(storeUserId) │ └─────────────────┬───────────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ 3. 检查用户是否存在 │ │ IF storeUser == null │ │ RETURN "未查询到用户", data="false" │ └─────────────────┬───────────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ 4. 检查是否设置了支付密码 │ │ IF payPassword == null │ │ RETURN "用户未设置支付密码", data="false" │ └─────────────────┬───────────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ 5. 如果提供了password参数,验证密码 │ │ IF password != null │ │ IF password != payPassword │ │ RETURN "密码错误", data="false" │ └─────────────────┬───────────────────────────┘ ↓ ┌─────────────────────────────────────────────┐ │ 6. 验证通过 │ │ RETURN "用户已设置支付密码", data="true" │ └─────────────────────────────────────────────┘ ``` ### 验证逻辑详解 #### 步骤1: 用户存在性检查 ```java StoreUser storeUser = storeUserMapper.selectById(storeUserId); if (storeUser == null) { // 用户不存在 return {"message": "未查询到用户", "data": "false"}; } ``` #### 步骤2: 支付密码设置检查 ```java if (storeUser.getPayPassword() == null) { // 用户未设置支付密码 return {"message": "用户未设置支付密码", "data": "false"}; } ``` #### 步骤3: 密码验证(可选) ```java if (password != null) { if (!password.equals(storeUser.getPayPassword())) { // 密码错误 return {"message": "密码错误", "data": "false"}; } } // 验证通过 return {"message": "用户已设置支付密码", "data": "true"}; ``` --- ## 数据库查询 ### 涉及的表 #### store_user(商户用户表) **查询SQL**: ```sql SELECT * FROM store_user WHERE id = ? ``` **使用字段**: - `id`: 用户ID - `pay_password`: 支付密码 --- ## 业务场景 ### 场景1: 支付前检查 **背景**: 用户发起支付操作前,先检查是否设置了支付密码 **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114 ``` **响应处理**: ```javascript if (response.data.data === "true") { // 已设置支付密码,弹出密码输入框 showPasswordInput(); } else { // 未设置支付密码,引导用户设置 showSetPasswordTip(); } ``` --- ### 场景2: 提现前验证 **背景**: 用户申请提现时,验证支付密码是否正确 **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114&password=123456 ``` **响应处理**: ```javascript if (response.data.data === "true") { // 密码验证通过,允许提现 proceedWithdrawal(); } else { // 密码验证失败,提示错误 showError(response.data.message); } ``` --- ### 场景3: 修改支付密码前验证 **背景**: 用户修改支付密码前,验证旧密码是否正确 **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114&password=old_password ``` **响应处理**: ```javascript if (response.data.data === "true") { // 旧密码正确,允许修改 showChangePasswordForm(); } else if (response.data.message === "密码错误") { // 旧密码错误 showError("原密码错误,请重新输入"); } else { // 其他错误 showError(response.data.message); } ``` --- ### 场景4: 忘记密码判断 **背景**: 用户点击"忘记密码",判断是否已设置过密码 **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114 ``` **响应处理**: ```javascript if (response.data.data === "false" && response.data.message === "用户未设置支付密码") { // 从未设置过密码,引导设置 showSetPasswordPage(); } else { // 已设置密码,进入重置流程 showResetPasswordPage(); } ``` --- ## 前端集成示例 ### Vue.js 示例 ```javascript // API调用方法 async checkPayPassword(userId, password = null) { try { const params = { storeUserId: userId }; if (password) { params.password = password; } const response = await axios.get('/merchantUser/checkPayPassword', { params: params }); if (response.data.success) { const result = response.data.data; return { hasPassword: result.data === "true", message: result.message }; } return { hasPassword: false, message: "查询失败" }; } catch (error) { console.error("检查支付密码失败:", error); return { hasPassword: false, message: "网络错误" }; } } // 使用示例1: 检查是否设置支付密码 async function checkIfPasswordSet() { const result = await checkPayPassword("114"); if (result.hasPassword) { console.log("用户已设置支付密码"); } else { console.log("用户未设置支付密码:", result.message); } } // 使用示例2: 验证支付密码 async function verifyPayPassword(password) { const result = await checkPayPassword("114", password); if (result.hasPassword) { console.log("密码验证成功"); return true; } else { console.log("密码验证失败:", result.message); return false; } } ``` ### React 示例 ```javascript import { useState } from 'react'; import axios from 'axios'; function PaymentComponent() { const [hasPassword, setHasPassword] = useState(false); const [message, setMessage] = useState(''); // 检查支付密码 const checkPayPassword = async (userId, password = null) => { try { const params = { storeUserId: userId }; if (password) params.password = password; const response = await axios.get('/merchantUser/checkPayPassword', { params }); if (response.data.success) { const result = response.data.data; setHasPassword(result.data === "true"); setMessage(result.message); return result.data === "true"; } } catch (error) { console.error('检查失败:', error); setMessage('查询失败'); } return false; }; return (

{message}

); } ``` --- ## 安全考虑 ### 1. 密码安全 ⚠️ **重要安全建议**: - 密码应该在数据库中**加密存储**(MD5、SHA256或BCrypt) - 传输密码时应使用**HTTPS**协议 - 不要在日志中记录明文密码 - 考虑添加密码错误次数限制,防止暴力破解 ### 2. 敏感信息保护 当前实现的安全措施: - ✅ 日志中不记录明文密码(只记录是否提供了密码) - ⚠️ 建议:密码应该加密存储 - ⚠️ 建议:添加密码错误次数限制 ### 3. 参数验证 - ✅ 必填参数:`storeUserId` - ✅ 可选参数:`password` - ⚠️ 建议:添加参数格式验证(如用户ID格式、密码长度等) ### 4. 防暴力破解 **建议实现**: ```java // 伪代码示例 if (password != null) { // 检查密码错误次数 int errorCount = getPasswordErrorCount(storeUserId); if (errorCount >= 5) { return R.fail("密码错误次数过多,请稍后再试"); } // 验证密码 if (!password.equals(storeUser.getPayPassword())) { // 记录错误次数 incrementPasswordErrorCount(storeUserId); return R.fail("密码错误"); } // 成功后清除错误次数 clearPasswordErrorCount(storeUserId); } ``` --- ## 日志记录 ### 日志级别 接口记录了详细的日志信息: ```java // INFO级别 - 请求日志 log.info("MerchantUserController.checkPayPassword?storeUserId={}, hasPassword={}", storeUserId, password != null); // INFO级别 - 业务开始 log.info("MerchantUserServiceImpl.checkPayPassword - 检查支付密码: storeUserId={}, hasPassword={}", storeUserId, password != null); // WARN级别 - 异常情况 log.warn("MerchantUserServiceImpl.checkPayPassword - 用户不存在: storeUserId={}", storeUserId); log.warn("MerchantUserServiceImpl.checkPayPassword - 密码错误: storeUserId={}", storeUserId); // INFO级别 - 业务完成 log.info("MerchantUserServiceImpl.checkPayPassword - 检查完成: storeUserId={}, result=true", storeUserId); // ERROR级别 - 异常日志 log.error("MerchantUserController.checkPayPassword ERROR: {}", e.getMessage(), e); ``` ### 日志安全 **重要**: - ✅ 不记录明文密码 - ✅ 只记录是否提供了密码(`hasPassword=true/false`) - ✅ 用户ID可以记录(非敏感信息) --- ## 异常处理 ### 异常场景 | 异常情况 | HTTP状态码 | 返回code | 返回data.message | |----------|-----------|----------|------------------| | 用户不存在 | 200 | 200 | "未查询到用户" | | 未设置密码 | 200 | 200 | "用户未设置支付密码" | | 密码错误 | 200 | 200 | "密码错误" | | 系统异常 | 200 | 500 | "查询失败:{异常信息}" | **注意**: 所有业务逻辑错误都返回HTTP 200,通过`data.data`字段判断实际结果。 --- ## 测试用例 ### 测试场景1: 正常检查(已设置密码) **前置条件**: - 用户ID=114存在 - 用户已设置支付密码 **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114 ``` **预期结果**: ```json { "data": { "code": 200, "message": "用户已设置支付密码", "data": "true" } } ``` --- ### 测试场景2: 用户未设置密码 **前置条件**: - 用户ID=114存在 - 用户未设置支付密码(pay_password为NULL) **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114 ``` **预期结果**: ```json { "data": { "code": 200, "message": "用户未设置支付密码", "data": "false" } } ``` --- ### 测试场景3: 用户不存在 **前置条件**: - 用户ID=999999不存在 **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=999999 ``` **预期结果**: ```json { "data": { "code": 200, "message": "未查询到用户", "data": "false" } } ``` --- ### 测试场景4: 密码验证成功 **前置条件**: - 用户ID=114存在 - 支付密码为"123456" **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114&password=123456 ``` **预期结果**: ```json { "data": { "code": 200, "message": "用户已设置支付密码", "data": "true" } } ``` --- ### 测试场景5: 密码验证失败 **前置条件**: - 用户ID=114存在 - 支付密码为"123456" **请求**: ``` GET /merchantUser/checkPayPassword?storeUserId=114&password=wrong_password ``` **预期结果**: ```json { "data": { "code": 200, "message": "密码错误", "data": "false" } } ``` --- ## 性能优化 ### 1. 数据库索引 确保 `store_user` 表的主键有索引: ```sql -- 主键索引(通常自动创建) ALTER TABLE store_user ADD PRIMARY KEY (id); ``` ### 2. 查询优化 - ✅ 使用主键查询(性能最优) - ✅ 只查询必要的字段 ### 3. 缓存策略 对于频繁查询的用户信息,可以考虑使用Redis缓存: ```java // 伪代码示例 String cacheKey = "user:pay_password:" + storeUserId; String hasPassword = redisTemplate.opsForValue().get(cacheKey); if (hasPassword == null) { // 查询数据库 StoreUser storeUser = storeUserMapper.selectById(storeUserId); hasPassword = storeUser.getPayPassword() != null ? "true" : "false"; // 缓存结果(TTL: 5分钟) redisTemplate.opsForValue().set(cacheKey, hasPassword, 5, TimeUnit.MINUTES); } ``` **注意**: 如果使用缓存,在用户设置或修改支付密码时需要清除缓存。 --- ## 注意事项 ### 1. 返回值格式 ⚠️ **特殊格式**: 本接口返回的`data`字段是一个Map对象,而不是简单的布尔值。 ```json // 外层R对象 { "code": 200, "success": true, "data": { // <- Map对象 "code": 200, "message": "...", "data": "true/false" // <- 字符串,不是布尔值 } } ``` ### 2. 字符串类型 ⚠️ `data.data` 字段的值是**字符串类型**(`"true"`或`"false"`),不是布尔类型。 **正确判断**: ```javascript // ✅ 正确 if (response.data.data.data === "true") { ... } // ❌ 错误 if (response.data.data.data === true) { ... } ``` ### 3. 密码安全 ⚠️ **强烈建议**: - 数据库中的密码应该加密存储 - 传输过程使用HTTPS - 添加密码错误次数限制 - 不在日志中记录明文密码 ### 4. 参数可选性 ⚠️ `password` 参数是可选的: - 不提供:只检查是否设置 - 提供:检查并验证密码 --- ## 迁移说明 ### 原接口(app端) - **服务**: `alien-store` - **路径**: `/alienStore/store/user/havePayPassword` - **Controller**: `StoreUserController` - **Service**: `StoreUserService.havePayPassword()` ### 新接口(web端) - **服务**: `alien-store-platform` - **路径**: `/merchantUser/checkPayPassword` - **Controller**: `MerchantUserController` - **Service**: `MerchantUserService.checkPayPassword()` ### 差异说明 | 项目 | app端 | web端 | 说明 | |------|-------|-------|------| | 接口路径 | `/havePayPassword` | `/checkPayPassword` | 更符合web端命名规范 | | 参数类型 | String | String | 保持一致 | | 返回类型 | R\ | R\ | 保持一致 | | 业务逻辑 | ✅ | ✅ | 完全复用 | | 日志记录 | 基础 | 详细 | 增强日志记录 | | 登录验证 | 无 | 无 | 公开接口 | ### 复用的核心组件 1. **Mapper**: `StoreUserMapper` 2. **Entity**: `StoreUser` 3. **业务逻辑**: 完全复用 --- ## 更新日志 ### 2025-11-17 **新增接口**: - ✅ `GET /merchantUser/checkPayPassword` - 检查是否设置支付密码 **核心功能**: - ✅ 检查用户是否存在 - ✅ 检查是否设置支付密码 - ✅ 可选的密码验证功能 - ✅ 返回统一格式的Map对象 - ✅ 详细日志记录 - ✅ 完善异常处理 **涉及文件**: - `MerchantUserController.java` - 更新 - `MerchantUserService.java` - 更新 - `MerchantUserServiceImpl.java` - 更新 **代码质量**: - ✅ Linter检查:无错误 - ✅ 日志记录:详细 - ✅ 异常处理:完善 - ✅ 代码注释:完整 **开发人员**: ssk --- **文档版本**: v1.0 **最后更新**: 2025-11-17 **维护人员**: ssk