package admin import ( "bytes" "strconv" "strings" "github.com/bytedance/sonic" "github.com/go-playground/validator/v10" "github.com/gofiber/fiber/v2" agentrechargeapp "github.com/break/junhong_cmp_fiber/internal/application/agentrecharge" "github.com/break/junhong_cmp_fiber/internal/model/dto" agentrechargequery "github.com/break/junhong_cmp_fiber/internal/query/agentrecharge" agentRechargeSvc "github.com/break/junhong_cmp_fiber/internal/service/agent_recharge" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/break/junhong_cmp_fiber/pkg/errors" "github.com/break/junhong_cmp_fiber/pkg/middleware" "github.com/break/junhong_cmp_fiber/pkg/response" ) // AgentRechargeHandler 代理预充值 Handler type AgentRechargeHandler struct { service *agentRechargeSvc.Service online *agentrechargeapp.OnlineCreationService status *agentrechargequery.PaymentStatusQuery validator *validator.Validate } // SetOnlineCreationService 注入代理在线扫码充值用例。 func (h *AgentRechargeHandler) SetOnlineCreationService(service *agentrechargeapp.OnlineCreationService) { h.online = service } // SetPaymentStatusQuery 注入代理充值本地支付状态 Query。 func (h *AgentRechargeHandler) SetPaymentStatusQuery(query *agentrechargequery.PaymentStatusQuery) { h.status = query } // NewAgentRechargeHandler 创建代理预充值 Handler func NewAgentRechargeHandler(service *agentRechargeSvc.Service, validator *validator.Validate) *AgentRechargeHandler { return &AgentRechargeHandler{service: service, validator: validator} } // Create 创建代理充值订单 // POST /api/admin/agent-recharges func (h *AgentRechargeHandler) Create(c *fiber.Ctx) error { var req dto.CreateAgentRechargeRequest decoder := sonic.ConfigStd.NewDecoder(bytes.NewReader(c.Body())) decoder.DisallowUnknownFields() if err := decoder.Decode(&req); err != nil { return errors.New(errors.CodeInvalidParam, "请求参数解析失败") } if err := h.validator.Struct(&req); err != nil { return errors.New(errors.CodeInvalidParam) } if req.PaymentMethod == constants.RechargeMethodWechat || req.PaymentMethod == constants.RechargeMethodAlipay { return h.createOnline(c, req) } if strings.TrimSpace(req.RequestID) != "" { return errors.New(errors.CodeInvalidParam, "线下充值不能传入在线请求标识") } result, err := h.service.Create(c.UserContext(), &req) if err != nil { return err } return response.Success(c, result) } func (h *AgentRechargeHandler) createOnline(c *fiber.Ctx, req dto.CreateAgentRechargeRequest) error { if h.online == nil { return errors.New(errors.CodeServiceUnavailable, "代理在线充值能力未配置") } if req.ShopID != nil || len(req.PaymentVoucherKey) > 0 || strings.TrimSpace(req.Remark) != "" { return errors.New(errors.CodeInvalidParam, "在线充值不能指定店铺、支付凭证或运营备注") } result, err := h.online.Execute(c.UserContext(), agentrechargeapp.CreateOnlineCommand{ AccountID: middleware.GetUserIDFromContext(c.UserContext()), UserType: middleware.GetUserTypeFromContext(c.UserContext()), CurrentShopID: middleware.GetShopIDFromContext(c.UserContext()), Amount: req.Amount, PaymentMethod: req.PaymentMethod, RequestID: req.RequestID, PayerClientIP: c.IP(), }) if err != nil { return err } rechargeSource, rechargeSourceName := constants.GetAgentRechargeSource(result.Payment.PaymentMethod) return response.Success(c, &dto.AgentRechargeOnlineResponse{ RechargeID: result.Recharge.ID, RechargeNo: result.Recharge.RechargeNo, PaymentNo: result.Payment.PaymentNo, PaymentMethod: result.Payment.PaymentMethod, Amount: result.Payment.Amount, QRContent: result.Payment.QRContent, RechargeSource: rechargeSource, RechargeSourceName: rechargeSourceName, Status: result.Recharge.Status, StatusName: constants.GetRechargeStatusName(result.Recharge.Status), }) } // PaymentMethods 查询代理在线充值可用支付方式。 // GET /api/admin/agent-recharges/payment-methods func (h *AgentRechargeHandler) PaymentMethods(c *fiber.Ctx) error { if h.online == nil { return errors.New(errors.CodeServiceUnavailable, "代理在线充值能力未配置") } result, err := h.online.AvailablePaymentMethods(c.UserContext(), middleware.GetUserTypeFromContext(c.UserContext())) if err != nil { return err } return response.Success(c, &dto.AgentRechargePaymentMethodsResponse{ Methods: result.Methods, MinAmount: result.MinAmount, MaxAmount: result.MaxAmount, }) } // List 查询代理充值订单列表 // GET /api/admin/agent-recharges func (h *AgentRechargeHandler) List(c *fiber.Ctx) error { var req dto.AgentRechargeListRequest if err := c.QueryParser(&req); err != nil { return errors.New(errors.CodeInvalidParam, "请求参数解析失败") } if err := h.validator.Struct(&req); err != nil { return errors.New(errors.CodeInvalidParam) } list, total, err := h.service.List(c.UserContext(), &req) if err != nil { return err } return response.SuccessWithPagination(c, list, total, req.Page, req.PageSize) } // Get 查询代理充值订单详情 // GET /api/admin/agent-recharges/:id func (h *AgentRechargeHandler) Get(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return errors.New(errors.CodeInvalidParam, "无效的充值记录ID") } result, err := h.service.GetByID(c.UserContext(), uint(id)) if err != nil { return err } return response.Success(c, result) } // TriggerApproval 主动补发历史线下代理充值审批。 // POST /api/admin/agent-recharges/:id/trigger-approval func (h *AgentRechargeHandler) TriggerApproval(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil || id == 0 { return errors.New(errors.CodeInvalidParam, "无效的充值记录ID") } result, err := h.service.TriggerApproval(c.UserContext(), uint(id)) if err != nil { return err } return response.Success(c, result) } // PaymentStatus 查询代理充值本地支付与到账状态。 // GET /api/admin/agent-recharges/:id/payment-status func (h *AgentRechargeHandler) PaymentStatus(c *fiber.Ctx) error { if h.status == nil { return errors.New(errors.CodeServiceUnavailable, "代理充值支付状态查询未配置") } id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil || id == 0 { return errors.New(errors.CodeInvalidParam, "无效的充值记录ID") } result, err := h.status.Get(c.UserContext(), uint(id)) if err != nil { return err } return response.Success(c, result) } // Reject 驳回代理充值订单 // POST /api/admin/agent-recharges/:id/reject func (h *AgentRechargeHandler) Reject(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return errors.New(errors.CodeInvalidParam, "无效的充值记录ID") } var req dto.AgentRechargeRejectRequest if err := c.BodyParser(&req); err != nil { return errors.New(errors.CodeInvalidParam, "请求参数解析失败") } if err := h.validator.Struct(&req); err != nil { return errors.New(errors.CodeInvalidParam) } if err := h.service.Reject(c.UserContext(), uint(id), req.RejectionReason); err != nil { return err } return response.Success(c, nil) } // OfflinePay 确认线下充值 // POST /api/admin/agent-recharges/:id/offline-pay func (h *AgentRechargeHandler) OfflinePay(c *fiber.Ctx) error { id, err := strconv.ParseUint(c.Params("id"), 10, 64) if err != nil { return errors.New(errors.CodeInvalidParam, "无效的充值记录ID") } var req dto.AgentOfflinePayRequest if err := c.BodyParser(&req); err != nil { return errors.New(errors.CodeInvalidParam, "请求参数解析失败") } result, err := h.service.OfflinePay(c.UserContext(), uint(id), &req) if err != nil { return err } return response.Success(c, result) }