1 Commits
v1.7.0 ... main

Author SHA1 Message Date
6e14ea65d0 套餐白名单检查逻辑 & 检查订单金额 2026-04-21 18:09:53 +08:00
7 changed files with 32 additions and 17 deletions

View File

@@ -818,6 +818,7 @@ create table resource (
code text, code text,
type int not null, type int not null,
active bool not null default true, active bool not null default true,
checkip bool not null default true,
created_at timestamptz default current_timestamp, created_at timestamptz default current_timestamp,
updated_at timestamptz default current_timestamp, updated_at timestamptz default current_timestamp,
deleted_at timestamptz deleted_at timestamptz
@@ -832,9 +833,10 @@ comment on table resource is '套餐表';
comment on column resource.id is '套餐ID'; comment on column resource.id is '套餐ID';
comment on column resource.user_id is '用户ID'; comment on column resource.user_id is '用户ID';
comment on column resource.resource_no is '套餐编号'; comment on column resource.resource_no is '套餐编号';
comment on column resource.active is '套餐状态';
comment on column resource.type is '套餐类型1-短效动态2-长效动态';
comment on column resource.code is '产品编码'; comment on column resource.code is '产品编码';
comment on column resource.type is '套餐类型1-短效动态2-长效动态';
comment on column resource.active is '套餐状态';
comment on column resource.checkip is '提取时是否检查 ip 地址';
comment on column resource.created_at is '创建时间'; comment on column resource.created_at is '创建时间';
comment on column resource.updated_at is '更新时间'; comment on column resource.updated_at is '更新时间';
comment on column resource.deleted_at is '删除时间'; comment on column resource.deleted_at is '删除时间';

View File

@@ -12,6 +12,7 @@ type Resource struct {
Active bool `json:"active" gorm:"column:active"` // 套餐状态 Active bool `json:"active" gorm:"column:active"` // 套餐状态
Type ResourceType `json:"type" gorm:"column:type"` // 套餐类型1-短效动态2-长效动态 Type ResourceType `json:"type" gorm:"column:type"` // 套餐类型1-短效动态2-长效动态
Code string `json:"code" gorm:"column:code"` // 产品编码 Code string `json:"code" gorm:"column:code"` // 产品编码
CheckIP bool `json:"checkip" gorm:"column:checkip"` // 是否检查IP
User *User `json:"user,omitempty" gorm:"foreignKey:UserID"` User *User `json:"user,omitempty" gorm:"foreignKey:UserID"`
Short *ResourceShort `json:"short,omitempty" gorm:"foreignKey:ResourceID"` Short *ResourceShort `json:"short,omitempty" gorm:"foreignKey:ResourceID"`

View File

@@ -36,6 +36,7 @@ func newResource(db *gorm.DB, opts ...gen.DOOption) resource {
_resource.Active = field.NewBool(tableName, "active") _resource.Active = field.NewBool(tableName, "active")
_resource.Type = field.NewInt(tableName, "type") _resource.Type = field.NewInt(tableName, "type")
_resource.Code = field.NewString(tableName, "code") _resource.Code = field.NewString(tableName, "code")
_resource.CheckIP = field.NewBool(tableName, "checkip")
_resource.Short = resourceHasOneShort{ _resource.Short = resourceHasOneShort{
db: db.Session(&gorm.Session{}), db: db.Session(&gorm.Session{}),
@@ -185,6 +186,7 @@ type resource struct {
Active field.Bool Active field.Bool
Type field.Int Type field.Int
Code field.String Code field.String
CheckIP field.Bool
Short resourceHasOneShort Short resourceHasOneShort
Long resourceHasOneLong Long resourceHasOneLong
@@ -217,6 +219,7 @@ func (r *resource) updateTableName(table string) *resource {
r.Active = field.NewBool(table, "active") r.Active = field.NewBool(table, "active")
r.Type = field.NewInt(table, "type") r.Type = field.NewInt(table, "type")
r.Code = field.NewString(table, "code") r.Code = field.NewString(table, "code")
r.CheckIP = field.NewBool(table, "checkip")
r.fillFieldMap() r.fillFieldMap()
@@ -233,7 +236,7 @@ func (r *resource) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
} }
func (r *resource) fillFieldMap() { func (r *resource) fillFieldMap() {
r.fieldMap = make(map[string]field.Expr, 13) r.fieldMap = make(map[string]field.Expr, 14)
r.fieldMap["id"] = r.ID r.fieldMap["id"] = r.ID
r.fieldMap["created_at"] = r.CreatedAt r.fieldMap["created_at"] = r.CreatedAt
r.fieldMap["updated_at"] = r.UpdatedAt r.fieldMap["updated_at"] = r.UpdatedAt
@@ -243,6 +246,7 @@ func (r *resource) fillFieldMap() {
r.fieldMap["active"] = r.Active r.fieldMap["active"] = r.Active
r.fieldMap["type"] = r.Type r.fieldMap["type"] = r.Type
r.fieldMap["code"] = r.Code r.fieldMap["code"] = r.Code
r.fieldMap["checkip"] = r.CheckIP
} }

View File

@@ -83,10 +83,11 @@ func findResource(resourceId int32, now time.Time) (*ResourceView, error) {
return nil, ErrResourceNotExist return nil, ErrResourceNotExist
} }
var info = &ResourceView{ var info = &ResourceView{
Id: resource.ID, Id: resource.ID,
User: *resource.User, User: *resource.User,
Active: resource.Active, Active: resource.Active,
Type: resource.Type, Type: resource.Type,
CheckIP: resource.CheckIP,
} }
switch resource.Type { switch resource.Type {
@@ -142,6 +143,7 @@ type ResourceView struct {
Daily int32 Daily int32
LastAt *time.Time LastAt *time.Time
Today int // 今日用量 Today int // 今日用量
CheckIP bool
} }
// 检查用户是否可提取 // 检查用户是否可提取
@@ -178,7 +180,7 @@ func ensure(now time.Time, source netip.Addr, resourceId int32, count int) (*Res
pass = true pass = true
} }
} }
if !pass { if resource.CheckIP && !pass {
return nil, nil, core.NewBizErr(fmt.Sprintf("IP 地址 %s 不在白名单内", source.String())) return nil, nil, core.NewBizErr(fmt.Sprintf("IP 地址 %s 不在白名单内", source.String()))
} }

View File

@@ -188,7 +188,7 @@ func (s *proxyService) Remove(id int32) error {
type UpdateProxyStatus struct { type UpdateProxyStatus struct {
ID int32 `json:"id" validate:"required"` ID int32 `json:"id" validate:"required"`
Status m.ProxyStatus `json:"status" validate:"required"` Status m.ProxyStatus `json:"status"`
} }
func (s *proxyService) UpdateStatus(update *UpdateProxyStatus) error { func (s *proxyService) UpdateStatus(update *UpdateProxyStatus) error {

View File

@@ -121,14 +121,13 @@ func (s *resourceService) Create(q *q.Query, uid int32, now time.Time, data *Cre
} }
func (s *resourceService) Update(data *UpdateResourceData) error { func (s *resourceService) Update(data *UpdateResourceData) error {
if data.Active == nil {
return core.NewBizErr("更新套餐失败active 不能为空")
}
do := make([]field.AssignExpr, 0) do := make([]field.AssignExpr, 0)
if data.Active != nil { if data.Active != nil {
do = append(do, q.Resource.Active.Value(*data.Active)) do = append(do, q.Resource.Active.Value(*data.Active))
} }
if data.CheckIP != nil {
do = append(do, q.Resource.CheckIP.Value(*data.CheckIP))
}
_, err := q.Resource. _, err := q.Resource.
Where(q.Resource.ID.Eq(data.Id)). Where(q.Resource.ID.Eq(data.Id)).
@@ -142,10 +141,14 @@ func (s *resourceService) Update(data *UpdateResourceData) error {
type UpdateResourceData struct { type UpdateResourceData struct {
core.IdReq core.IdReq
Active *bool `json:"active"` Active *bool `json:"active"`
CheckIP *bool `json:"checkip"`
} }
func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, cuid *int32) (*m.ProductSku, *m.ProductDiscount, *m.CouponUser, decimal.Decimal, decimal.Decimal, decimal.Decimal, error) { func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, cuid *int32) (*m.ProductSku, *m.ProductDiscount, *m.CouponUser, decimal.Decimal, decimal.Decimal, decimal.Decimal, error) {
if count <= 0 {
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewBizErr("购买数量必须大于 0")
}
sku, err := q.ProductSku. sku, err := q.ProductSku.
Joins(q.ProductSku.Discount). Joins(q.ProductSku.Discount).
@@ -153,7 +156,7 @@ func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, c
Take() Take()
if err != nil { if err != nil {
slog.Debug("查询产品失败", "skuCode", skuCode) slog.Debug("查询产品失败", "skuCode", skuCode)
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewBizErr(fmt.Sprintf("产品不可用", skuCode), err) return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewBizErr("产品不可用", err)
} }
// 原价 // 原价
@@ -163,7 +166,7 @@ func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, c
// 折扣价 // 折扣价
discount := sku.Discount discount := sku.Discount
if discount == nil { if discount == nil {
return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewServErr("价格查询失败", err) return nil, nil, nil, decimal.Zero, decimal.Zero, decimal.Zero, core.NewServErr("产品未配置折扣", err)
} }
discountRate := discount.Rate() discountRate := discount.Rate()
@@ -201,7 +204,7 @@ func (s *resourceService) CalcPrice(skuCode string, count int32, user *m.User, c
couponApplied = amountMin.Copy() couponApplied = amountMin.Copy()
} }
return sku, discount, coupon, amount, discounted, couponApplied, nil return sku, discount, coupon, amount.RoundCeil(2), discounted.RoundCeil(2), couponApplied.RoundCeil(2), nil
} }
type CreateResourceData struct { type CreateResourceData struct {

View File

@@ -88,6 +88,9 @@ type UpdateBalanceData struct {
} }
func (data *UpdateBalanceData) TradeDetail(user *m.User) (*TradeDetail, error) { func (data *UpdateBalanceData) TradeDetail(user *m.User) (*TradeDetail, error) {
if data.Amount <= 0 {
return nil, core.NewBizErr("充值金额必须大于0")
}
amount := decimal.NewFromInt(int64(data.Amount)).Div(decimal.NewFromInt(100)) amount := decimal.NewFromInt(int64(data.Amount)).Div(decimal.NewFromInt(100))
return &TradeDetail{ return &TradeDetail{
data, data,