Files
junhong_cmp_fiber/internal/handler/app/client_auth.go
huang 2ef8b8a705
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
fix: 修复分页字段/角色DTO/套餐详情/批量分配Bug,新增C端测试登录接口和Hurl价格验证测试
- 修复B-2:27个分页DTO字段名统一(list→items, page_size→size,删除total_pages)
- 修复B-1:角色接口统一返回DTO(id小写,消除GORM大写字段名)
- 修复C-1:套餐详情接口(GET /packages/:id)补充代理佣金字段
- 修复C-2:批量分配已存在记录由500改为静默跳过
- 修复C-3:创建系列授权响应在事务提交后构建,packages数组不再为空
- 新增C端开发测试登录接口(POST /api/c/v1/auth/dev-login,仅logging.development=true时生效)
- 新增Hurl测试:card-price-verification-flow.hurl(导入卡→分配→C端价格验证)
- 新增测试Excel数据文件和dev.env测试变量
2026-03-31 09:54:08 +08:00

189 lines
5.5 KiB
Go

package app
import (
"github.com/break/junhong_cmp_fiber/internal/middleware"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
clientAuthSvc "github.com/break/junhong_cmp_fiber/internal/service/client_auth"
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/break/junhong_cmp_fiber/pkg/logger"
"github.com/break/junhong_cmp_fiber/pkg/response"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
var clientAuthValidator = validator.New()
// ClientAuthHandler C 端认证处理器
type ClientAuthHandler struct {
service *clientAuthSvc.Service
logger *zap.Logger
}
// NewClientAuthHandler 创建 C 端认证处理器
func NewClientAuthHandler(service *clientAuthSvc.Service, logger *zap.Logger) *ClientAuthHandler {
return &ClientAuthHandler{service: service, logger: logger}
}
// VerifyAsset A1 资产验证
// POST /api/c/v1/auth/verify-asset
func (h *ClientAuthHandler) VerifyAsset(c *fiber.Ctx) error {
var req dto.VerifyAssetRequest
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
if err := clientAuthValidator.Struct(&req); err != nil {
logger.GetAppLogger().Warn("资产验证参数校验失败", zap.Error(err))
return errors.New(errors.CodeInvalidParam)
}
resp, err := h.service.VerifyAsset(c.UserContext(), &req, c.IP())
if err != nil {
return err
}
return response.Success(c, resp)
}
// WechatLogin A2 公众号登录
// POST /api/c/v1/auth/wechat-login
func (h *ClientAuthHandler) WechatLogin(c *fiber.Ctx) error {
var req dto.WechatLoginRequest
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
if err := clientAuthValidator.Struct(&req); err != nil {
logger.GetAppLogger().Warn("公众号登录参数校验失败", zap.Error(err))
return errors.New(errors.CodeInvalidParam)
}
resp, err := h.service.WechatLogin(c.UserContext(), &req, c.IP())
if err != nil {
return err
}
return response.Success(c, resp)
}
// MiniappLogin A3 小程序登录
// POST /api/c/v1/auth/miniapp-login
func (h *ClientAuthHandler) MiniappLogin(c *fiber.Ctx) error {
var req dto.MiniappLoginRequest
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
if err := clientAuthValidator.Struct(&req); err != nil {
logger.GetAppLogger().Warn("小程序登录参数校验失败", zap.Error(err))
return errors.New(errors.CodeInvalidParam)
}
resp, err := h.service.MiniappLogin(c.UserContext(), &req, c.IP())
if err != nil {
return err
}
return response.Success(c, resp)
}
// SendCode A4 发送验证码
// POST /api/c/v1/auth/send-code
func (h *ClientAuthHandler) SendCode(c *fiber.Ctx) error {
var req dto.ClientSendCodeRequest
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
if err := clientAuthValidator.Struct(&req); err != nil {
logger.GetAppLogger().Warn("发送验证码参数校验失败", zap.Error(err))
return errors.New(errors.CodeInvalidParam)
}
resp, err := h.service.SendCode(c.UserContext(), &req, c.IP())
if err != nil {
return err
}
return response.Success(c, resp)
}
// BindPhone A5 绑定手机号
// POST /api/c/v1/auth/bind-phone
func (h *ClientAuthHandler) BindPhone(c *fiber.Ctx) error {
customerID, ok := middleware.GetCustomerID(c)
if !ok || customerID == 0 {
return errors.New(errors.CodeUnauthorized)
}
var req dto.BindPhoneRequest
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
if err := clientAuthValidator.Struct(&req); err != nil {
logger.GetAppLogger().Warn("绑定手机号参数校验失败", zap.Error(err))
return errors.New(errors.CodeInvalidParam)
}
resp, err := h.service.BindPhone(c.UserContext(), customerID, &req)
if err != nil {
return err
}
return response.Success(c, resp)
}
// ChangePhone A6 更换手机号
// POST /api/c/v1/auth/change-phone
func (h *ClientAuthHandler) ChangePhone(c *fiber.Ctx) error {
customerID, ok := middleware.GetCustomerID(c)
if !ok || customerID == 0 {
return errors.New(errors.CodeUnauthorized)
}
var req dto.ChangePhoneRequest
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
if err := clientAuthValidator.Struct(&req); err != nil {
logger.GetAppLogger().Warn("更换手机号参数校验失败", zap.Error(err))
return errors.New(errors.CodeInvalidParam)
}
resp, err := h.service.ChangePhone(c.UserContext(), customerID, &req)
if err != nil {
return err
}
return response.Success(c, resp)
}
// DevLogin 开发环境测试登录(仅开发模式可用)
// POST /api/c/v1/auth/dev-login
func (h *ClientAuthHandler) DevLogin(c *fiber.Ctx) error {
var req dto.DevLoginRequest
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam)
}
if err := clientAuthValidator.Struct(&req); err != nil {
h.logger.Warn("测试登录参数校验失败", zap.Error(err))
return errors.New(errors.CodeInvalidParam)
}
token, customerID, isNewUser, err := h.service.DevLogin(c.UserContext(), req.Identifier)
if err != nil {
return err
}
return response.Success(c, dto.DevLoginResponse{
Token: token,
CustomerID: customerID,
IsNewUser: isNewUser,
})
}
// Logout A7 退出登录
// POST /api/c/v1/auth/logout
func (h *ClientAuthHandler) Logout(c *fiber.Ctx) error {
customerID, ok := middleware.GetCustomerID(c)
if !ok || customerID == 0 {
return errors.New(errors.CodeUnauthorized)
}
resp, err := h.service.Logout(c.UserContext(), customerID)
if err != nil {
return err
}
return response.Success(c, resp)
}