Files
junhong_cmp_fiber/internal/routes/personal.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

281 lines
10 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package routes
import (
"github.com/gofiber/fiber/v2"
"github.com/break/junhong_cmp_fiber/internal/bootstrap"
apphandler "github.com/break/junhong_cmp_fiber/internal/handler/app"
"github.com/break/junhong_cmp_fiber/internal/middleware"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
"github.com/break/junhong_cmp_fiber/pkg/config"
"github.com/break/junhong_cmp_fiber/pkg/openapi"
)
// RegisterPersonalCustomerRoutes 注册个人客户路由
// 路由挂载在 /api/c/v1 下
//
// 重要Fiber 的 Group.Use() 会在路由表中注册全局 USE 处理器,
// 匹配该前缀下的所有请求(不区分 Group 对象)。
// 因此公开路由必须在任何 Use() 调用之前注册,利用 Fiber 按注册顺序匹配的机制,
// 确保公开路由优先命中并直接返回,不会被后续的认证中间件拦截。
func RegisterPersonalCustomerRoutes(router fiber.Router, doc *openapi.Generator, basePath string, handlers *bootstrap.Handlers, personalAuthMiddleware *middleware.PersonalAuthMiddleware) {
authBasePath := "/auth"
// === 公开路由(无需认证)===
Register(router, doc, basePath, "POST", authBasePath+"/verify-asset", handlers.ClientAuth.VerifyAsset, RouteSpec{
Summary: "资产验证",
Tags: []string{"个人客户 - 认证"},
Auth: false,
Input: &dto.VerifyAssetRequest{},
Output: &dto.VerifyAssetResponse{},
})
Register(router, doc, basePath, "POST", authBasePath+"/wechat-login", handlers.ClientAuth.WechatLogin, RouteSpec{
Summary: "公众号登录",
Tags: []string{"个人客户 - 认证"},
Auth: false,
Input: &dto.WechatLoginRequest{},
Output: &dto.WechatLoginResponse{},
})
Register(router, doc, basePath, "POST", authBasePath+"/miniapp-login", handlers.ClientAuth.MiniappLogin, RouteSpec{
Summary: "小程序登录",
Tags: []string{"个人客户 - 认证"},
Auth: false,
Input: &dto.MiniappLoginRequest{},
Output: &dto.WechatLoginResponse{},
})
Register(router, doc, basePath, "POST", authBasePath+"/send-code", handlers.ClientAuth.SendCode, RouteSpec{
Summary: "发送验证码",
Tags: []string{"个人客户 - 认证"},
Auth: false,
Input: &dto.ClientSendCodeRequest{},
Output: &dto.ClientSendCodeResponse{},
})
// 开发模式测试登录接口(仅 logging.development=true 时注册)
if config.Get().Logging.Development {
Register(router, doc, basePath, "POST", authBasePath+"/dev-login", handlers.ClientAuth.DevLogin, RouteSpec{
Summary: "开发环境测试登录",
Description: "⚠️ 仅开发模式可用。传入资产标识符ICCID等自动绑定测试客户并签发 JWT用于接口测试。",
Tags: []string{"个人客户 - 认证"},
Auth: false,
Input: &dto.DevLoginRequest{},
Output: &dto.DevLoginResponse{},
})
}
// === 需要认证的 auth 路由 ===
authProtectedGroup := router.Group(authBasePath)
authProtectedGroup.Use(personalAuthMiddleware.Authenticate())
Register(authProtectedGroup, doc, basePath+authBasePath, "POST", "/bind-phone", handlers.ClientAuth.BindPhone, RouteSpec{
Summary: "绑定手机号",
Tags: []string{"个人客户 - 认证"},
Auth: true,
Input: &dto.BindPhoneRequest{},
Output: &dto.BindPhoneResponse{},
})
Register(authProtectedGroup, doc, basePath+authBasePath, "POST", "/change-phone", handlers.ClientAuth.ChangePhone, RouteSpec{
Summary: "更换手机号",
Tags: []string{"个人客户 - 认证"},
Auth: true,
Input: &dto.ChangePhoneRequest{},
Output: &dto.ChangePhoneResponse{},
})
Register(authProtectedGroup, doc, basePath+authBasePath, "POST", "/logout", handlers.ClientAuth.Logout, RouteSpec{
Summary: "退出登录",
Tags: []string{"个人客户 - 认证"},
Auth: true,
Input: nil,
Output: &dto.LogoutResponse{},
})
// 需要认证的路由
authGroup := router.Group("")
authGroup.Use(personalAuthMiddleware.Authenticate())
// 获取个人资料
Register(authGroup, doc, basePath, "GET", "/profile", handlers.PersonalCustomer.GetProfile, RouteSpec{
Summary: "获取个人资料",
Description: "获取当前登录客户的个人资料",
Tags: []string{"个人客户 - 账户"},
Auth: true,
Input: nil,
Output: &apphandler.PersonalCustomerDTO{},
})
// 更新个人资料
Register(authGroup, doc, basePath, "PUT", "/profile", handlers.PersonalCustomer.UpdateProfile, RouteSpec{
Summary: "更新个人资料",
Description: "更新当前登录客户的昵称和头像",
Tags: []string{"个人客户 - 账户"},
Auth: true,
Input: &apphandler.UpdateProfileRequest{},
Output: nil,
})
Register(authGroup, doc, basePath, "GET", "/asset/info", handlers.ClientAsset.GetAssetInfo, RouteSpec{
Summary: "资产信息",
Tags: []string{"个人客户 - 资产"},
Auth: true,
Input: &dto.AssetInfoRequest{},
Output: &dto.AssetInfoResponse{},
})
Register(authGroup, doc, basePath, "GET", "/asset/packages", handlers.ClientAsset.GetAvailablePackages, RouteSpec{
Summary: "资产可购套餐列表",
Tags: []string{"个人客户 - 资产"},
Auth: true,
Input: &dto.AssetPackageListRequest{},
Output: &dto.AssetPackageListResponse{},
})
Register(authGroup, doc, basePath, "GET", "/asset/package-history", handlers.ClientAsset.GetPackageHistory, RouteSpec{
Summary: "资产套餐历史",
Tags: []string{"个人客户 - 资产"},
Auth: true,
Input: &dto.AssetPackageHistoryRequest{},
Output: &dto.AssetPackageHistoryResponse{},
})
Register(authGroup, doc, basePath, "POST", "/asset/refresh", handlers.ClientAsset.RefreshAsset, RouteSpec{
Summary: "资产刷新",
Tags: []string{"个人客户 - 资产"},
Auth: true,
Input: &dto.AssetRefreshRequest{},
Output: &dto.AssetRefreshResponse{},
})
Register(authGroup, doc, basePath, "GET", "/wallet/detail", handlers.ClientWallet.GetWalletDetail, RouteSpec{
Summary: "钱包详情",
Tags: []string{"个人客户 - 钱包"},
Auth: true,
Input: &dto.WalletDetailRequest{},
Output: &dto.WalletDetailResponse{},
})
Register(authGroup, doc, basePath, "GET", "/wallet/transactions", handlers.ClientWallet.GetWalletTransactions, RouteSpec{
Summary: "钱包流水列表",
Tags: []string{"个人客户 - 钱包"},
Auth: true,
Input: &dto.WalletTransactionListRequest{},
Output: &dto.WalletTransactionListResponse{},
})
Register(authGroup, doc, basePath, "GET", "/wallet/recharge-check", handlers.ClientWallet.GetRechargeCheck, RouteSpec{
Summary: "充值前校验",
Tags: []string{"个人客户 - 钱包"},
Auth: true,
Input: &dto.ClientRechargeCheckRequest{},
Output: &dto.ClientRechargeCheckResponse{},
})
Register(authGroup, doc, basePath, "POST", "/wallet/recharge", handlers.ClientWallet.CreateRecharge, RouteSpec{
Summary: "创建充值订单",
Tags: []string{"个人客户 - 钱包"},
Auth: true,
Input: &dto.ClientCreateRechargeRequest{},
Output: &dto.ClientRechargeResponse{},
})
Register(authGroup, doc, basePath, "GET", "/wallet/recharges", handlers.ClientWallet.GetRechargeList, RouteSpec{
Summary: "充值记录列表",
Tags: []string{"个人客户 - 钱包"},
Auth: true,
Input: &dto.ClientRechargeListRequest{},
Output: &dto.ClientRechargeListResponse{},
})
Register(authGroup, doc, basePath, "POST", "/orders/create", handlers.ClientOrder.CreateOrder, RouteSpec{
Summary: "创建订单",
Tags: []string{"个人客户 - 订单"},
Auth: true,
Input: &dto.ClientCreateOrderRequest{},
Output: &dto.ClientCreateOrderResponse{},
})
Register(authGroup, doc, basePath, "GET", "/orders", handlers.ClientOrder.ListOrders, RouteSpec{
Summary: "订单列表",
Tags: []string{"个人客户 - 订单"},
Auth: true,
Input: &dto.ClientOrderListRequest{},
Output: &dto.ClientOrderListResponse{},
})
Register(authGroup, doc, basePath, "GET", "/orders/:id", handlers.ClientOrder.GetOrderDetail, RouteSpec{
Summary: "订单详情",
Tags: []string{"个人客户 - 订单"},
Auth: true,
Input: &dto.IDReq{},
Output: &dto.ClientOrderDetailResponse{},
})
Register(authGroup, doc, basePath, "GET", "/exchange/pending", handlers.ClientExchange.GetPending, RouteSpec{
Summary: "查询待处理换货单",
Tags: []string{"个人客户 - 换货"},
Auth: true,
Input: &dto.ClientExchangePendingRequest{},
Output: &dto.ClientExchangePendingResponse{},
})
Register(authGroup, doc, basePath, "POST", "/exchange/:id/shipping-info", handlers.ClientExchange.SubmitShippingInfo, RouteSpec{
Summary: "提交收货信息",
Tags: []string{"个人客户 - 换货"},
Auth: true,
Input: &dto.ClientShippingInfoParams{},
Output: nil,
})
Register(authGroup, doc, basePath, "GET", "/realname/link", handlers.ClientRealname.GetRealnameLink, RouteSpec{
Summary: "获取实名认证链接",
Tags: []string{"个人客户 - 实名"},
Auth: true,
Input: &dto.RealnimeLinkRequest{},
Output: &dto.RealnimeLinkResponse{},
})
Register(authGroup, doc, basePath, "GET", "/device/cards", handlers.ClientDevice.GetDeviceCards, RouteSpec{
Summary: "获取设备卡列表",
Tags: []string{"个人客户 - 设备"},
Auth: true,
Input: &dto.DeviceCardListRequest{},
Output: &dto.DeviceCardListResponse{},
})
Register(authGroup, doc, basePath, "POST", "/device/reboot", handlers.ClientDevice.RebootDevice, RouteSpec{
Summary: "设备重启",
Tags: []string{"个人客户 - 设备"},
Auth: true,
Input: &dto.DeviceRebootRequest{},
Output: &dto.DeviceOperationResponse{},
})
Register(authGroup, doc, basePath, "POST", "/device/factory-reset", handlers.ClientDevice.FactoryResetDevice, RouteSpec{
Summary: "恢复出厂设置",
Tags: []string{"个人客户 - 设备"},
Auth: true,
Input: &dto.DeviceFactoryResetRequest{},
Output: &dto.DeviceOperationResponse{},
})
Register(authGroup, doc, basePath, "POST", "/device/wifi", handlers.ClientDevice.SetWiFi, RouteSpec{
Summary: "设备WiFi配置",
Tags: []string{"个人客户 - 设备"},
Auth: true,
Input: &dto.DeviceWifiRequest{},
Output: &dto.DeviceOperationResponse{},
})
Register(authGroup, doc, basePath, "POST", "/device/switch-card", handlers.ClientDevice.SwitchCard, RouteSpec{
Summary: "设备切卡",
Tags: []string{"个人客户 - 设备"},
Auth: true,
Input: &dto.DeviceSwitchCardRequest{},
Output: &dto.DeviceSwitchCardResponse{},
})
}