feat: 添加账号临时停用功能,429请求会临时停用10分钟,24小时内出现5次429,封禁账号

This commit is contained in:
danial
2024-09-06 10:04:18 +08:00
parent 3115fc6743
commit 6e3750757d
7 changed files with 84 additions and 17 deletions

View File

@@ -6,18 +6,21 @@ const (
AppleCardUserAccountMinBalance float64 = 1000
AppleOrderMaxDistributionCount int = 5
AppleTmpSoppedMaxCount int = 5
)
// AppleAccountStatus 账号状态编码
type AppleAccountStatus int32
const (
AppleAccountForbidden AppleAccountStatus = iota + 1 // 账号禁用
AppleAccountNormal // 账号正常
AppleAccountWrongPassword // 账号密码错误
AppleAccountLimited // 账号受到限制
AppleAccountForbiddenByLowRecharge // 由于低于50元以下充值导致
AppleAccountForbiddenBySafetyReason // 账号安全原因
AppleAccountForbidden AppleAccountStatus = iota + 1 // 账号禁用
AppleAccountNormal // 账号正常
AppleAccountWrongPassword // 账号密码错误
AppleAccountLimited // 账号受到限制
AppleAccountForbiddenByLowRecharge // 由于低于50元以下充值导致
AppleAccountForbiddenBySafetyReason // 账号安全原因
AppleAccountTmpStoppedByTooManyRequest // 账号临时暂停兑换10分钟后恢复
AppleAccountForbiddenByTooManyRecharge // 账号永久禁止充值
)
// AppleRechargeOrderStatus 充值编码
@@ -75,6 +78,7 @@ const (
AppleRechargeItunesStatusSuccess AppleRechargeItunesStatus = 20 // 订单处理成功
AppleRechargeItunesRefund AppleRechargeItunesStatus = 30 // 订单退回,状态未知
AppleRechargeItunesRefundWithAccountLimited AppleRechargeItunesStatus = 31 // 订单退回,账号额度受到限制
AppleRechargeItunesRefundWithRequestTooMany AppleRechargeItunesStatus = 32 // 订单退回,账号请求过多
)
type AppleRechargeOperation string

View File

@@ -3,16 +3,16 @@ package apple_card_info
import (
"context"
"fmt"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/os/gcron"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/os/gtime"
v1 "kami/api/apple_card_info/v1"
"kami/internal/consts"
"kami/internal/errHandler"
"kami/internal/model"
"kami/internal/service"
"github.com/gogf/gf/v2/errors/gcode"
"kami/utility/cache"
)
func (c *ControllerV1) RechargeItunesCallback(ctx context.Context, req *v1.RechargeItunesCallbackReq) (res *v1.RechargeItunesCallbackRes, err error) {
@@ -47,7 +47,7 @@ func (c *ControllerV1) RechargeItunesCallback(ctx context.Context, req *v1.Recha
Operation: consts.AppleRechargeOperationWrongPassword,
Remark: req.Remark,
}, nil)
case consts.AppleRechargeItunesRefund, consts.AppleRechargeItunesRefundWithAccountLimited:
case consts.AppleRechargeItunesRefund, consts.AppleRechargeItunesRefundWithAccountLimited, consts.AppleRechargeItunesRefundWithRequestTooMany:
if req.Status == consts.AppleRechargeItunesRefundWithAccountLimited {
req.Remark = fmt.Sprintf("%s%s", "账号受到限制", req.Remark)
}
@@ -66,6 +66,18 @@ func (c *ControllerV1) RechargeItunesCallback(ctx context.Context, req *v1.Recha
_ = appleAccountService.ModifyStatus(ctx, orderEntity.AccountId, consts.AppleAccountLimited, nil)
_ = rechargeOrderService.DecrementDistributionCount(ctx, orderEntity.OrderNo)
}
if req.Status == consts.AppleRechargeItunesRefundWithRequestTooMany {
_ = rechargeOrderService.DecrementDistributionCount(ctx, orderEntity.OrderNo)
cacheN := cache.NewCache()
result, _ := cacheN.Get(ctx, fmt.Sprintf("%s:%s", cache.ItunesAccountTmpStopped, orderEntity.AccountName))
if result != nil && !result.IsNil() && result.Int() > consts.AppleTmpSoppedMaxCount {
_ = appleAccountService.ModifyStatus(ctx, orderEntity.AccountId, consts.AppleAccountForbiddenByTooManyRecharge, nil)
} else {
_ = appleAccountService.ModifyStatus(ctx, orderEntity.AccountId, consts.AppleAccountTmpStoppedByTooManyRequest, nil)
_ = cacheN.Incr(ctx, fmt.Sprintf("%s:%s", cache.ItunesAccountTmpStopped, orderEntity.AccountName), gtime.D)
}
}
// 移除之前的定时器
case consts.AppleRechargeItunesStatusSuccess:
// 如果当前订单已经处理成功,则不处理

