Merge upstream/master into master
This commit is contained in:
commit
31e75efacb
@ -14,14 +14,14 @@ type (
|
|||||||
CreateOrderRequest {
|
CreateOrderRequest {
|
||||||
UserId int64 `json:"user_id" validate:"required"`
|
UserId int64 `json:"user_id" validate:"required"`
|
||||||
Type uint8 `json:"type" validate:"required"`
|
Type uint8 `json:"type" validate:"required"`
|
||||||
Quantity int64 `json:"quantity,omitempty"`
|
Quantity int64 `json:"quantity,omitempty" validate:"omitempty,lte=1000"`
|
||||||
Price int64 `json:"price" validate:"required"`
|
Price int64 `json:"price" validate:"required,gte=0,lte=2000000000"`
|
||||||
Amount int64 `json:"amount" validate:"required"`
|
Amount int64 `json:"amount" validate:"required,gte=0,lte=2147483647"`
|
||||||
Discount int64 `json:"discount,omitempty"`
|
Discount int64 `json:"discount,omitempty" validate:"omitempty,gte=0,lte=2000000000"`
|
||||||
Coupon string `json:"coupon,omitempty"`
|
Coupon string `json:"coupon,omitempty"`
|
||||||
CouponDiscount int64 `json:"coupon_discount,omitempty"`
|
CouponDiscount int64 `json:"coupon_discount,omitempty" validate:"omitempty,gte=0,lte=2000000000"`
|
||||||
Commission int64 `json:"commission"`
|
Commission int64 `json:"commission" validate:"gte=0,lte=2000000000"`
|
||||||
FeeAmount int64 `json:"fee_amount" validate:"required"`
|
FeeAmount int64 `json:"fee_amount" validate:"required,gte=0,lte=2000000000"`
|
||||||
PaymentId int64 `json:"payment_id" validate:"required"`
|
PaymentId int64 `json:"payment_id" validate:"required"`
|
||||||
TradeNo string `json:"trade_no,omitempty"`
|
TradeNo string `json:"trade_no,omitempty"`
|
||||||
Status uint8 `json:"status,omitempty"`
|
Status uint8 `json:"status,omitempty"`
|
||||||
|
|||||||
@ -604,7 +604,7 @@ type (
|
|||||||
//public order
|
//public order
|
||||||
PurchaseOrderRequest {
|
PurchaseOrderRequest {
|
||||||
SubscribeId int64 `json:"subscribe_id"`
|
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"`
|
Payment int64 `json:"payment,omitempty"`
|
||||||
Coupon string `json:"coupon,omitempty"`
|
Coupon string `json:"coupon,omitempty"`
|
||||||
}
|
}
|
||||||
@ -622,7 +622,7 @@ type (
|
|||||||
}
|
}
|
||||||
RenewalOrderRequest {
|
RenewalOrderRequest {
|
||||||
UserSubscribeID int64 `json:"user_subscribe_id"`
|
UserSubscribeID int64 `json:"user_subscribe_id"`
|
||||||
Quantity int64 `json:"quantity"`
|
Quantity int64 `json:"quantity" validate:"lte=1000"`
|
||||||
Payment int64 `json:"payment"`
|
Payment int64 `json:"payment"`
|
||||||
Coupon string `json:"coupon,omitempty"`
|
Coupon string `json:"coupon,omitempty"`
|
||||||
}
|
}
|
||||||
@ -637,7 +637,7 @@ type (
|
|||||||
OrderNo string `json:"order_no"`
|
OrderNo string `json:"order_no"`
|
||||||
}
|
}
|
||||||
RechargeOrderRequest {
|
RechargeOrderRequest {
|
||||||
Amount int64 `json:"amount"`
|
Amount int64 `json:"amount" validate:"required,gt=0,lte=2000000000"`
|
||||||
Payment int64 `json:"payment"`
|
Payment int64 `json:"payment"`
|
||||||
}
|
}
|
||||||
RechargeOrderResponse {
|
RechargeOrderResponse {
|
||||||
|
|||||||
@ -24,7 +24,7 @@ func Currency(ctx *svc.ServiceContext) {
|
|||||||
AccessKey string
|
AccessKey string
|
||||||
}{}
|
}{}
|
||||||
tool.SystemConfigSliceReflectToStruct(currency, &configs)
|
tool.SystemConfigSliceReflectToStruct(currency, &configs)
|
||||||
|
ctx.ExchangeRate = 0 // Default exchange rate to 0
|
||||||
ctx.Config.Currency = config.Currency{
|
ctx.Config.Currency = config.Currency{
|
||||||
Unit: configs.CurrencyUnit,
|
Unit: configs.CurrencyUnit,
|
||||||
Symbol: configs.CurrencySymbol,
|
Symbol: configs.CurrencySymbol,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/perfect-panel/server/initialize"
|
||||||
"github.com/perfect-panel/server/internal/config"
|
"github.com/perfect-panel/server/internal/config"
|
||||||
"github.com/perfect-panel/server/internal/model/system"
|
"github.com/perfect-panel/server/internal/model/system"
|
||||||
"github.com/perfect-panel/server/pkg/tool"
|
"github.com/perfect-panel/server/pkg/tool"
|
||||||
@ -54,6 +55,7 @@ func (l *UpdateCurrencyConfigLogic) UpdateCurrencyConfig(req *types.CurrencyConf
|
|||||||
// clear cache
|
// clear cache
|
||||||
return l.svcCtx.Redis.Del(l.ctx, config.CurrencyConfigKey, config.GlobalConfigKey).Err()
|
return l.svcCtx.Redis.Del(l.ctx, config.CurrencyConfigKey, config.GlobalConfigKey).Err()
|
||||||
})
|
})
|
||||||
|
initialize.Currency(l.svcCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Errorw("[UpdateCurrencyConfig] update currency config error", logger.Field("error", err.Error()))
|
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)
|
return errors.Wrapf(xerr.NewErrCode(xerr.DatabaseUpdateError), "update invite config error: %v", err)
|
||||||
|
|||||||
@ -6,4 +6,9 @@ const (
|
|||||||
StripeAlipay = "stripe_alipay"
|
StripeAlipay = "stripe_alipay"
|
||||||
StripeWeChatPay = "stripe_wechat_pay"
|
StripeWeChatPay = "stripe_wechat_pay"
|
||||||
Balance = "balance"
|
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
|
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
|
// find user subscription
|
||||||
userSub, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, u.Id)
|
userSub, err := l.svcCtx.UserModel.QueryUserSubscribe(l.ctx, u.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -97,6 +103,17 @@ func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.P
|
|||||||
// discount amount
|
// discount amount
|
||||||
amount := int64(float64(price) * discount)
|
amount := int64(float64(price) * discount)
|
||||||
discountAmount := price - amount
|
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
|
var coupon int64 = 0
|
||||||
// Calculate the coupon deduction
|
// Calculate the coupon deduction
|
||||||
if req.Coupon != "" {
|
if req.Coupon != "" {
|
||||||
@ -141,6 +158,15 @@ func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.P
|
|||||||
if amount > 0 {
|
if amount > 0 {
|
||||||
feeAmount = calculateFee(amount, payment)
|
feeAmount = calculateFee(amount, payment)
|
||||||
amount += feeAmount
|
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")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Calculate gift amount deduction after fee calculation
|
// Calculate gift amount deduction after fee calculation
|
||||||
var deductionAmount int64
|
var deductionAmount int64
|
||||||
|
|||||||
@ -40,6 +40,21 @@ func (l *RechargeLogic) Recharge(req *types.RechargeOrderRequest) (resp *types.R
|
|||||||
logger.Error("current user is not found in context")
|
logger.Error("current user is not found in context")
|
||||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.InvalidAccess), "Invalid Access")
|
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
|
// find payment method
|
||||||
payment, err := l.svcCtx.PaymentModel.FindOne(l.ctx, req.Payment)
|
payment, err := l.svcCtx.PaymentModel.FindOne(l.ctx, req.Payment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -48,6 +63,17 @@ func (l *RechargeLogic) Recharge(req *types.RechargeOrderRequest) (resp *types.R
|
|||||||
}
|
}
|
||||||
// Calculate the handling fee
|
// Calculate the handling fee
|
||||||
feeAmount := calculateFee(req.Amount, payment)
|
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
|
// query user is new purchase or renewal
|
||||||
isNew, err := l.svcCtx.OrderModel.IsUserEligibleForNewOrder(l.ctx, u.Id)
|
isNew, err := l.svcCtx.OrderModel.IsUserEligibleForNewOrder(l.ctx, u.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -59,7 +85,7 @@ func (l *RechargeLogic) Recharge(req *types.RechargeOrderRequest) (resp *types.R
|
|||||||
OrderNo: tool.GenerateTradeNo(),
|
OrderNo: tool.GenerateTradeNo(),
|
||||||
Type: 4,
|
Type: 4,
|
||||||
Price: req.Amount,
|
Price: req.Amount,
|
||||||
Amount: req.Amount + feeAmount,
|
Amount: totalAmount,
|
||||||
FeeAmount: feeAmount,
|
FeeAmount: feeAmount,
|
||||||
PaymentId: payment.Id,
|
PaymentId: payment.Id,
|
||||||
Method: payment.Platform,
|
Method: payment.Platform,
|
||||||
|
|||||||
@ -50,6 +50,12 @@ func (l *RenewalLogic) Renewal(req *types.RenewalOrderRequest) (resp *types.Rene
|
|||||||
req.Quantity = 1
|
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()
|
orderNo := tool.GenerateTradeNo()
|
||||||
// find user subscribe
|
// find user subscribe
|
||||||
userSubscribe, err := l.svcCtx.UserModel.FindOneUserSubscribe(l.ctx, req.UserSubscribeID)
|
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
|
price := sub.UnitPrice * req.Quantity
|
||||||
amount := int64(float64(price) * discount)
|
amount := int64(float64(price) * discount)
|
||||||
discountAmount := price - amount
|
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
|
var coupon int64 = 0
|
||||||
if req.Coupon != "" {
|
if req.Coupon != "" {
|
||||||
couponInfo, err := l.svcCtx.CouponModel.FindOneByCode(l.ctx, 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
|
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
|
// create order
|
||||||
orderInfo := order.Order{
|
orderInfo := order.Order{
|
||||||
UserId: u.Id,
|
UserId: u.Id,
|
||||||
|
|||||||
@ -51,6 +51,7 @@ func NewPurchaseCheckoutLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
|
|||||||
// PurchaseCheckout processes the checkout for an order using the specified payment method
|
// 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
|
// 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) {
|
func (l *PurchaseCheckoutLogic) PurchaseCheckout(req *types.CheckoutOrderRequest) (resp *types.CheckoutOrderResponse, err error) {
|
||||||
|
|
||||||
// Validate and retrieve order information
|
// Validate and retrieve order information
|
||||||
orderInfo, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
|
orderInfo, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -76,6 +77,7 @@ func (l *PurchaseCheckoutLogic) PurchaseCheckout(req *types.CheckoutOrderRequest
|
|||||||
// Process EPay payment - generates payment URL for redirect
|
// Process EPay payment - generates payment URL for redirect
|
||||||
url, err := l.epayPayment(paymentConfig, orderInfo, req.ReturnUrl)
|
url, err := l.epayPayment(paymentConfig, orderInfo, req.ReturnUrl)
|
||||||
if err != nil {
|
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())
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "epayPayment error: %v", err.Error())
|
||||||
}
|
}
|
||||||
resp = &types.CheckoutOrderResponse{
|
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
|
// Convert order amount to CNY using current exchange rate
|
||||||
amount, err = l.queryExchangeRate("CNY", info.Amount)
|
amount, err = l.queryExchangeRate("CNY", info.Amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
l.Logger.Error("[PurchaseCheckout] queryExchangeRate error", logger.Field("error", err.Error()))
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -382,6 +385,11 @@ func (l *PurchaseCheckoutLogic) queryExchangeRate(to string, src int64) (amount
|
|||||||
// Convert cents to decimal amount
|
// Convert cents to decimal amount
|
||||||
amount = float64(src) / float64(100)
|
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" {
|
if l.svcCtx.ExchangeRate != 0 && to == "CNY" {
|
||||||
amount = amount * l.svcCtx.ExchangeRate
|
amount = amount * l.svcCtx.ExchangeRate
|
||||||
return amount, nil
|
return amount, nil
|
||||||
@ -395,6 +403,7 @@ func (l *PurchaseCheckoutLogic) queryExchangeRate(to string, src int64) (amount
|
|||||||
// Convert currency if system currency differs from target currency
|
// 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)
|
result, err := exchangeRate.GetExchangeRete(l.svcCtx.Config.Currency.Unit, to, l.svcCtx.Config.Currency.AccessKey, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
l.Logger.Error("[PurchaseCheckout] QueryExchangeRate error", logger.Field("error", err.Error()))
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
l.svcCtx.ExchangeRate = result
|
l.svcCtx.ExchangeRate = result
|
||||||
|
|||||||
@ -24,6 +24,7 @@ type SecurityConfig struct {
|
|||||||
RealityPublicKey string `json:"reality_public_key"`
|
RealityPublicKey string `json:"reality_public_key"`
|
||||||
RealityShortId string `json:"reality_short_id"`
|
RealityShortId string `json:"reality_short_id"`
|
||||||
RealityMldsa65seed string `json:"reality_mldsa65seed"`
|
RealityMldsa65seed string `json:"reality_mldsa65seed"`
|
||||||
|
PaddingScheme string `json:"padding_scheme"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type TransportConfig struct {
|
type TransportConfig struct {
|
||||||
|
|||||||
@ -199,6 +199,7 @@ func (l *GetServerConfigLogic) compatible(config node.Protocol) map[string]inter
|
|||||||
RealityPrivateKey: config.RealityPrivateKey,
|
RealityPrivateKey: config.RealityPrivateKey,
|
||||||
RealityPublicKey: config.RealityPublicKey,
|
RealityPublicKey: config.RealityPublicKey,
|
||||||
RealityShortId: config.RealityShortId,
|
RealityShortId: config.RealityShortId,
|
||||||
|
PaddingScheme: config.PaddingScheme,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
case Tuic:
|
case Tuic:
|
||||||
|
|||||||
@ -333,14 +333,14 @@ type CreateNodeRequest struct {
|
|||||||
type CreateOrderRequest struct {
|
type CreateOrderRequest struct {
|
||||||
UserId int64 `json:"user_id" validate:"required"`
|
UserId int64 `json:"user_id" validate:"required"`
|
||||||
Type uint8 `json:"type" validate:"required"`
|
Type uint8 `json:"type" validate:"required"`
|
||||||
Quantity int64 `json:"quantity,omitempty"`
|
Quantity int64 `json:"quantity,omitempty" validate:"omitempty,lte=1000"`
|
||||||
Price int64 `json:"price" validate:"required"`
|
Price int64 `json:"price" validate:"required,gte=0,lte=2000000000"`
|
||||||
Amount int64 `json:"amount" validate:"required"`
|
Amount int64 `json:"amount" validate:"required,gte=0,lte=2147483647"`
|
||||||
Discount int64 `json:"discount,omitempty"`
|
Discount int64 `json:"discount,omitempty" validate:"omitempty,gte=0,lte=2000000000"`
|
||||||
Coupon string `json:"coupon,omitempty"`
|
Coupon string `json:"coupon,omitempty"`
|
||||||
CouponDiscount int64 `json:"coupon_discount,omitempty"`
|
CouponDiscount int64 `json:"coupon_discount,omitempty" validate:"omitempty,gte=0,lte=2000000000"`
|
||||||
Commission int64 `json:"commission"`
|
Commission int64 `json:"commission" validate:"gte=0,lte=2000000000"`
|
||||||
FeeAmount int64 `json:"fee_amount" validate:"required"`
|
FeeAmount int64 `json:"fee_amount" validate:"required,gte=0,lte=2000000000"`
|
||||||
PaymentId int64 `json:"payment_id" validate:"required"`
|
PaymentId int64 `json:"payment_id" validate:"required"`
|
||||||
TradeNo string `json:"trade_no,omitempty"`
|
TradeNo string `json:"trade_no,omitempty"`
|
||||||
Status uint8 `json:"status,omitempty"`
|
Status uint8 `json:"status,omitempty"`
|
||||||
@ -1602,7 +1602,7 @@ type PubilcVerifyCodeConfig struct {
|
|||||||
|
|
||||||
type PurchaseOrderRequest struct {
|
type PurchaseOrderRequest struct {
|
||||||
SubscribeId int64 `json:"subscribe_id"`
|
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"`
|
Payment int64 `json:"payment,omitempty"`
|
||||||
Coupon string `json:"coupon,omitempty"`
|
Coupon string `json:"coupon,omitempty"`
|
||||||
}
|
}
|
||||||
@ -1814,7 +1814,7 @@ type QuotaTask struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RechargeOrderRequest struct {
|
type RechargeOrderRequest struct {
|
||||||
Amount int64 `json:"amount"`
|
Amount int64 `json:"amount" validate:"required,gt=0,lte=2000000000"`
|
||||||
Payment int64 `json:"payment"`
|
Payment int64 `json:"payment"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1877,7 +1877,7 @@ type RegisterLog struct {
|
|||||||
|
|
||||||
type RenewalOrderRequest struct {
|
type RenewalOrderRequest struct {
|
||||||
UserSubscribeID int64 `json:"user_subscribe_id"`
|
UserSubscribeID int64 `json:"user_subscribe_id"`
|
||||||
Quantity int64 `json:"quantity"`
|
Quantity int64 `json:"quantity" validate:"lte=1000"`
|
||||||
Payment int64 `json:"payment"`
|
Payment int64 `json:"payment"`
|
||||||
Coupon string `json:"coupon,omitempty"`
|
Coupon string `json:"coupon,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,10 +6,11 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
|
"github.com/perfect-panel/server/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Url = "https://api.exchangerate.host"
|
Url = "https://api.apilayer.com"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Response struct {
|
type Response struct {
|
||||||
@ -40,15 +41,17 @@ func GetExchangeRete(form, to, access string, amount float64) (float64, error) {
|
|||||||
"from": form,
|
"from": form,
|
||||||
"to": to,
|
"to": to,
|
||||||
"amount": amountStr,
|
"amount": amountStr,
|
||||||
"access_key": access,
|
|
||||||
})
|
})
|
||||||
resp := new(Response)
|
result := new(Response)
|
||||||
_, err := client.R().SetResult(resp).Get("/convert")
|
resp, err := client.R().SetHeader("apikey", access).SetResult(result).Get("/currency_data/convert")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if !resp.Success {
|
if !result.Success {
|
||||||
|
logger.Info("Exchange Rate Response: ", resp.String())
|
||||||
return 0, errors.New("exchange rate failed")
|
return 0, errors.New("exchange rate failed")
|
||||||
}
|
}
|
||||||
return resp.Result, nil
|
return result.Result, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import "testing"
|
|||||||
|
|
||||||
func TestGetExchangeRete(t *testing.T) {
|
func TestGetExchangeRete(t *testing.T) {
|
||||||
t.Skip("skip TestGetExchangeRete")
|
t.Skip("skip TestGetExchangeRete")
|
||||||
result, err := GetExchangeRete("USD", "CNY", "90734e5af4f5353114cdaf3bb9c3f2e3", 1)
|
result, err := GetExchangeRete("USD", "CNY", "", 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user