Files

274 lines
8.3 KiB
Go
Raw Permalink Normal View History

2025-11-17 14:11:46 +08:00
package handler
import (
"dianshang/internal/service"
"dianshang/pkg/logger"
"dianshang/pkg/response"
"strconv"
"github.com/gin-gonic/gin"
)
type RefundHandler struct {
refundService *service.RefundService
}
func NewRefundHandler(refundService *service.RefundService) *RefundHandler {
return &RefundHandler{
refundService: refundService,
}
}
// CreateRefund 创建退款申请
// @Summary 创建退款申请
// @Description 用户申请退款
// @Tags 退款管理
// @Accept json
// @Produce json
// @Param request body service.CreateRefundRequest true "退款申请信息"
// @Success 200 {object} response.Response{data=model.Refund}
// @Failure 400 {object} response.Response
// @Router /api/refunds [post]
func (h *RefundHandler) CreateRefund(c *gin.Context) {
var req service.CreateRefundRequest
if err := c.ShouldBindJSON(&req); err != nil {
logger.Error("绑定退款申请参数失败", "error", err)
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "参数错误: "+err.Error())
return
}
// 从上下文获取用户ID假设已通过中间件设置
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, response.ERROR_UNAUTHORIZED)
return
}
req.UserID = userID.(uint)
refund, err := h.refundService.CreateRefund(c.Request.Context(), &req)
if err != nil {
logger.Error("创建退款申请失败", "error", err, "userID", req.UserID, "orderID", req.OrderID)
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
logger.Info("退款申请创建成功", "refundID", refund.ID, "userID", req.UserID)
response.Success(c, refund)
}
// GetRefundsByOrder 获取订单的退款记录
// @Summary 获取订单的退款记录
// @Description 用户获取指定订单的所有退款记录
// @Tags 退款管理
// @Accept json
// @Produce json
// @Param order_id path int true "订单ID"
// @Success 200 {object} response.Response{data=[]model.Refund}
// @Failure 400 {object} response.Response
// @Router /api/orders/{order_id}/refunds [get]
func (h *RefundHandler) GetRefundsByOrder(c *gin.Context) {
orderIDStr := c.Param("order_id")
orderID, err := strconv.ParseUint(orderIDStr, 10, 32)
if err != nil {
response.Error(c, response.ERROR_INVALID_PARAMS)
return
}
// 从上下文获取用户ID
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, response.ERROR_UNAUTHORIZED)
return
}
refunds, err := h.refundService.GetRefundsByOrderID(c.Request.Context(), uint(orderID), userID.(uint))
if err != nil {
logger.Error("获取订单退款记录失败", "error", err, "orderID", orderID, "userID", userID)
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, refunds)
}
// GetUserRefunds 获取用户的退款记录
// @Summary 获取用户的退款记录
// @Description 用户获取自己的所有退款记录(分页)
// @Tags 退款管理
// @Accept json
// @Produce json
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(10)
// @Param status query int false "退款状态筛选"
// @Success 200 {object} response.Response{data=response.PageResponse{list=[]model.Refund}}
// @Failure 400 {object} response.Response
// @Router /api/user/refunds [get]
func (h *RefundHandler) GetUserRefunds(c *gin.Context) {
// 获取分页参数
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 10
}
// 从上下文获取用户ID
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, response.ERROR_UNAUTHORIZED)
return
}
refunds, total, err := h.refundService.GetRefundsByUserID(c.Request.Context(), userID.(uint), page, pageSize)
if err != nil {
logger.Error("获取用户退款记录失败", "error", err, "userID", userID)
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Page(c, refunds, total, page, pageSize)
}
// GetRefundDetail 获取退款详情
// @Summary 获取退款详情
// @Description 用户获取指定退款记录的详细信息
// @Tags 退款管理
// @Accept json
// @Produce json
// @Param refund_id path int true "退款ID"
// @Success 200 {object} response.Response{data=model.Refund}
// @Failure 400 {object} response.Response
// @Router /api/refunds/{refund_id} [get]
func (h *RefundHandler) GetRefundDetail(c *gin.Context) {
refundIDStr := c.Param("id")
refundID, err := strconv.ParseUint(refundIDStr, 10, 32)
if err != nil {
response.Error(c, response.ERROR_INVALID_PARAMS)
return
}
// 从上下文获取用户ID
userID, exists := c.Get("user_id")
if !exists {
response.Error(c, response.ERROR_UNAUTHORIZED)
return
}
refund, err := h.refundService.GetRefundByID(c.Request.Context(), uint(refundID), userID.(uint))
if err != nil {
logger.Error("获取退款详情失败", "error", err, "refundID", refundID, "userID", userID)
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
response.Success(c, refund)
}
// QueryRefundStatus 查询退款状态
// @Summary 查询退款状态
// @Description 用户主动查询退款状态
// @Tags 退款管理
// @Accept json
// @Produce json
// @Param refund_id path int true "退款ID"
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /api/refunds/{refund_id}/query [post]
func (h *RefundHandler) QueryRefundStatus(c *gin.Context) {
refundIDStr := c.Param("id")
refundID, err := strconv.ParseUint(refundIDStr, 10, 32)
if err != nil {
response.Error(c, response.ERROR_INVALID_PARAMS)
return
}
err = h.refundService.QueryRefundStatus(c.Request.Context(), uint(refundID))
if err != nil {
logger.Error("查询退款状态失败", "error", err, "refundID", refundID)
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
logger.Info("查询退款状态成功", "refundID", refundID)
response.Success(c, "查询完成")
}
// SyncRefundAndOrderStatus 同步退款状态和订单状态
// @Summary 同步退款状态和订单状态
// @Description 修复退款状态已成功但订单状态未更新的问题
// @Tags 退款管理
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /api/admin/refunds/sync-status [post]
func (h *RefundHandler) SyncRefundAndOrderStatus(c *gin.Context) {
err := h.refundService.SyncRefundAndOrderStatus(c.Request.Context())
if err != nil {
logger.Error("同步退款状态和订单状态失败", "error", err)
response.ErrorWithMessage(c, response.ERROR, err.Error())
return
}
logger.Info("同步退款状态和订单状态成功")
response.Success(c, "同步完成")
}
// RefundCallback 微信退款回调
// @Summary 微信退款回调
// @Description 处理微信退款回调通知
// @Tags 退款管理
// @Accept json
// @Produce json
// @Success 200 {object} response.Response
// @Failure 400 {object} response.Response
// @Router /api/refunds/callback [post]
func (h *RefundHandler) RefundCallback(c *gin.Context) {
logger.Info("收到微信退款回调")
// 读取请求体
body, err := c.GetRawData()
if err != nil {
logger.Error("读取退款回调数据失败", "error", err)
response.ErrorWithMessage(c, response.ERROR_INVALID_PARAMS, "读取回调数据失败")
return
}
// 获取请求头
headers := make(map[string]string)
for key, values := range c.Request.Header {
if len(values) > 0 {
headers[key] = values[0]
}
}
logger.Info("退款回调数据", "bodyLength", len(body))
// 处理微信退款回调service层会解析和解密数据
notify, err := h.refundService.HandleWeChatRefundNotify(c.Request.Context(), body, headers)
if err != nil {
logger.Error("处理退款回调失败", "error", err)
response.ErrorWithMessage(c, response.ERROR, "处理回调失败: "+err.Error())
return
}
// 根据回调类型处理
if notify.EventType == "REFUND.SUCCESS" {
// 退款成功,更新退款状态
err = h.refundService.HandleRefundCallback(c.Request.Context(), notify)
if err != nil {
logger.Error("处理退款成功回调失败", "error", err)
response.ErrorWithMessage(c, response.ERROR, "处理退款成功回调失败: "+err.Error())
return
}
}
logger.Info("退款回调处理成功")
response.Success(c, gin.H{
"code": "SUCCESS",
"message": "处理成功",
})
}