package app import ( "fmt" "net/http" "time" "bindbox-game/internal/code" "bindbox-game/internal/pkg/core" "bindbox-game/internal/pkg/validation" "bindbox-game/internal/repository/mysql/model" ) const ( shippingFeeThreshold = 5 // 超过此件数收运费 shippingFeeCents = 1000 // 运费金额(分),10 元 shippingFeeSourceType = int32(5) // orders.source_type: 5 = 运费订单 ) type shippingFeePreorderRequest struct { InventoryIDs []int64 `json:"inventory_ids"` } type shippingFeePreorderResponse struct { OrderNo string `json:"order_no"` } // ShippingFeePreorder 创建运费订单 // @Summary 创建运费订单 // @Description 选中件数超过 5 件时,创建 10 元运费订单并返回 order_no;前端再调用 /pay/wechat/jsapi/preorder 发起支付 // @Tags APP端.用户 // @Accept json // @Produce json // @Security LoginVerifyToken // @Param user_id path integer true "用户ID" // @Param RequestBody body shippingFeePreorderRequest true "请求参数:资产ID列表" // @Success 200 {object} shippingFeePreorderResponse // @Failure 400 {object} code.Failure // @Router /api/app/users/{user_id}/inventory/shipping-fee/preorder [post] func (h *handler) ShippingFeePreorder() core.HandlerFunc { return func(ctx core.Context) { req := new(shippingFeePreorderRequest) rsp := new(shippingFeePreorderResponse) if err := ctx.ShouldBindJSON(req); err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) return } if len(req.InventoryIDs) == 0 { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "inventory_ids 不能为空")) return } if len(req.InventoryIDs) <= shippingFeeThreshold { ctx.AbortWithError(core.Error(http.StatusBadRequest, 150001, fmt.Sprintf("件数不超过 %d 件,无需支付运费", shippingFeeThreshold))) return } userID := int64(ctx.SessionUserInfo().Id) // 生成运费订单号(SF + 时间戳 + 用户ID后6位,保证唯一) now := time.Now() orderNo := fmt.Sprintf("SF%s%06d", now.Format("20060102150405"), userID%1000000) // 创建运费订单(source_type=5 区分普通商品订单,status=1 待支付) order := &model.Orders{ UserID: userID, OrderNo: orderNo, SourceType: shippingFeeSourceType, TotalAmount: shippingFeeCents, DiscountAmount: 0, PointsAmount: 0, ActualAmount: shippingFeeCents, Status: 1, IsConsumed: 0, } if err := h.writeDB.Orders.WithContext(ctx.RequestContext()). Omit(h.writeDB.Orders.PaidAt, h.writeDB.Orders.CancelledAt). Create(order); err != nil { ctx.AbortWithError(core.Error(http.StatusBadRequest, 150002, "创建运费订单失败: "+err.Error())) return } rsp.OrderNo = orderNo ctx.Payload(rsp) } }