feat: 添加账号临时停用功能,429请求会临时停用10分钟,24小时内出现5次429,封禁账号
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
// 如果当前订单已经处理成功,则不处理
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
30
utility/cache/cache.go
vendored
30
utility/cache/cache.go
vendored
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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, "不支持的平台")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user