From 58caa497c38eb7af108c03fc8afedf29981b3cb4 Mon Sep 17 00:00:00 2001 From: Chang lue Tsen Date: Wed, 7 Jan 2026 09:35:09 -0500 Subject: [PATCH 1/6] fix(exchange): update exchange rate API endpoint and adjust request parameters --- pkg/exchangeRate/exchangeRate.go | 21 ++++++++++++--------- pkg/exchangeRate/exchange_rate_test.go | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/pkg/exchangeRate/exchangeRate.go b/pkg/exchangeRate/exchangeRate.go index 83ce545..8ee78c7 100644 --- a/pkg/exchangeRate/exchangeRate.go +++ b/pkg/exchangeRate/exchangeRate.go @@ -6,10 +6,11 @@ import ( "time" "github.com/go-resty/resty/v2" + "github.com/perfect-panel/server/pkg/logger" ) const ( - Url = "https://api.exchangerate.host" + Url = "https://api.apilayer.com" ) type Response struct { @@ -37,18 +38,20 @@ func GetExchangeRete(form, to, access string, amount float64) (float64, error) { amountStr := strconv.FormatFloat(amount, 'f', -1, 64) client.SetQueryParams(map[string]string{ - "from": form, - "to": to, - "amount": amountStr, - "access_key": access, + "from": form, + "to": to, + "amount": amountStr, }) - resp := new(Response) - _, err := client.R().SetResult(resp).Get("/convert") + result := new(Response) + resp, err := client.R().SetHeader("apikey", access).SetResult(result).Get("/currency_data/convert") + if err != nil { + return 0, err } - if !resp.Success { + if !result.Success { + logger.Info("Exchange Rate Response: ", resp.String()) return 0, errors.New("exchange rate failed") } - return resp.Result, nil + return result.Result, nil } diff --git a/pkg/exchangeRate/exchange_rate_test.go b/pkg/exchangeRate/exchange_rate_test.go index c24595d..1444098 100644 --- a/pkg/exchangeRate/exchange_rate_test.go +++ b/pkg/exchangeRate/exchange_rate_test.go @@ -4,7 +4,7 @@ import "testing" func TestGetExchangeRete(t *testing.T) { t.Skip("skip TestGetExchangeRete") - result, err := GetExchangeRete("USD", "CNY", "90734e5af4f5353114cdaf3bb9c3f2e3", 1) + result, err := GetExchangeRete("USD", "CNY", "", 1) if err != nil { t.Fatal(err) } From 7d84cf858bb5d3e747fa164ca5fa4322ffe8bb7f Mon Sep 17 00:00:00 2001 From: Chang lue Tsen Date: Wed, 7 Jan 2026 09:35:52 -0500 Subject: [PATCH 2/6] fix(currency): initialize exchange rate to 0 and improve error logging in purchase checkout --- initialize/currency.go | 2 +- internal/logic/admin/system/updateCurrencyConfigLogic.go | 2 ++ internal/logic/public/portal/purchaseCheckoutLogic.go | 9 +++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/initialize/currency.go b/initialize/currency.go index 25dc52f..29c5642 100644 --- a/initialize/currency.go +++ b/initialize/currency.go @@ -24,7 +24,7 @@ func Currency(ctx *svc.ServiceContext) { AccessKey string }{} tool.SystemConfigSliceReflectToStruct(currency, &configs) - + ctx.ExchangeRate = 0 // Default exchange rate to 0 ctx.Config.Currency = config.Currency{ Unit: configs.CurrencyUnit, Symbol: configs.CurrencySymbol, diff --git a/internal/logic/admin/system/updateCurrencyConfigLogic.go b/internal/logic/admin/system/updateCurrencyConfigLogic.go index 0104331..f49f490 100644 --- a/internal/logic/admin/system/updateCurrencyConfigLogic.go +++ b/internal/logic/admin/system/updateCurrencyConfigLogic.go @@ -4,6 +4,7 @@ import ( "context" "reflect" + "github.com/perfect-panel/server/initialize" "github.com/perfect-panel/server/internal/config" "github.com/perfect-panel/server/internal/model/system" "github.com/perfect-panel/server/pkg/tool" @@ -54,6 +55,7 @@ func (l *UpdateCurrencyConfigLogic) UpdateCurrencyConfig(req *types.CurrencyConf // clear cache return l.svcCtx.Redis.Del(l.ctx, config.CurrencyConfigKey, config.GlobalConfigKey).Err() }) + initialize.Currency(l.svcCtx) if err != nil { l.Errorw("[UpdateCurrencyConfig] update currency config error", logger.Field("error", err.Error())) return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update invite config error: %v", err) diff --git a/internal/logic/public/portal/purchaseCheckoutLogic.go b/internal/logic/public/portal/purchaseCheckoutLogic.go index 105e1dc..568fb05 100644 --- a/internal/logic/public/portal/purchaseCheckoutLogic.go +++ b/internal/logic/public/portal/purchaseCheckoutLogic.go @@ -51,6 +51,7 @@ func NewPurchaseCheckoutLogic(ctx context.Context, svcCtx *svc.ServiceContext) * // PurchaseCheckout processes the checkout for an order using the specified payment method // It validates the order, retrieves payment configuration, and routes to the appropriate payment handler func (l *PurchaseCheckoutLogic) PurchaseCheckout(req *types.CheckoutOrderRequest) (resp *types.CheckoutOrderResponse, err error) { + // Validate and retrieve order information orderInfo, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo) if err != nil { @@ -76,6 +77,7 @@ func (l *PurchaseCheckoutLogic) PurchaseCheckout(req *types.CheckoutOrderRequest // Process EPay payment - generates payment URL for redirect url, err := l.epayPayment(paymentConfig, orderInfo, req.ReturnUrl) if err != nil { + l.Logger.Error("[PurchaseCheckout] epay error", logger.Field("error", err.Error())) return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "epayPayment error: %v", err.Error()) } resp = &types.CheckoutOrderResponse{ @@ -274,6 +276,7 @@ func (l *PurchaseCheckoutLogic) epayPayment(config *payment.Payment, info *order // Convert order amount to CNY using current exchange rate amount, err = l.queryExchangeRate("CNY", info.Amount) if err != nil { + l.Logger.Error("[PurchaseCheckout] queryExchangeRate error", logger.Field("error", err.Error())) return "", err } } else { @@ -381,6 +384,11 @@ func (l *PurchaseCheckoutLogic) queryExchangeRate(to string, src int64) (amount // Convert cents to decimal amount amount = float64(src) / float64(100) + // No conversion needed if target currency matches system currency + if to == l.svcCtx.Config.Currency.Unit { + return amount, nil + } + if l.svcCtx.ExchangeRate != 0 && to == "CNY" { amount = amount * l.svcCtx.ExchangeRate return amount, nil @@ -394,6 +402,7 @@ func (l *PurchaseCheckoutLogic) queryExchangeRate(to string, src int64) (amount // Convert currency if system currency differs from target currency result, err := exchangeRate.GetExchangeRete(l.svcCtx.Config.Currency.Unit, to, l.svcCtx.Config.Currency.AccessKey, 1) if err != nil { + l.Logger.Error("[PurchaseCheckout] QueryExchangeRate error", logger.Field("error", err.Error())) return 0, err } l.svcCtx.ExchangeRate = result From 1995987f006ce73a7ab7ff7e5212d3c74ed82bec Mon Sep 17 00:00:00 2001 From: Chang lue Tsen Date: Wed, 7 Jan 2026 09:39:10 -0500 Subject: [PATCH 3/6] feat(config): add PaddingScheme to configuration and update server config logic --- internal/logic/server/constant.go | 1 + internal/logic/server/getServerConfigLogic.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/logic/server/constant.go b/internal/logic/server/constant.go index e2d1584..40a9113 100644 --- a/internal/logic/server/constant.go +++ b/internal/logic/server/constant.go @@ -24,6 +24,7 @@ type SecurityConfig struct { RealityPublicKey string `json:"reality_public_key"` RealityShortId string `json:"reality_short_id"` RealityMldsa65seed string `json:"reality_mldsa65seed"` + PaddingScheme string `json:"padding_scheme"` } type TransportConfig struct { diff --git a/internal/logic/server/getServerConfigLogic.go b/internal/logic/server/getServerConfigLogic.go index 94221a9..2b7ea3b 100644 --- a/internal/logic/server/getServerConfigLogic.go +++ b/internal/logic/server/getServerConfigLogic.go @@ -199,6 +199,7 @@ func (l *GetServerConfigLogic) compatible(config node.Protocol) map[string]inter RealityPrivateKey: config.RealityPrivateKey, RealityPublicKey: config.RealityPublicKey, RealityShortId: config.RealityShortId, + PaddingScheme: config.PaddingScheme, }, } case Tuic: From 701d47ed21db1a5a6f2e5e9663b4252a66774830 Mon Sep 17 00:00:00 2001 From: Chang lue Tsen Date: Sun, 8 Feb 2026 06:41:23 -0500 Subject: [PATCH 4/6] feat(order): add validation for quantity and amount limits in order requests --- apis/admin/order.api | 14 +++++----- apis/types.api | 6 ++--- internal/handler/routes.go | 4 +-- internal/logic/public/order/constant.go | 5 ++++ internal/logic/public/order/purchaseLogic.go | 26 ++++++++++++++++++ internal/logic/public/order/rechargeLogic.go | 28 +++++++++++++++++++- internal/logic/public/order/renewalLogic.go | 26 ++++++++++++++++++ internal/types/types.go | 20 +++++++------- 8 files changed, 106 insertions(+), 23 deletions(-) diff --git a/apis/admin/order.api b/apis/admin/order.api index 0d49074..87fa80d 100644 --- a/apis/admin/order.api +++ b/apis/admin/order.api @@ -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"` diff --git a/apis/types.api b/apis/types.api index 5f174be..f3e0f15 100644 --- a/apis/types.api +++ b/apis/types.api @@ -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 { diff --git a/internal/handler/routes.go b/internal/handler/routes.go index 6a942a7..16654d5 100644 --- a/internal/handler/routes.go +++ b/internal/handler/routes.go @@ -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)) } } diff --git a/internal/logic/public/order/constant.go b/internal/logic/public/order/constant.go index ca1c44a..cc3683a 100644 --- a/internal/logic/public/order/constant.go +++ b/internal/logic/public/order/constant.go @@ -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 ) diff --git a/internal/logic/public/order/purchaseLogic.go b/internal/logic/public/order/purchaseLogic.go index cbc960f..91bc834 100644 --- a/internal/logic/public/order/purchaseLogic.go +++ b/internal/logic/public/order/purchaseLogic.go @@ -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) diff --git a/internal/logic/public/order/rechargeLogic.go b/internal/logic/public/order/rechargeLogic.go index 04ff41c..a27053c 100644 --- a/internal/logic/public/order/rechargeLogic.go +++ b/internal/logic/public/order/rechargeLogic.go @@ -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, diff --git a/internal/logic/public/order/renewalLogic.go b/internal/logic/public/order/renewalLogic.go index c78824f..e384413 100644 --- a/internal/logic/public/order/renewalLogic.go +++ b/internal/logic/public/order/renewalLogic.go @@ -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, diff --git a/internal/types/types.go b/internal/types/types.go index 97042bd..45c46c9 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -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"` } From ea94f3c9f97f2f7d6a9ca2691966de3a49d3a8ea Mon Sep 17 00:00:00 2001 From: Chang lue Tsen Date: Sun, 8 Feb 2026 06:43:34 -0500 Subject: [PATCH 5/6] feat(stripe): update webhook event construction to ignore API version mismatches --- pkg/payment/stripe/stripe.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/payment/stripe/stripe.go b/pkg/payment/stripe/stripe.go index d0f4af6..ced0499 100644 --- a/pkg/payment/stripe/stripe.go +++ b/pkg/payment/stripe/stripe.go @@ -155,7 +155,9 @@ func (c *Client) QueryOrderStatus(orderNo string) (bool, error) { // ParseNotify func (c *Client) ParseNotify(payload []byte, signature string) (*NotifyResult, error) { - event, err := webhook.ConstructEvent(payload, signature, c.Config.WebhookSecret) + event, err := webhook.ConstructEventWithOptions(payload, signature, c.Config.WebhookSecret, webhook.ConstructEventOptions{ + IgnoreAPIVersionMismatch: true, + }) if err != nil { return nil, err } From b6a1739efaaaf25ee9bad31fd702a1f515b94b2f Mon Sep 17 00:00:00 2001 From: Chang lue Tsen Date: Sun, 8 Feb 2026 06:47:06 -0500 Subject: [PATCH 6/6] refactor(routes): rename server group router for clarity and consistency --- internal/handler/routes.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/handler/routes.go b/internal/handler/routes.go index 16654d5..6a942a7 100644 --- a/internal/handler/routes.go +++ b/internal/handler/routes.go @@ -888,10 +888,10 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) { serverGroupRouter.GET("/user", server.GetServerUserListHandler(serverCtx)) } - serverGroupRouter := router.Group("/v2/server") + serverV2GroupRouter := router.Group("/v2/server") { // Get Server Protocol Config - serverGroupRouter.GET("/:server_id", server.QueryServerProtocolConfigHandler(serverCtx)) + serverV2GroupRouter.GET("/:server_id", server.QueryServerProtocolConfigHandler(serverCtx)) } }