feat: 初始化 ChatGPT Team 管理后端项目
- 添加用户认证模块 (JWT + 密码管理) - 添加 ChatGPT 账户管理功能 - 添加卡密管理功能 (创建、批量生成、查询) - 添加邀请功能 - 配置数据库迁移和路由系统
This commit is contained in:
213
internal/handler/card_key_handler.go
Normal file
213
internal/handler/card_key_handler.go
Normal file
@@ -0,0 +1,213 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gpt-manager-go/internal/middleware"
|
||||
"gpt-manager-go/internal/models"
|
||||
"gpt-manager-go/internal/repository"
|
||||
)
|
||||
|
||||
// CardKeyHandler 卡密处理器
|
||||
type CardKeyHandler struct {
|
||||
repo *repository.CardKeyRepository
|
||||
}
|
||||
|
||||
// NewCardKeyHandler 创建处理器
|
||||
func NewCardKeyHandler(repo *repository.CardKeyRepository) *CardKeyHandler {
|
||||
return &CardKeyHandler{repo: repo}
|
||||
}
|
||||
|
||||
// CreateCardKeyRequest 创建卡密请求
|
||||
type CreateCardKeyRequest struct {
|
||||
ValidityDays int `json:"validity_days"` // 有效期天数,默认30
|
||||
MaxUses int `json:"max_uses"` // 最大使用次数,默认1
|
||||
}
|
||||
|
||||
// BatchCreateCardKeyRequest 批量创建卡密请求
|
||||
type BatchCreateCardKeyRequest struct {
|
||||
Count int `json:"count"` // 创建数量
|
||||
ValidityDays int `json:"validity_days"` // 有效期天数,默认30
|
||||
MaxUses int `json:"max_uses"` // 最大使用次数,默认1
|
||||
}
|
||||
|
||||
// CardKeyResponse 卡密响应
|
||||
type CardKeyResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Data *models.CardKey `json:"data,omitempty"`
|
||||
Keys []*models.CardKey `json:"keys,omitempty"`
|
||||
}
|
||||
|
||||
// Handle 处理卡密接口 (GET: 列表, POST: 创建)
|
||||
func (h *CardKeyHandler) Handle(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
h.list(w, r)
|
||||
case http.MethodPost:
|
||||
h.create(w, r)
|
||||
default:
|
||||
respondJSON(w, http.StatusMethodNotAllowed, CardKeyResponse{
|
||||
Success: false,
|
||||
Message: "Method not allowed",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// create 创建单个卡密
|
||||
func (h *CardKeyHandler) create(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var req CreateCardKeyRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
// 允许空请求体,使用默认值
|
||||
req = CreateCardKeyRequest{}
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if req.ValidityDays <= 0 {
|
||||
req.ValidityDays = 30
|
||||
}
|
||||
if req.MaxUses <= 0 {
|
||||
req.MaxUses = 1
|
||||
}
|
||||
|
||||
// 获取当前用户
|
||||
claims := middleware.GetUserFromContext(r.Context())
|
||||
|
||||
// 生成卡密
|
||||
cardKey := &models.CardKey{
|
||||
Key: generateCardKey(),
|
||||
MaxUses: req.MaxUses,
|
||||
UsedCount: 0,
|
||||
ValidityType: "custom",
|
||||
ExpiresAt: time.Now().AddDate(0, 0, req.ValidityDays),
|
||||
IsActive: true,
|
||||
CreatedByID: claims.UserID,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
if err := h.repo.Create(cardKey); err != nil {
|
||||
respondJSON(w, http.StatusInternalServerError, CardKeyResponse{
|
||||
Success: false,
|
||||
Message: "Failed to create card key: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
respondJSON(w, http.StatusCreated, CardKeyResponse{
|
||||
Success: true,
|
||||
Message: "Card key created successfully",
|
||||
Data: cardKey,
|
||||
})
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建卡密 (POST /api/cardkeys/batch)
|
||||
func (h *CardKeyHandler) BatchCreate(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
respondJSON(w, http.StatusMethodNotAllowed, CardKeyResponse{
|
||||
Success: false,
|
||||
Message: "Method not allowed",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var req BatchCreateCardKeyRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
respondJSON(w, http.StatusBadRequest, CardKeyResponse{
|
||||
Success: false,
|
||||
Message: "Invalid request body",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证和设置默认值
|
||||
if req.Count <= 0 {
|
||||
respondJSON(w, http.StatusBadRequest, CardKeyResponse{
|
||||
Success: false,
|
||||
Message: "Count must be greater than 0",
|
||||
})
|
||||
return
|
||||
}
|
||||
if req.Count > 100 {
|
||||
respondJSON(w, http.StatusBadRequest, CardKeyResponse{
|
||||
Success: false,
|
||||
Message: "Count cannot exceed 100",
|
||||
})
|
||||
return
|
||||
}
|
||||
if req.ValidityDays <= 0 {
|
||||
req.ValidityDays = 30
|
||||
}
|
||||
if req.MaxUses <= 0 {
|
||||
req.MaxUses = 1
|
||||
}
|
||||
|
||||
// 获取当前用户
|
||||
claims := middleware.GetUserFromContext(r.Context())
|
||||
|
||||
// 批量创建
|
||||
var createdKeys []*models.CardKey
|
||||
expiresAt := time.Now().AddDate(0, 0, req.ValidityDays)
|
||||
|
||||
for i := 0; i < req.Count; i++ {
|
||||
cardKey := &models.CardKey{
|
||||
Key: generateCardKey(),
|
||||
MaxUses: req.MaxUses,
|
||||
UsedCount: 0,
|
||||
ValidityType: "custom",
|
||||
ExpiresAt: expiresAt,
|
||||
IsActive: true,
|
||||
CreatedByID: claims.UserID,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
if err := h.repo.Create(cardKey); err != nil {
|
||||
// 如果创建失败,返回已创建的卡密
|
||||
respondJSON(w, http.StatusInternalServerError, CardKeyResponse{
|
||||
Success: false,
|
||||
Message: "Failed to create some card keys",
|
||||
Keys: createdKeys,
|
||||
})
|
||||
return
|
||||
}
|
||||
createdKeys = append(createdKeys, cardKey)
|
||||
}
|
||||
|
||||
respondJSON(w, http.StatusCreated, CardKeyResponse{
|
||||
Success: true,
|
||||
Message: "Card keys created successfully",
|
||||
Keys: createdKeys,
|
||||
})
|
||||
}
|
||||
|
||||
// list 获取卡密列表
|
||||
func (h *CardKeyHandler) list(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
cardKeys, err := h.repo.FindAll()
|
||||
if err != nil {
|
||||
respondJSON(w, http.StatusInternalServerError, CardKeyResponse{
|
||||
Success: false,
|
||||
Message: "Failed to fetch card keys",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
respondJSON(w, http.StatusOK, CardKeyResponse{
|
||||
Success: true,
|
||||
Message: "OK",
|
||||
Keys: cardKeys,
|
||||
})
|
||||
}
|
||||
|
||||
// generateCardKey 生成卡密格式: XXXX-XXXX-XXXX-XXXX
|
||||
func generateCardKey() string {
|
||||
bytes := make([]byte, 8)
|
||||
rand.Read(bytes)
|
||||
hex := strings.ToUpper(hex.EncodeToString(bytes))
|
||||
return hex[0:4] + "-" + hex[4:8] + "-" + hex[8:12] + "-" + hex[12:16]
|
||||
}
|
||||
Reference in New Issue
Block a user