This commit is contained in:
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/server/internal/logic/telegram"
|
||||
"github.com/perfect-panel/server/internal/model/order"
|
||||
internaltypes "github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/internal/model/redemption"
|
||||
"github.com/perfect-panel/server/internal/model/subscribe"
|
||||
"github.com/perfect-panel/server/internal/model/user"
|
||||
@@ -223,6 +224,29 @@ func (l *ActivateOrderLogic) NewPurchase(ctx context.Context, orderInfo *order.O
|
||||
return err
|
||||
}
|
||||
|
||||
// check new user only restriction at activation to prevent concurrent bypass
|
||||
if orderInfo.Type == OrderTypeSubscribe && sub.Discount != "" {
|
||||
var dis []internaltypes.SubscribeDiscount
|
||||
if jsonErr := json.Unmarshal([]byte(sub.Discount), &dis); jsonErr == nil {
|
||||
newUserOnly := isNewUserOnlyForQuantity(dis, orderInfo.Quantity)
|
||||
if newUserOnly {
|
||||
if time.Since(userInfo.CreatedAt) > 24*time.Hour {
|
||||
return fmt.Errorf("new user only: user %d is not a new user", userInfo.Id)
|
||||
}
|
||||
var historyCount int64
|
||||
if e := l.svc.DB.Model(&order.Order{}).
|
||||
Where("user_id = ? AND subscribe_id = ? AND type = 1 AND status = ? AND order_no != ?",
|
||||
orderInfo.UserId, orderInfo.SubscribeId, OrderStatusFinished, orderInfo.OrderNo).
|
||||
Count(&historyCount).Error; e != nil {
|
||||
return fmt.Errorf("new user only: check history error: %w", e)
|
||||
}
|
||||
if historyCount >= 1 {
|
||||
return fmt.Errorf("new user only: user %d already activated subscribe %d", userInfo.Id, orderInfo.SubscribeId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var userSub *user.Subscribe
|
||||
|
||||
// 单订阅模式下,优先兜底为“续费语义”:延长已购订阅,避免并发下重复创建 user_subscribe
|
||||
@@ -615,7 +639,7 @@ func (l *ActivateOrderLogic) handleCommission(ctx context.Context, userInfo *use
|
||||
|
||||
func (l *ActivateOrderLogic) grantGiftDaysToBothParties(ctx context.Context, referee *user.User, orderNo string) {
|
||||
giftDays := l.svc.Config.Invite.GiftDays
|
||||
if giftDays <= 0 || referee == nil || referee.Id == 0 {
|
||||
if giftDays <= 0 || referee == nil || referee.Id == 0 || referee.RefererId == 0 {
|
||||
return
|
||||
}
|
||||
_ = l.grantGiftDays(ctx, referee, int(giftDays), orderNo, "邀请赠送")
|
||||
@@ -1312,3 +1336,18 @@ func (l *ActivateOrderLogic) RedemptionActivate(ctx context.Context, orderInfo *
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isNewUserOnlyForQuantity checks whether the matched discount tier has new_user_only enabled.
|
||||
func isNewUserOnlyForQuantity(discounts []internaltypes.SubscribeDiscount, inputQuantity int64) bool {
|
||||
var finalDiscount float64 = 100
|
||||
var newUserOnly bool
|
||||
|
||||
for _, d := range discounts {
|
||||
if inputQuantity >= d.Quantity && d.Discount < finalDiscount {
|
||||
finalDiscount = d.Discount
|
||||
newUserOnly = d.NewUserOnly
|
||||
}
|
||||
}
|
||||
|
||||
return newUserOnly
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user