Files
2025-11-17 13:32:54 +08:00

274 lines
8.3 KiB
Go
Raw Permalink 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 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": "处理成功",
})
}