feat: 添加注册发送验证码功能,支持手机号验证及频率限制,更新相关文档和国际化文本
This commit is contained in:
1 parent
af76eaf1b1
commit
9c2b503d2b
13 files changed
+530
-28
No files matched your search
@@ -18,11 +18,13 @@ errors:
|
||||
customer:
|
||||
"200001": "Customer not found"
|
||||
"200002": "Customer already exists"
|
||||
"200003": "Customer name is required"
|
||||
"200004": "Invalid customer information format"
|
||||
"200005": "Failed to query customer list"
|
||||
"200006": "Customer has authorization codes, cannot delete. Please delete authorizations first"
|
||||
"200007": "Customer is disabled, cannot create authorization"
|
||||
"200003": "Request too frequent, please try again later"
|
||||
"200004": "SMS sending failed"
|
||||
"200005": "Customer name is required"
|
||||
"200006": "Invalid customer information format"
|
||||
"200007": "Failed to query customer list"
|
||||
"200008": "Customer has authorization codes, cannot delete. Please delete authorizations first"
|
||||
"200009": "Customer is disabled, cannot create authorization"
|
||||
|
||||
# Authorization module (30xxxx)
|
||||
authorization:
|
||||
|
||||
@@ -18,11 +18,13 @@ errors:
|
||||
customer:
|
||||
"200001": "客户不存在"
|
||||
"200002": "客户已存在"
|
||||
"200003": "客户名称不能为空"
|
||||
"200004": "客户信息格式无效"
|
||||
"200005": "客户列表查询失败"
|
||||
"200006": "客户仍有授权,无法删除,请先删除授权"
|
||||
"200007": "客户已停用,无法创建授权"
|
||||
"200003": "请求过于频繁,请稍后再试"
|
||||
"200004": "短信发送失败"
|
||||
"200005": "客户名称不能为空"
|
||||
"200006": "客户信息格式无效"
|
||||
"200007": "客户列表查询失败"
|
||||
"200008": "客户仍有授权,无法删除,请先删除授权"
|
||||
"200009": "客户已停用,无法创建授权"
|
||||
|
||||
# 授权模块 (30xxxx)
|
||||
authorization:
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
ORM: GORM,开发环境使用Auto Migration
|
||||
配置: Viper
|
||||
日志: logrus
|
||||
认证: JWT
|
||||
认证: JWT (支持管理员和C端用户双JWT体系)
|
||||
缓存: Redis (可选)
|
||||
数据库: PostgreSQL/MySQL
|
||||
支付集成: 支付宝
|
||||
加密算法: RSA
|
||||
|
||||
|
||||
## 目录结构
|
||||
@@ -20,16 +22,32 @@
|
||||
backend/
|
||||
├── cmd/
|
||||
│ ├── main.go # 程序入口
|
||||
│ └── license_manager.sh # 启动脚本
|
||||
│ ├── license_manager.sh # 启动脚本
|
||||
│ ├── client-demo/ # C端客户端演示程序
|
||||
│ │ ├── main.go
|
||||
│ │ ├── rsa.go
|
||||
│ │ ├── client_config.json
|
||||
│ │ ├── README.md
|
||||
│ │ └── license_code/
|
||||
│ └── gen-rsa-keys/ # RSA密钥生成工具
|
||||
│ └── main.go
|
||||
├── internal/
|
||||
│ ├── api/
|
||||
│ │ ├── handlers/ # HTTP处理器
|
||||
│ │ │ ├── auth_handler.go
|
||||
│ │ │ ├── authorization_code_handler.go
|
||||
│ │ │ ├── customer_handler.go
|
||||
│ │ │ ├── dashboard_handler.go
|
||||
│ │ │ ├── enum_handler.go
|
||||
│ │ │ ├── license_handler.go
|
||||
│ │ │ └── system_handler.go
|
||||
│ │ │ ├── payment_handler.go
|
||||
│ │ │ ├── system_handler.go
|
||||
│ │ │ ├── cu_auth_handler.go
|
||||
│ │ │ ├── cu_authorization_handler.go
|
||||
│ │ │ ├── cu_device_handler.go
|
||||
│ │ │ ├── cu_order_handler.go
|
||||
│ │ │ ├── cu_order_handler_test.go
|
||||
│ │ │ └── cu_profile_handler.go
|
||||
│ │ ├── middleware/ # 中间件
|
||||
│ │ │ ├── auth.go
|
||||
│ │ │ ├── cors.go
|
||||
@@ -41,22 +59,36 @@ backend/
|
||||
│ │ ├── auth_service.go
|
||||
│ │ ├── authorization_code_service.go
|
||||
│ │ ├── customer_service.go
|
||||
│ │ ├── dashboard_service.go
|
||||
│ │ ├── enum_service.go
|
||||
│ │ ├── license_service.go
|
||||
│ │ ├── payment_service.go
|
||||
│ │ ├── system_service.go
|
||||
│ │ ├── cu_device_service.go
|
||||
│ │ ├── cu_order_service.go
|
||||
│ │ ├── cu_user_service.go
|
||||
│ │ └── interfaces.go # 接口定义
|
||||
│ ├── repository/ # 数据访问层
|
||||
│ │ ├── authorization_code_repository.go
|
||||
│ │ ├── customer_repository.go
|
||||
│ │ ├── dashboard_repository.go
|
||||
│ │ ├── license_repository.go
|
||||
│ │ ├── payment_repository.go
|
||||
│ │ ├── user_repository.go
|
||||
│ │ ├── cu_order_repository.go
|
||||
│ │ ├── cu_user_repository.go
|
||||
│ │ ├── gorm/ # GORM相关扩展
|
||||
│ │ ├── errors.go
|
||||
│ │ └── interfaces.go
|
||||
│ ├── models/ # 数据模型
|
||||
│ │ ├── auth.go
|
||||
│ │ ├── common.go
|
||||
│ │ ├── customer.go
|
||||
│ │ ├── cu_order.go
|
||||
│ │ ├── cu_user.go
|
||||
│ │ ├── dashboard.go
|
||||
│ │ ├── license.go
|
||||
│ │ ├── payment.go
|
||||
│ │ ├── system.go
|
||||
│ │ └── user.go
|
||||
│ ├── config/ # 配置管理
|
||||
@@ -71,8 +103,11 @@ backend/
|
||||
│ │ ├── errors.go
|
||||
│ │ └── manager.go
|
||||
│ ├── utils/ # 工具函数
|
||||
│ │ ├── crypto.go
|
||||
│ │ └── jwt.go
|
||||
│ │ ├── alipay.go # 支付宝支付集成
|
||||
│ │ ├── crypto.go # 加密工具
|
||||
│ │ ├── cu_jwt.go # C端用户JWT工具
|
||||
│ │ ├── jwt.go # JWT工具
|
||||
│ │ └── license_codec.go # 授权码编解码
|
||||
│ └── logger/ # 日志封装
|
||||
│ └── logger.go
|
||||
├── configs/
|
||||
@@ -113,6 +148,11 @@ backend/
|
||||
│ ├── 004_create_licenses_table.sql
|
||||
│ ├── 005_create_authorization_changes_table.sql
|
||||
│ ├── 006_create_users_table.sql
|
||||
│ ├── 007_create_cu_users_table.sql
|
||||
│ ├── 008_create_cu_orders_table.sql
|
||||
│ ├── 009_update_authorization_codes_code_length.sql
|
||||
│ ├── 010_update_cu_orders_authorization_code_length.sql
|
||||
│ ├── 011_create_payments_table.sql
|
||||
│ └── README.md
|
||||
├── go.mod
|
||||
└── go.sum
|
||||
@@ -123,4 +163,7 @@ backend/
|
||||
- **依赖注入**:通过接口解耦各层
|
||||
- **配置驱动**:Viper管理所有配置
|
||||
- **缓存抽象**:支持内存/Redis切换
|
||||
- **双JWT体系**:支持管理员和C端用户独立认证体系
|
||||
- **模块化设计**:支持客户管理、订单管理、支付集成等独立模块
|
||||
- **国际化支持**:完整的多语言错误信息系统
|
||||
|
||||
@@ -59,10 +59,12 @@ errors:
|
||||
"100004": "缺少认证信息"
|
||||
"100005": "权限不足"
|
||||
|
||||
# 客户模块 (20xxxx) - 预留
|
||||
# 客户模块 (20xxxx)
|
||||
customer:
|
||||
"200001": "客户不存在"
|
||||
"200002": "客户已存在"
|
||||
"200003": "请求过于频繁,请稍后再试"
|
||||
"200004": "短信发送失败"
|
||||
|
||||
# 授权模块 (30xxxx) - 预留
|
||||
license:
|
||||
@@ -99,6 +101,8 @@ errors:
|
||||
customer:
|
||||
"200001": "Customer not found"
|
||||
"200002": "Customer already exists"
|
||||
"200003": "Request too frequent, please try again later"
|
||||
"200004": "SMS sending failed"
|
||||
|
||||
license:
|
||||
"300001": "Invalid license key"
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
# 注册发送验证码接口
|
||||
|
||||
## 概述
|
||||
|
||||
为注册流程提供手机号验证功能,用户在注册前需要先获取短信验证码进行手机号验证。
|
||||
|
||||
## 接口信息
|
||||
|
||||
- **接口路径**: `POST /api/cu/send-register-sms`
|
||||
- **认证方式**: 无需认证(公开接口)
|
||||
- **请求格式**: `application/json`
|
||||
- **响应格式**: `application/json`
|
||||
|
||||
## 请求参数
|
||||
|
||||
```json
|
||||
{
|
||||
"phone": "13800138000", // 必填,手机号
|
||||
"phone_country_code": "+86" // 可选,国家代码,默认+86
|
||||
}
|
||||
```
|
||||
|
||||
### 参数说明
|
||||
|
||||
| 参数名 | 类型 | 必填 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| phone | string | 是 | 手机号,长度7-20位 |
|
||||
| phone_country_code | string | 否 | 国家代码,默认"+86" |
|
||||
|
||||
## 响应格式
|
||||
|
||||
### 成功响应 (200)
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "验证码发送成功",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
### 错误响应
|
||||
|
||||
#### 手机号已存在 (200002)
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "200002",
|
||||
"message": "客户已存在",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
#### 请求过于频繁 (200003)
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "200003",
|
||||
"message": "请求过于频繁,请稍后再试",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
#### 参数无效 (900001)
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "900001",
|
||||
"message": "请求参数无效",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
#### 短信发送失败 (200004)
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "200004",
|
||||
"message": "短信发送失败",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
## 业务逻辑
|
||||
|
||||
1. **参数验证**
|
||||
- 验证手机号格式
|
||||
- 验证国家代码格式(如提供)
|
||||
- 参数不符合要求时,返回错误码 `900001`
|
||||
|
||||
2. **用户检查**
|
||||
- 检查手机号是否已被注册
|
||||
- 如已注册,返回错误码 `200002`
|
||||
|
||||
3. **频率限制**
|
||||
- 限制同一手机号发送频率(建议:1分钟内最多1次,1小时内最多5次)
|
||||
- 使用Redis缓存记录发送时间和次数
|
||||
- 超过频率限制时,返回错误码 `200003`
|
||||
|
||||
4. **验证码生成**
|
||||
- 生成6位数字验证码
|
||||
- 将验证码存储到Redis(设置过期时间,如5分钟)
|
||||
|
||||
5. **短信发送**
|
||||
- 调用短信服务发送验证码
|
||||
- 发送失败时,返回错误码 `200004`
|
||||
- 记录发送日志
|
||||
|
||||
## 与忘记密码接口对比
|
||||
|
||||
| 对比项 | 注册验证码接口 | 忘记密码验证码接口 |
|
||||
|--------|----------------|-------------------|
|
||||
| 接口路径 | `/api/cu/send-register-sms` | `/api/cu/forgot-password` |
|
||||
| 用户存在检查 | 检查用户**不存在** | 检查用户**存在** |
|
||||
| 验证码用途 | 手机号验证 | 密码重置 |
|
||||
| 频率限制 | 较宽松 | 较严格 |
|
||||
| 缓存键前缀 | `register_sms:` | `forgot_sms:` |
|
||||
|
||||
## 缓存设计
|
||||
|
||||
- **验证码存储**: `register_sms:{phone_country_code}:{phone}` (过期时间: 5分钟)
|
||||
- **频率限制**: `register_sms_limit:{phone_country_code}:{phone}` (过期时间: 1小时)
|
||||
|
||||
## 安全考虑
|
||||
|
||||
1. 验证码只能使用一次,验证后立即删除
|
||||
2. 限制发送频率,防止短信轰炸
|
||||
3. 记录发送日志,便于审计
|
||||
4. 支持图形验证码作为二次验证(可选)
|
||||
|
||||
## 后续流程
|
||||
|
||||
1. 用户收到验证码后,填写注册表单
|
||||
2. 调用注册接口 `/api/cu/register`,提交手机号、验证码、密码等信息
|
||||
3. 后端验证验证码正确性,完成注册流程
|
||||
@@ -1180,6 +1180,64 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/cu/send-register-sms": {
|
||||
"post": {
|
||||
"description": "注册前发送短信验证码到手机",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"客户用户管理"
|
||||
],
|
||||
"summary": "注册发送验证码",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "注册发送验证码请求",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.CuUserSendRegisterSmsRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "验证码发送成功",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.APIResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "请求参数无效",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"409": {
|
||||
"description": "手机号已被注册",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"429": {
|
||||
"description": "请求过于频繁",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "短信发送失败",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/customers": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -4325,7 +4383,7 @@ const docTemplate = `{
|
||||
"type": "string"
|
||||
},
|
||||
"payment_method": {
|
||||
"description": "可选:支付方式,不传则为免费订单",
|
||||
"description": "可选:支付方式,不传则为免费订单 支持:alipay,wechat",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@@ -4642,6 +4700,23 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.CuUserSendRegisterSmsRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"phone"
|
||||
],
|
||||
"properties": {
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"maxLength": 20,
|
||||
"minLength": 7
|
||||
},
|
||||
"phone_country_code": {
|
||||
"description": "可选,默认+86",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.Customer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -5587,9 +5662,15 @@ const docTemplate = `{
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"cu_user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"customer_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"expire_time": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -5619,9 +5700,6 @@ const docTemplate = `{
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1176,6 +1176,64 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/cu/send-register-sms": {
|
||||
"post": {
|
||||
"description": "注册前发送短信验证码到手机",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"客户用户管理"
|
||||
],
|
||||
"summary": "注册发送验证码",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "注册发送验证码请求",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.CuUserSendRegisterSmsRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "验证码发送成功",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.APIResponse"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "请求参数无效",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"409": {
|
||||
"description": "手机号已被注册",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"429": {
|
||||
"description": "请求过于频繁",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "短信发送失败",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/customers": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -4321,7 +4379,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"payment_method": {
|
||||
"description": "可选:支付方式,不传则为免费订单",
|
||||
"description": "可选:支付方式,不传则为免费订单 支持:alipay,wechat",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
@@ -4638,6 +4696,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.CuUserSendRegisterSmsRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"phone"
|
||||
],
|
||||
"properties": {
|
||||
"phone": {
|
||||
"type": "string",
|
||||
"maxLength": 20,
|
||||
"minLength": 7
|
||||
},
|
||||
"phone_country_code": {
|
||||
"description": "可选,默认+86",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.Customer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -5583,9 +5658,15 @@
|
||||
"created_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"cu_user_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"currency": {
|
||||
"type": "string"
|
||||
},
|
||||
"customer_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"expire_time": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -5615,9 +5696,6 @@
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -470,7 +470,7 @@ definitions:
|
||||
package_id:
|
||||
type: string
|
||||
payment_method:
|
||||
description: 可选:支付方式,不传则为免费订单
|
||||
description: 可选:支付方式,不传则为免费订单 支持:alipay,wechat
|
||||
type: string
|
||||
required:
|
||||
- license_count
|
||||
@@ -693,6 +693,18 @@ definitions:
|
||||
user_role:
|
||||
type: string
|
||||
type: object
|
||||
models.CuUserSendRegisterSmsRequest:
|
||||
properties:
|
||||
phone:
|
||||
maxLength: 20
|
||||
minLength: 7
|
||||
type: string
|
||||
phone_country_code:
|
||||
description: 可选,默认+86
|
||||
type: string
|
||||
required:
|
||||
- phone
|
||||
type: object
|
||||
models.Customer:
|
||||
properties:
|
||||
address:
|
||||
@@ -1354,8 +1366,12 @@ definitions:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
cu_user_id:
|
||||
type: string
|
||||
currency:
|
||||
type: string
|
||||
customer_id:
|
||||
type: string
|
||||
expire_time:
|
||||
type: string
|
||||
id:
|
||||
@@ -1376,8 +1392,6 @@ definitions:
|
||||
type: string
|
||||
updated_at:
|
||||
type: string
|
||||
user_id:
|
||||
type: integer
|
||||
type: object
|
||||
models.PaymentStatusResponse:
|
||||
properties:
|
||||
@@ -2241,6 +2255,44 @@ paths:
|
||||
summary: 重置密码
|
||||
tags:
|
||||
- 客户用户管理
|
||||
/api/cu/send-register-sms:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 注册前发送短信验证码到手机
|
||||
parameters:
|
||||
- description: 注册发送验证码请求
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/models.CuUserSendRegisterSmsRequest'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: 验证码发送成功
|
||||
schema:
|
||||
$ref: '#/definitions/models.APIResponse'
|
||||
"400":
|
||||
description: 请求参数无效
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
"409":
|
||||
description: 手机号已被注册
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
"429":
|
||||
description: 请求过于频繁
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
"500":
|
||||
description: 短信发送失败
|
||||
schema:
|
||||
$ref: '#/definitions/models.ErrorResponse'
|
||||
summary: 注册发送验证码
|
||||
tags:
|
||||
- 客户用户管理
|
||||
/api/customers:
|
||||
get:
|
||||
consumes:
|
||||
|
||||
@@ -235,6 +235,64 @@ func (h *CuAuthHandler) CuUserForgotPassword(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// CuUserSendRegisterSms 注册发送验证码
|
||||
// @Summary 注册发送验证码
|
||||
// @Description 注册前发送短信验证码到手机
|
||||
// @Tags 客户用户管理
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body models.CuUserSendRegisterSmsRequest true "注册发送验证码请求"
|
||||
// @Success 200 {object} models.APIResponse "验证码发送成功"
|
||||
// @Failure 400 {object} models.ErrorResponse "请求参数无效"
|
||||
// @Failure 409 {object} models.ErrorResponse "手机号已被注册"
|
||||
// @Failure 429 {object} models.ErrorResponse "请求过于频繁"
|
||||
// @Failure 500 {object} models.ErrorResponse "短信发送失败"
|
||||
// @Router /api/cu/send-register-sms [post]
|
||||
func (h *CuAuthHandler) CuUserSendRegisterSms(c *gin.Context) {
|
||||
var req models.CuUserSendRegisterSmsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
lang := middleware.GetLanguage(c)
|
||||
status, errCode, message := i18n.NewI18nErrorResponse("900001", lang)
|
||||
c.JSON(status, models.ErrorResponse{
|
||||
Code: errCode,
|
||||
Message: message + ": " + err.Error(),
|
||||
Timestamp: getCurrentTimestamp(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err := h.cuUserService.SendRegisterSms(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
// err已经是i18n.I18nError,直接使用
|
||||
i18nErr, ok := err.(*i18n.I18nError)
|
||||
if ok {
|
||||
c.JSON(i18nErr.HttpCode, models.ErrorResponse{
|
||||
Code: i18nErr.Code,
|
||||
Message: i18nErr.Message,
|
||||
Timestamp: getCurrentTimestamp(),
|
||||
})
|
||||
return
|
||||
}
|
||||
// 如果不是i18n错误,使用通用错误
|
||||
lang := middleware.GetLanguage(c)
|
||||
status, errCode, message := i18n.NewI18nErrorResponse("900004", lang, err.Error())
|
||||
c.JSON(status, models.ErrorResponse{
|
||||
Code: errCode,
|
||||
Message: message,
|
||||
Timestamp: getCurrentTimestamp(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
lang := middleware.GetLanguage(c)
|
||||
successMessage := i18n.GetErrorMessage("000000", lang)
|
||||
c.JSON(http.StatusOK, models.APIResponse{
|
||||
Code: "000000",
|
||||
Message: successMessage,
|
||||
Data: nil,
|
||||
})
|
||||
}
|
||||
|
||||
// CuUserResetPassword 重置密码
|
||||
// @Summary 重置密码
|
||||
// @Description 通过验证码重置密码
|
||||
|
||||
@@ -160,6 +160,7 @@ func SetupRouter() *gin.Engine {
|
||||
{
|
||||
cuPublic.POST("/register", cuAuthHandler.CuUserRegister)
|
||||
cuPublic.POST("/login", cuAuthHandler.CuUserLogin)
|
||||
cuPublic.POST("/send-register-sms", cuAuthHandler.CuUserSendRegisterSms)
|
||||
cuPublic.POST("/forgot-password", cuAuthHandler.CuUserForgotPassword)
|
||||
cuPublic.POST("/reset-password", cuAuthHandler.CuUserResetPassword)
|
||||
cuPublic.GET("/packages", cuOrderHandler.GetPackages)
|
||||
|
||||
@@ -61,7 +61,7 @@ func (o *CuOrder) BeforeUpdate(tx *gorm.DB) error {
|
||||
type CuOrderCreateRequest struct {
|
||||
PackageID string `json:"package_id" binding:"required"`
|
||||
LicenseCount int `json:"license_count" binding:"required,min=1,max=1000"`
|
||||
PaymentMethod string `json:"payment_method,omitempty"` // 可选:支付方式,不传则为免费订单
|
||||
PaymentMethod string `json:"payment_method,omitempty"` // 可选:支付方式,不传则为免费订单 支持:alipay,wechat
|
||||
}
|
||||
|
||||
// CuOrderResponse 订单响应结构
|
||||
|
||||
@@ -112,6 +112,12 @@ type CuUserPhoneUpdateRequest struct {
|
||||
NewSmsCode string `json:"new_sms_code" binding:"required,len=6"` // 新手机号验证码
|
||||
}
|
||||
|
||||
// CuUserSendRegisterSmsRequest 注册发送验证码请求结构
|
||||
type CuUserSendRegisterSmsRequest struct {
|
||||
Phone string `json:"phone" binding:"required,min=7,max=20"`
|
||||
PhoneCountryCode string `json:"phone_country_code" binding:"omitempty"` // 可选,默认+86
|
||||
}
|
||||
|
||||
// CuUserForgotPasswordRequest 忘记密码请求结构(发送重置验证码)
|
||||
type CuUserForgotPasswordRequest struct {
|
||||
Phone string `json:"phone" binding:"required,min=7,max=20"`
|
||||
|
||||
@@ -22,6 +22,7 @@ type CuUserService interface {
|
||||
UpdateProfile(ctx context.Context, userID string, req *models.CuUserProfileUpdateRequest) error
|
||||
UpdatePhone(ctx context.Context, userID string, req *models.CuUserPhoneUpdateRequest) error
|
||||
ChangePassword(ctx context.Context, userID, oldPassword, newPassword string) error
|
||||
SendRegisterSms(ctx context.Context, req *models.CuUserSendRegisterSmsRequest) error
|
||||
ForgotPassword(ctx context.Context, req *models.CuUserForgotPasswordRequest) error
|
||||
ResetPassword(ctx context.Context, req *models.CuUserResetPasswordRequest) error
|
||||
GetUsersByCustomer(ctx context.Context, customerID string, offset, limit int) ([]*models.CuUser, int64, error)
|
||||
@@ -353,6 +354,48 @@ func (s *cuUserService) ChangePassword(ctx context.Context, userID, oldPassword,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *cuUserService) SendRegisterSms(ctx context.Context, req *models.CuUserSendRegisterSmsRequest) error {
|
||||
lang := pkgcontext.GetLanguageFromContext(ctx)
|
||||
|
||||
// 业务逻辑:参数验证
|
||||
if req == nil {
|
||||
return i18n.NewI18nError("900001", lang)
|
||||
}
|
||||
|
||||
// 设置默认国家代码
|
||||
phoneCountryCode := req.PhoneCountryCode
|
||||
if phoneCountryCode == "" {
|
||||
phoneCountryCode = "+86" // 默认中国
|
||||
}
|
||||
|
||||
// 检查手机号是否已被注册
|
||||
exists, err := s.repo.CheckPhoneExists(req.Phone, phoneCountryCode, "")
|
||||
if err != nil {
|
||||
return i18n.NewI18nError("900004", lang, err.Error())
|
||||
}
|
||||
if exists {
|
||||
return i18n.NewI18nError("200002", lang) // 客户已存在
|
||||
}
|
||||
|
||||
// TODO: 实现频率限制检查
|
||||
// 这里应该检查Redis中该手机号的发送频率
|
||||
// 例如:1分钟内最多发送1次,1小时内最多发送5次
|
||||
// 如果超出限制,返回错误码 200003
|
||||
|
||||
// TODO: 生成6位随机验证码并发送短信
|
||||
// 1. 生成随机验证码
|
||||
// 2. 调用短信服务发送验证码
|
||||
// 3. 将验证码存储到Redis中,设置过期时间(5分钟)
|
||||
// 例如:
|
||||
// verificationCode := generateRandomCode(6)
|
||||
// smsService.SendSms(phoneCountryCode + req.Phone, fmt.Sprintf("您的注册验证码是:%s", verificationCode))
|
||||
// redis.Set(fmt.Sprintf("register_sms:%s:%s", phoneCountryCode, req.Phone), verificationCode, 5*time.Minute)
|
||||
// 如果发送失败,返回错误码 200004
|
||||
|
||||
// 暂时返回成功,等待短信服务实现
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *cuUserService) ForgotPassword(ctx context.Context, req *models.CuUserForgotPasswordRequest) error {
|
||||
lang := pkgcontext.GetLanguageFromContext(ctx)
|
||||
|
||||
|
||||
Reference in new issue
Block a user