|
@@ -1 +1,183 @@
|
|
|
package task
|
|
|
+
|
|
|
+import (
|
|
|
+ "context"
|
|
|
+ "github.com/go-nunu/nunu-layout-advanced/internal/repository"
|
|
|
+ "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,
|
|
|
+
|
|
|
+) GameShieldTask {
|
|
|
+ return &gameShieldTask{
|
|
|
+ Task: task,
|
|
|
+ gameShieldRepo: gameShieldRepo,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+type gameShieldTask struct {
|
|
|
+ *Task
|
|
|
+ gameShieldRepo repository.GameShieldRepository
|
|
|
+}
|
|
|
+
|
|
|
+// 检查已过期的记录
|
|
|
+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
|
|
|
+ }
|
|
|
+
|
|
|
+ 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, 7)
|
|
|
+ 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.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
|
|
|
+ }
|
|
|
+
|
|
|
+ t.logger.Info("自动续期成功: 用户ID=%d, 商品=%s, 新过期时间=%v",
|
|
|
+ zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Time("新过期时间", time.Unix(shield.ExpireTime, 0)))
|
|
|
+ } else {
|
|
|
+ // 用户未续费,可以发送提醒通知
|
|
|
+ t.logger.Info("用户未续费: 用户ID=%d, 商品=%s", zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ 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("同步记录 ID=%d 的过期时间失败: %v", zap.Int("ID", shield.Id), zap.Error(err))
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ t.logger.Info("同步记录 ID=%d 的过期时间成功", 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
|
|
|
+}
|