View File

@@ -220,3 +220,28 @@ func (a *sAppleAccount) GetListByStatus(ctx context.Context, status consts.Apple
func (a *sAppleAccount) CheckIsNormal(ctx context.Context, accountId string) {
}
// HandleTmpStoppedList 处理临时暂停账号
func (h *sAppleAccount) HandleTmpStoppedList(ctx context.Context) (err error) {
dataList := make([]entity.V1CardAppleAccountInfo, 0)
err = dao.V1CardAppleAccountInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
Where(dao.V1CardAppleAccountInfo.Columns().Status, consts.AppleAccountTmpStoppedByTooManyRequest).
WhereLT(dao.V1CardAppleAccountInfo.Columns().UpdatedAt, gtime.Now().Add(-10*gtime.M)).
Scan(&dataList)
if err != nil {
glog.Error(ctx, dataList, err)
return
}
for _, info := range dataList {
err = config.GetDatabaseV1().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
if err2 := h.ModifyStatus(ctx, info.Id, consts.AppleAccountNormal, tx); err2 != nil {
return err2
}
return nil
})
if err != nil {
glog.Error(ctx, "苹果账号:"+info.Id+info.Account, err)
}
}
return
}

View File

@@ -38,6 +38,8 @@ type (
GetListByStatus(ctx context.Context, status consts.AppleAccountStatus) (data []entity.V1CardAppleAccountInfo, err error)
// CheckIsNormal 查询当前账户是否正常
CheckIsNormal(ctx context.Context, accountId string)
// HandleTmpStoppedList 处理临时暂停账号
HandleTmpStoppedList(ctx context.Context) (err error)
// GetNextUser 从sysUser表中查询所有用户获取排序后的当前用户后面下一个Id
GetNextUser(ctx context.Context, originalUserId string, amount decimal.Decimal) (targetId string, err error)
SetCurrentTargetAccount(ctx context.Context, machineId string, m model.AccountIdInfo) (err error)

View File

@@ -1,16 +1,40 @@
package cache
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcache"
"time"
)
var cache *gcache.Cache
type Cache struct {
*gcache.Cache
}
func NewCache() *gcache.Cache {
var cache *Cache
const (
ItunesAccountTmpStopped string = "itunes_account_tmp_stopped"
)
func NewCache() *Cache {
if cache == nil {
cache = gcache.New()
gcache.New()
cache = &Cache{
Cache: gcache.New(),
}
cache.SetAdapter(gcache.NewAdapterRedis(g.Redis()))
}
return cache
}
// Incr 设置计数器缓存
func (i *Cache) Incr(ctx context.Context, key string, duration time.Duration) (err error) {
result, err := i.Get(ctx, key)
if result == nil || result.IsNil() {
_ = i.Set(ctx, key, 1, duration)
return
}
_, _, err = i.Update(ctx, key, result.Int()+1)
return
}

View File

@@ -15,7 +15,8 @@ func RegisterCron(ctx context.Context) {
_ = service.AppleAccount().ResetStatus(ctx, nil)
})
_, _ = gcron.Add(ctx, "@every 10m", func(ctx context.Context) {
glog.Info(ctx, "每10分钟执行处理等待充值订单")
glog.Info(ctx, "每10分钟执行处理等待充值订单和账号")
_ = service.RechargeHistory().HandleWaitingList(ctx)
_ = service.AppleAccount().HandleTmpStoppedList(ctx)
})
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/gogf/gf/v2/os/glog"
"kami/utility/config"
notify "kami/utility/notify/impl"
)
type Notification interface {
@@ -25,8 +24,8 @@ func NewClient(ctx context.Context) *Notification {
panic(gerror.Wrap(err, "初始化通知失败"))
}
switch model.Platform {
case "feishu":
client = notify.Feishu{}
//case "feishu":
// client = notify.Feishu{}
default:
glog.Error(ctx, "不支持的平台")
}