feat(h5): 新增充值订单处理器和 DTO

- 实现 RechargeHandler 处理充值订单创建、预检、查询等接口
- 添加充值相关 DTO(CreateRechargeRequest、RechargeCheckRequest 等)
- 支持充值预检(强充检查、金额限制等)
- 支持充值订单列表和详情查询
This commit is contained in:
2026-01-31 12:14:59 +08:00
parent 001eb81e5e
commit 760b3db1df
2 changed files with 174 additions and 0 deletions

View File

@@ -0,0 +1,169 @@
package h5
import (
"strconv"
"github.com/gofiber/fiber/v2"
"github.com/break/junhong_cmp_fiber/internal/model/dto"
rechargeService "github.com/break/junhong_cmp_fiber/internal/service/recharge"
"github.com/break/junhong_cmp_fiber/pkg/errors"
"github.com/break/junhong_cmp_fiber/pkg/middleware"
"github.com/break/junhong_cmp_fiber/pkg/response"
)
// RechargeHandler 充值订单处理器
// 提供充值订单的创建、预检、查询等接口
type RechargeHandler struct {
service *rechargeService.Service
}
// NewRechargeHandler 创建充值订单处理器实例
// 参数:
// - service: 充值服务
//
// 返回:
// - *RechargeHandler: 充值订单处理器实例
func NewRechargeHandler(service *rechargeService.Service) *RechargeHandler {
return &RechargeHandler{service: service}
}
// Create 创建充值订单
// POST /api/h5/wallets/recharge
// 请求参数:
// - resource_type: 资源类型iot_card/device
// - resource_id: 资源ID卡ID或设备ID
// - amount: 充值金额(分)
// - payment_method: 支付方式wechat/alipay
//
// 响应:
// - 成功: 返回充值订单信息订单ID、订单号、金额、状态等
// - 失败: 返回错误信息
func (h *RechargeHandler) Create(c *fiber.Ctx) error {
var req dto.CreateRechargeRequest
if err := c.BodyParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
}
ctx := c.UserContext()
// 获取个人客户ID作为用户ID
userID := middleware.GetCustomerIDFromContext(ctx)
if userID == 0 {
return errors.New(errors.CodeUnauthorized, "用户未登录")
}
result, err := h.service.Create(ctx, &req, userID)
if err != nil {
return err
}
return response.Success(c, result)
}
// RechargeCheck 充值预检
// GET /api/h5/wallets/recharge-check
// 请求参数:
// - resource_type: 资源类型iot_card/device
// - resource_id: 资源ID卡ID或设备ID
//
// 响应:
// - 成功: 返回预检信息(是否需要强充、强充金额、最小/最大充值金额等)
// - 失败: 返回错误信息
func (h *RechargeHandler) RechargeCheck(c *fiber.Ctx) error {
var req dto.RechargeCheckRequest
if err := c.QueryParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
}
// 验证必填参数
if req.ResourceType == "" {
return errors.New(errors.CodeInvalidParam, "资源类型不能为空")
}
if req.ResourceID == 0 {
return errors.New(errors.CodeInvalidParam, "资源ID不能为空")
}
ctx := c.UserContext()
result, err := h.service.GetRechargeCheck(ctx, req.ResourceType, req.ResourceID)
if err != nil {
return err
}
// 转换为 DTO 响应
resp := &dto.RechargeCheckResponse{
NeedForceRecharge: result.NeedForceRecharge,
ForceRechargeAmount: result.ForceRechargeAmount,
TriggerType: result.TriggerType,
MinAmount: result.MinAmount,
MaxAmount: result.MaxAmount,
CurrentAccumulated: result.CurrentAccumulated,
Threshold: result.Threshold,
Message: result.Message,
FirstCommissionPaid: result.FirstCommissionPaid,
}
return response.Success(c, resp)
}
// List 查询充值订单列表
// GET /api/h5/wallets/recharges
// 请求参数:
// - page: 页码从1开始默认1
// - page_size: 每页数量默认20最大100
// - wallet_id: 钱包ID筛选可选
// - status: 状态筛选可选1-待支付 2-已支付 3-已完成 4-已关闭 5-已退款)
// - start_time: 开始时间筛选(可选)
// - end_time: 结束时间筛选(可选)
//
// 响应:
// - 成功: 返回充值订单列表(分页数据、总记录数、总页数)
// - 失败: 返回错误信息
func (h *RechargeHandler) List(c *fiber.Ctx) error {
var req dto.RechargeListRequest
if err := c.QueryParser(&req); err != nil {
return errors.New(errors.CodeInvalidParam, "请求参数解析失败")
}
ctx := c.UserContext()
// 获取个人客户ID作为用户ID
userID := middleware.GetCustomerIDFromContext(ctx)
if userID == 0 {
return errors.New(errors.CodeUnauthorized, "用户未登录")
}
result, err := h.service.List(ctx, &req, userID)
if err != nil {
return err
}
return response.Success(c, result)
}
// Get 查询充值订单详情
// GET /api/h5/wallets/recharges/:id
// 路径参数:
// - id: 充值订单ID
//
// 响应:
// - 成功: 返回充值订单详情订单ID、订单号、金额、状态、支付信息等
// - 失败: 返回错误信息
func (h *RechargeHandler) Get(c *fiber.Ctx) error {
id, err := strconv.ParseUint(c.Params("id"), 10, 64)
if err != nil {
return errors.New(errors.CodeInvalidParam, "无效的充值订单ID")
}
ctx := c.UserContext()
// 获取个人客户ID作为用户ID
userID := middleware.GetCustomerIDFromContext(ctx)
if userID == 0 {
return errors.New(errors.CodeUnauthorized, "用户未登录")
}
result, err := h.service.GetByID(ctx, uint(id), userID)
if err != nil {
return err
}
return response.Success(c, result)
}

View File

@@ -105,3 +105,8 @@ type RechargeCheckResponse struct {
// 一次性佣金是否已发放
FirstCommissionPaid bool `json:"first_commission_paid" description:"一次性佣金是否已发放"`
}
// GetRechargeRequest 获取充值订单详情请求
type GetRechargeRequest struct {
ID uint `path:"id" description:"充值订单ID" required:"true"`
}