feat(order): add validation for quantity and amount limits in order requests
This commit is contained in:
parent
1995987f00
commit
701d47ed21
@ -14,14 +14,14 @@ type (
|
||||
CreateOrderRequest {
|
||||
UserId int64 `json:"user_id" validate:"required"`
|
||||
Type uint8 `json:"type" validate:"required"`
|
||||
Quantity int64 `json:"quantity,omitempty"`
|
||||
Price int64 `json:"price" validate:"required"`
|
||||
Amount int64 `json:"amount" validate:"required"`
|
||||
Discount int64 `json:"discount,omitempty"`
|
||||
Quantity int64 `json:"quantity,omitempty" validate:"omitempty,lte=1000"`
|
||||
Price int64 `json:"price" validate:"required,gte=0,lte=2000000000"`
|
||||
Amount int64 `json:"amount" validate:"required,gte=0,lte=2147483647"`
|
||||
Discount int64 `json:"discount,omitempty" validate:"omitempty,gte=0,lte=2000000000"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
CouponDiscount int64 `json:"coupon_discount,omitempty"`
|
||||
Commission int64 `json:"commission"`
|
||||
FeeAmount int64 `json:"fee_amount" validate:"required"`
|
||||
CouponDiscount int64 `json:"coupon_discount,omitempty" validate:"omitempty,gte=0,lte=2000000000"`
|
||||
Commission int64 `json:"commission" validate:"gte=0,lte=2000000000"`
|
||||
FeeAmount int64 `json:"fee_amount" validate:"required,gte=0,lte=2000000000"`
|
||||
PaymentId int64 `json:"payment_id" validate:"required"`
|
||||
TradeNo string `json:"trade_no,omitempty"`
|
||||
Status uint8 `json:"status,omitempty"`
|
||||
|
||||
@ -580,7 +580,7 @@ type (
|
||||
//public order
|
||||
PurchaseOrderRequest {
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Quantity int64 `json:"quantity" validate:"required,gt=0"`
|
||||
Quantity int64 `json:"quantity" validate:"required,gt=0,lte=1000"`
|
||||
Payment int64 `json:"payment,omitempty"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
}
|
||||
@ -598,7 +598,7 @@ type (
|
||||
}
|
||||
RenewalOrderRequest {
|
||||
UserSubscribeID int64 `json:"user_subscribe_id"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
Quantity int64 `json:"quantity" validate:"lte=1000"`
|
||||
Payment int64 `json:"payment"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
}
|
||||
@ -613,7 +613,7 @@ type (
|
||||
OrderNo string `json:"order_no"`
|
||||
}
|
||||
RechargeOrderRequest {
|
||||
Amount int64 `json:"amount"`
|
||||
Amount int64 `json:"amount" validate:"required,gt=0,lte=2000000000"`
|
||||
Payment int64 `json:"payment"`
|
||||
}
|
||||
RechargeOrderResponse {
|
||||
|
||||
@ -888,10 +888,10 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
|
||||
serverGroupRouter.GET("/user", server.GetServerUserListHandler(serverCtx))
|
||||
}
|
||||
|
||||
serverV2GroupRouter := router.Group("/v2/server")
|
||||
serverGroupRouter := router.Group("/v2/server")
|
||||
|
||||
{
|
||||
// Get Server Protocol Config
|
||||
serverV2GroupRouter.GET("/:server_id", server.QueryServerProtocolConfigHandler(serverCtx))
|
||||
serverGroupRouter.GET("/:server_id", server.QueryServerProtocolConfigHandler(serverCtx))
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,4 +6,9 @@ const (
|
||||
StripeAlipay = "stripe_alipay"
|
||||
StripeWeChatPay = "stripe_wechat_pay"
|
||||
Balance = "balance"
|
||||
|
||||
// MaxOrderAmount Order amount limits
|
||||
MaxOrderAmount = 2147483647 // int32 max value (2.1 billion)
|
||||
MaxRechargeAmount = 2000000000 // 2 billion, slightly lower for safety
|
||||
MaxQuantity = 1000 // Maximum quantity per order
|
||||
)
|
||||
|
||||
@ -58,6 +58,12 @@ func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.P
|
||||
req.Quantity = 1
|
||||
}
|
||||
|
||||
// Validate quantity limit
|
||||
if req.Quantity > MaxQuantity {
|
||||
l.Errorw("[Purchase] Quantity exceeds maximum limit", logger.Field("quantity", req.Quantity), logger.Field("max", MaxQuantity))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "quantity exceeds maximum limit of %d", MaxQuantity)
|
||||
}
|
||||
|
||||
// find user subscription
|
||||
userSub, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, u.Id)
|
||||
if err != nil {
|
||||
@ -110,6 +116,17 @@ func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.P
|
||||
// discount amount
|
||||
amount := int64(float64(price) * discount)
|
||||
discountAmount := price - amount
|
||||
|
||||
// Validate amount to prevent overflow
|
||||
if amount > MaxOrderAmount {
|
||||
l.Errorw("[Purchase] Order amount exceeds maximum limit",
|
||||
logger.Field("amount", amount),
|
||||
logger.Field("max", MaxOrderAmount),
|
||||
logger.Field("user_id", u.Id),
|
||||
logger.Field("subscribe_id", req.SubscribeId))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "order amount exceeds maximum limit")
|
||||
}
|
||||
|
||||
var coupon int64 = 0
|
||||
// Calculate the coupon deduction
|
||||
if req.Coupon != "" {
|
||||
@ -167,6 +184,15 @@ func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.P
|
||||
if amount > 0 {
|
||||
feeAmount = calculateFee(amount, payment)
|
||||
amount += feeAmount
|
||||
|
||||
// Final validation after adding fee
|
||||
if amount > MaxOrderAmount {
|
||||
l.Errorw("[Purchase] Final order amount exceeds maximum limit after fee",
|
||||
logger.Field("amount", amount),
|
||||
logger.Field("max", MaxOrderAmount),
|
||||
logger.Field("user_id", u.Id))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "order amount exceeds maximum limit")
|
||||
}
|
||||
}
|
||||
// query user is new purchase or renewal
|
||||
isNew, err := l.svcCtx.OrderModel.IsUserEligibleForNewOrder(l.ctx, u.Id)
|
||||
|
||||
@ -40,6 +40,21 @@ func (l *RechargeLogic) Recharge(req *types.RechargeOrderRequest) (resp *types.R
|
||||
logger.Error("current user is not found in context")
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
||||
}
|
||||
|
||||
// Validate recharge amount
|
||||
if req.Amount <= 0 {
|
||||
l.Errorw("[Recharge] Invalid recharge amount", logger.Field("amount", req.Amount), logger.Field("user_id", u.Id))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "recharge amount must be greater than 0")
|
||||
}
|
||||
|
||||
if req.Amount > MaxRechargeAmount {
|
||||
l.Errorw("[Recharge] Recharge amount exceeds maximum limit",
|
||||
logger.Field("amount", req.Amount),
|
||||
logger.Field("max", MaxRechargeAmount),
|
||||
logger.Field("user_id", u.Id))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "recharge amount exceeds maximum limit")
|
||||
}
|
||||
|
||||
// find payment method
|
||||
payment, err := l.svcCtx.PaymentModel.FindOne(l.ctx, req.Payment)
|
||||
if err != nil {
|
||||
@ -48,6 +63,17 @@ func (l *RechargeLogic) Recharge(req *types.RechargeOrderRequest) (resp *types.R
|
||||
}
|
||||
// Calculate the handling fee
|
||||
feeAmount := calculateFee(req.Amount, payment)
|
||||
totalAmount := req.Amount + feeAmount
|
||||
|
||||
// Validate total amount after adding fee
|
||||
if totalAmount > MaxOrderAmount {
|
||||
l.Errorw("[Recharge] Total amount exceeds maximum limit after fee",
|
||||
logger.Field("amount", totalAmount),
|
||||
logger.Field("max", MaxOrderAmount),
|
||||
logger.Field("user_id", u.Id))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "total amount exceeds maximum limit")
|
||||
}
|
||||
|
||||
// query user is new purchase or renewal
|
||||
isNew, err := l.svcCtx.OrderModel.IsUserEligibleForNewOrder(l.ctx, u.Id)
|
||||
if err != nil {
|
||||
@ -59,7 +85,7 @@ func (l *RechargeLogic) Recharge(req *types.RechargeOrderRequest) (resp *types.R
|
||||
OrderNo: tool.GenerateTradeNo(),
|
||||
Type: 4,
|
||||
Price: req.Amount,
|
||||
Amount: req.Amount + feeAmount,
|
||||
Amount: totalAmount,
|
||||
FeeAmount: feeAmount,
|
||||
PaymentId: payment.Id,
|
||||
Method: payment.Platform,
|
||||
|
||||
@ -50,6 +50,12 @@ func (l *RenewalLogic) Renewal(req *types.RenewalOrderRequest) (resp *types.Rene
|
||||
req.Quantity = 1
|
||||
}
|
||||
|
||||
// Validate quantity limit
|
||||
if req.Quantity > MaxQuantity {
|
||||
l.Errorw("[Renewal] Quantity exceeds maximum limit", logger.Field("quantity", req.Quantity), logger.Field("max", MaxQuantity))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "quantity exceeds maximum limit of %d", MaxQuantity)
|
||||
}
|
||||
|
||||
orderNo := tool.GenerateTradeNo()
|
||||
// find user subscribe
|
||||
userSubscribe, err := l.svcCtx.UserModel.FindOneUserSubscribe(l.ctx, req.UserSubscribeID)
|
||||
@ -75,6 +81,17 @@ func (l *RenewalLogic) Renewal(req *types.RenewalOrderRequest) (resp *types.Rene
|
||||
price := sub.UnitPrice * req.Quantity
|
||||
amount := int64(float64(price) * discount)
|
||||
discountAmount := price - amount
|
||||
|
||||
// Validate amount to prevent overflow
|
||||
if amount > MaxOrderAmount {
|
||||
l.Errorw("[Renewal] Order amount exceeds maximum limit",
|
||||
logger.Field("amount", amount),
|
||||
logger.Field("max", MaxOrderAmount),
|
||||
logger.Field("user_id", u.Id),
|
||||
logger.Field("subscribe_id", sub.Id))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "order amount exceeds maximum limit")
|
||||
}
|
||||
|
||||
var coupon int64 = 0
|
||||
if req.Coupon != "" {
|
||||
couponInfo, err := l.svcCtx.CouponModel.FindOneByCode(l.ctx, req.Coupon)
|
||||
@ -134,6 +151,15 @@ func (l *RenewalLogic) Renewal(req *types.RenewalOrderRequest) (resp *types.Rene
|
||||
|
||||
amount += feeAmount
|
||||
|
||||
// Final validation after adding fee
|
||||
if amount > MaxOrderAmount {
|
||||
l.Errorw("[Renewal] Final order amount exceeds maximum limit after fee",
|
||||
logger.Field("amount", amount),
|
||||
logger.Field("max", MaxOrderAmount),
|
||||
logger.Field("user_id", u.Id))
|
||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidParams), "order amount exceeds maximum limit")
|
||||
}
|
||||
|
||||
// create order
|
||||
orderInfo := order.Order{
|
||||
UserId: u.Id,
|
||||
|
||||
@ -323,14 +323,14 @@ type CreateNodeRequest struct {
|
||||
type CreateOrderRequest struct {
|
||||
UserId int64 `json:"user_id" validate:"required"`
|
||||
Type uint8 `json:"type" validate:"required"`
|
||||
Quantity int64 `json:"quantity,omitempty"`
|
||||
Price int64 `json:"price" validate:"required"`
|
||||
Amount int64 `json:"amount" validate:"required"`
|
||||
Discount int64 `json:"discount,omitempty"`
|
||||
Quantity int64 `json:"quantity,omitempty" validate:"omitempty,lte=1000"`
|
||||
Price int64 `json:"price" validate:"required,gte=0,lte=2000000000"`
|
||||
Amount int64 `json:"amount" validate:"required,gte=0,lte=2147483647"`
|
||||
Discount int64 `json:"discount,omitempty" validate:"omitempty,gte=0,lte=2000000000"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
CouponDiscount int64 `json:"coupon_discount,omitempty"`
|
||||
Commission int64 `json:"commission"`
|
||||
FeeAmount int64 `json:"fee_amount" validate:"required"`
|
||||
CouponDiscount int64 `json:"coupon_discount,omitempty" validate:"omitempty,gte=0,lte=2000000000"`
|
||||
Commission int64 `json:"commission" validate:"gte=0,lte=2000000000"`
|
||||
FeeAmount int64 `json:"fee_amount" validate:"required,gte=0,lte=2000000000"`
|
||||
PaymentId int64 `json:"payment_id" validate:"required"`
|
||||
TradeNo string `json:"trade_no,omitempty"`
|
||||
Status uint8 `json:"status,omitempty"`
|
||||
@ -1548,7 +1548,7 @@ type PubilcVerifyCodeConfig struct {
|
||||
|
||||
type PurchaseOrderRequest struct {
|
||||
SubscribeId int64 `json:"subscribe_id"`
|
||||
Quantity int64 `json:"quantity" validate:"required,gt=0"`
|
||||
Quantity int64 `json:"quantity" validate:"required,gt=0,lte=1000"`
|
||||
Payment int64 `json:"payment,omitempty"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
}
|
||||
@ -1760,7 +1760,7 @@ type QuotaTask struct {
|
||||
}
|
||||
|
||||
type RechargeOrderRequest struct {
|
||||
Amount int64 `json:"amount"`
|
||||
Amount int64 `json:"amount" validate:"required,gt=0,lte=2000000000"`
|
||||
Payment int64 `json:"payment"`
|
||||
}
|
||||
|
||||
@ -1790,7 +1790,7 @@ type RegisterLog struct {
|
||||
|
||||
type RenewalOrderRequest struct {
|
||||
UserSubscribeID int64 `json:"user_subscribe_id"`
|
||||
Quantity int64 `json:"quantity"`
|
||||
Quantity int64 `json:"quantity" validate:"lte=1000"`
|
||||
Payment int64 `json:"payment"`
|
||||
Coupon string `json:"coupon,omitempty"`
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user