package task import ( "context" v1 "github.com/go-nunu/nunu-layout-advanced/api/v1" "github.com/go-nunu/nunu-layout-advanced/internal/repository" "github.com/go-nunu/nunu-layout-advanced/internal/service/api/gameShield" "go.uber.org/zap" "strconv" "time" ) type GameShieldTask interface { CheckGameShield(ctx context.Context) error SyncAllExpireTimeFromHost(ctx context.Context) error } func NewGameShieldTask( task *Task, gameShieldRepo repository.GameShieldRepository, gameShieldBackendService gameShield.GameShieldBackendService, ) GameShieldTask { return &gameShieldTask{ Task: task, gameShieldRepo: gameShieldRepo, gameShieldBackendService: gameShieldBackendService, } } type gameShieldTask struct { *Task gameShieldRepo repository.GameShieldRepository gameShieldBackendService gameShield.GameShieldBackendService } // 检查已过期的记录 func (t gameShieldTask) CheckExpiredGameShields(ctx context.Context) error { // 获取已过期的商品 expiredShields, err := t.gameShieldRepo.GetExpiredGameShields(ctx) if err != nil { t.logger.Error("查询已过期的游戏盾失败", zap.Error(err)) return err } t.logger.Info("找到已过期的游戏盾商品", zap.Int("数量", len(expiredShields))) // 遍历已过期的商品 for _, shield := range expiredShields { t.logger.Info("已过期商品", zap.Int("ID", shield.Id), zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Time("过期时间", time.Unix(shield.ExpireTime, 0))) // 检查用户是否已续费(检查nextduedate字段) nextduedate, err := t.gameShieldRepo.GetGameShieldNextduedate(ctx, int64(shield.Uid), shield.HostId) if err != nil { t.logger.Error("获取nextduedate失败", zap.Int("用户ID", shield.Uid), zap.Error(err)) continue } nextduedateTime, err := strconv.ParseInt(nextduedate, 10, 64) if err != nil { t.logger.Error("解析nextduedate失败", zap.Error(err)) continue } currentTime := time.Now().Unix() renewed := nextduedateTime > currentTime if renewed { // 已过期但已续费,更新过期时间 shield.ExpireTime = nextduedateTime if err := t.gameShieldRepo.UpdateGameShield(ctx, shield); err != nil { t.logger.Error("更新过期游戏盾的过期时间失败", zap.String("商品", shield.AppName), zap.Error(err)) continue } // 更新蜗牛的过期时间 if _, _, err := t.gameShieldBackendService.GameShieldBackend(ctx, &v1.GameShieldBackendArrayRequest{Uid: shield.Uid, HostId: shield.HostId, Items: nil}); err != nil { t.logger.Error("更新shd_game_shield_backend表失败", zap.Int("产品id:", shield.HostId), zap.Int("用户id:", shield.Uid), zap.String("商品名:", shield.AppName), zap.Error(err)) continue } t.logger.Info("已过期商品续期成功", zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Time("新过期时间", time.Unix(nextduedateTime, 0))) } else { // 已过期且未续费,执行过期操作 t.logger.Info("商品已过期且未续费", zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName)) // TODO: 添加您的过期处理逻辑,例如: // - 发送过期通知 // - 禁用服务 // - 标记记录状态 } } return nil } // CheckSoonExpiredGameShields 检查即将过期的记录并处理续费 func (t gameShieldTask) CheckSoonExpiredGameShields(ctx context.Context) error { // 获取7天内即将过期的商品 soonExpiredShields, err := t.gameShieldRepo.GetSoonExpiredGameShields(ctx, 1) if err != nil { t.logger.Error("查询即将过期的游戏盾失败", zap.Error(err)) return err } t.logger.Info("找到 %d 个即将过期的游戏盾商品", zap.Int("数量", len(soonExpiredShields))) // 遍历即将过期的商品 for _, shield := range soonExpiredShields { t.logger.Info("即将过期商品", zap.Int("ID", shield.Id), zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Int("主机ID", shield.HostId), zap.Time("过期时间", time.Unix(shield.ExpireTime, 0))) currentTime := time.Now().Unix() // 检查用户是否已续费(检查nextduedate字段) nextduedate, err := t.gameShieldRepo.GetGameShieldNextduedate(ctx, int64(shield.Uid), shield.HostId) nextduedateTime, err := strconv.ParseInt(nextduedate, 10, 64) if err != nil { t.logger.Error("解析nextduedate失败", zap.Error(err)) continue } renewed := nextduedateTime > currentTime if renewed { // 用户已续费,更新shd_game_shield表中的ExpireTime字段 // 使用shd_host表中的nextduedate作为新的过期时间 shield.ExpireTime = nextduedateTime if err := t.gameShieldRepo.UpdateGameShield(ctx, shield); err != nil { t.logger.Error("更新shd_game_shield表失败: %v", zap.Error(err)) continue } // 更新蜗牛的过期时间 if _, _, err := t.gameShieldBackendService.GameShieldBackend(ctx, &v1.GameShieldBackendArrayRequest{Uid: shield.Uid, HostId: shield.HostId, Items: nil}); err != nil { t.logger.Error("更新shd_game_shield_backend表失败", zap.Int("产品id:", shield.HostId), zap.Int("用户id:", shield.Uid), zap.String("商品名:", shield.AppName), zap.Error(err)) continue } t.logger.Info("自动续期成功: ", zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Time("新过期时间", time.Unix(shield.ExpireTime, 0))) } else { // 用户未续费,可以发送提醒通知 t.logger.Info("用户未续费:", zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Int("hostid", shield.HostId)) } } return nil } // SyncAllExpireTimeFromHost 同步所有记录的过期时间 func (t gameShieldTask) SyncAllExpireTimeFromHost(ctx context.Context) error { // 获取所有游戏盾记录 shields, err := t.gameShieldRepo.GetAllGameShield(ctx) if err != nil { t.logger.Error("查询所有游戏盾记录失败", zap.Error(err)) return err } t.logger.Info("找到 %d 条游戏盾记录", zap.Int("数量", len(shields))) // 同步每条记录的过期时间 for _, shield := range shields { if err := t.gameShieldRepo.SyncExpireTimeFromHostNextDueDate(ctx, shield.Uid, shield.HostId); err != nil { t.logger.Error("同步记录过期时间失败: %v", zap.Int("ID", shield.Id), zap.Error(err)) continue } t.logger.Info("同步记录过期时间成功", zap.Int("ID", shield.Id)) } return nil } // 综合处理已过期和即将过期的记录 func (t gameShieldTask) CheckGameShield(ctx context.Context) error { // 先检查已过期的记录 if err := t.CheckExpiredGameShields(ctx); err != nil { return err } // 再检查即将过期的记录 if err := t.CheckSoonExpiredGameShields(ctx); err != nil { return err } return nil }