package handler import ( "strconv" "strings" "affiliate_dash/internal/middleware" "affiliate_dash/internal/pkg/response" "affiliate_dash/internal/service" "github.com/gin-gonic/gin" ) func (h *MerchantHandler) ListOrders(c *gin.Context) { page, size := pageParams(c) orderSource := strings.TrimSpace(c.Query("order_source")) list, total, err := h.fulfillmentSvc.ListOrders(middleware.GetMerchantID(c), page, size, c.Query("order_status"), orderSource, c.Query("keyword")) if err != nil { if err.Error() == "无效的订单来源" || err.Error() == "无效的订单状态" { response.BadRequest(c, err.Error()) return } response.ServerError(c, err.Error()) return } response.Page(c, list, total, page, size) } // ListPlatformOrders GET /api/platform/orders // // 平台管理员跨商户查看下游订单。merchant_id 查询参数可选:不传表示全部商户。 // 与商户侧 /api/merchant/orders 是两条独立路径——商户侧仍强制单商户隔离, // 这里不依赖 X-Merchant-ID,因此管理员遗留的商户上下文不会影响本接口。 func (h *MerchantHandler) ListPlatformOrders(c *gin.Context) { page, size := pageParams(c) var merchantID *uint if raw := strings.TrimSpace(c.Query("merchant_id")); raw != "" { id, err := strconv.ParseUint(raw, 10, 64) if err != nil || id == 0 { response.BadRequest(c, "商户 ID 无效") return } value := uint(id) merchantID = &value } list, total, err := h.fulfillmentSvc.ListPlatformOrders(merchantID, page, size, c.Query("order_status"), c.Query("order_source"), c.Query("keyword")) if err != nil { if err.Error() == "无效的订单来源" || err.Error() == "无效的订单状态" { response.BadRequest(c, err.Error()) return } response.ServerError(c, err.Error()) return } response.Page(c, list, total, page, size) } type merchantManualOrderReq struct { ClientOrderNo string `json:"client_order_no" binding:"required,max=96"` SKU string `json:"sku" binding:"required,max=96"` Quantity int64 `json:"quantity"` BuyerReference string `json:"buyer_reference" binding:"max=128"` GameAccount string `json:"game_account" binding:"max=128"` Note string `json:"note" binding:"max=512"` } // CreateManualOrder 在商户后台创建真实订单;扣款、库存和回调与开放 API 下单保持一致。 func (h *MerchantHandler) CreateManualOrder(c *gin.Context) { var req merchantManualOrderReq if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误:商户单号与商品必填") return } data := map[string]string{} if gameAccount := strings.TrimSpace(req.GameAccount); gameAccount != "" { data["game_account"] = gameAccount } if note := strings.TrimSpace(req.Note); note != "" { data["manual_note"] = note } result, err := h.fulfillmentSvc.CreateManualOrder(service.CreateManualOrderInput{ MerchantID: middleware.GetMerchantID(c), ActorUserID: middleware.GetUserID(c), ClientOrderNo: req.ClientOrderNo, SKU: req.SKU, Quantity: req.Quantity, BuyerReference: req.BuyerReference, RequestData: data, }) if err != nil { response.BadRequest(c, err.Error()) return } canShip, cannotShipReason := service.CanFulfill(result.Order) response.OK(c, gin.H{ "order": result.Order, "idempotent": result.Idempotent, "can_ship": canShip, "cannot_ship_reason": cannotShipReason, }) } type merchantTestOrderReq struct { SKU string `json:"sku" binding:"required"` BuyerReference string `json:"buyer_reference"` Note string `json:"note"` OrderStatus string `json:"order_status"` } func (h *MerchantHandler) CreateTestOrder(c *gin.Context) { var req merchantTestOrderReq if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误:sku 必填") return } order, err := h.fulfillmentSvc.CreateTestOrder(service.CreateTestOrderInput{ MerchantID: middleware.GetMerchantID(c), ActorUserID: middleware.GetUserID(c), SKU: req.SKU, BuyerReference: req.BuyerReference, Note: req.Note, OrderStatus: req.OrderStatus, }) if err != nil { response.BadRequest(c, err.Error()) return } canShip, cannotShipReason := service.CanFulfill(order) response.OK(c, gin.H{ "order": order, "can_ship": canShip, "cannot_ship_reason": cannotShipReason, }) } type merchantCancelOrderReq struct { Reason string `json:"reason" binding:"required,max=512"` } // CancelOrder 商户后台取消订单:全额退还积分并回补库存,取消后订单不可再发货。 func (h *MerchantHandler) CancelOrder(c *gin.Context) { var req merchantCancelOrderReq if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "参数错误:取消原因必填且最长 512 字") return } order, err := h.fulfillmentSvc.CancelOrderByUser(middleware.GetMerchantID(c), middleware.GetUserID(c), c.Param("order_no"), req.Reason) if err != nil { response.BadRequest(c, err.Error()) return } response.OK(c, gin.H{ "order": order, "refund_amount": order.Amount, }) } func (h *MerchantHandler) GetDeliveryLink(c *gin.Context) { link, err := h.deliverySvc.GetOrCreateDeliveryLink(middleware.GetMerchantID(c), c.Param("order_no"), requestBaseURL(c)) if err != nil { writeDeliveryError(c, err) return } response.OK(c, link) } func (h *MerchantHandler) RevokeDeliveryLink(c *gin.Context) { if err := h.deliverySvc.RevokeDeliveryLink(middleware.GetMerchantID(c), middleware.GetUserID(c), c.Param("order_no")); err != nil { writeDeliveryError(c, err) return } response.OK(c, nil) } func (h *MerchantHandler) RestoreDeliveryLink(c *gin.Context) { link, err := h.deliverySvc.RestoreDeliveryLink(middleware.GetMerchantID(c), middleware.GetUserID(c), c.Param("order_no"), requestBaseURL(c)) if err != nil { writeDeliveryError(c, err) return } response.OK(c, link) }