gameShield.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package task
  2. import (
  3. "context"
  4. v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
  5. "github.com/go-nunu/nunu-layout-advanced/internal/repository"
  6. "github.com/go-nunu/nunu-layout-advanced/internal/service"
  7. "go.uber.org/zap"
  8. "strconv"
  9. "time"
  10. )
  11. type GameShieldTask interface {
  12. CheckGameShield(ctx context.Context) error
  13. SyncAllExpireTimeFromHost(ctx context.Context) error
  14. }
  15. func NewGameShieldTask(
  16. task *Task,
  17. gameShieldRepo repository.GameShieldRepository,
  18. gameShieldBackendService service.GameShieldBackendService,
  19. ) GameShieldTask {
  20. return &gameShieldTask{
  21. Task: task,
  22. gameShieldRepo: gameShieldRepo,
  23. gameShieldBackendService: gameShieldBackendService,
  24. }
  25. }
  26. type gameShieldTask struct {
  27. *Task
  28. gameShieldRepo repository.GameShieldRepository
  29. gameShieldBackendService service.GameShieldBackendService
  30. }
  31. // 检查已过期的记录
  32. func (t gameShieldTask) CheckExpiredGameShields(ctx context.Context) error {
  33. // 获取已过期的商品
  34. expiredShields, err := t.gameShieldRepo.GetExpiredGameShields(ctx)
  35. if err != nil {
  36. t.logger.Error("查询已过期的游戏盾失败", zap.Error(err))
  37. return err
  38. }
  39. t.logger.Info("找到已过期的游戏盾商品", zap.Int("数量", len(expiredShields)))
  40. // 遍历已过期的商品
  41. for _, shield := range expiredShields {
  42. t.logger.Info("已过期商品",
  43. zap.Int("ID", shield.Id),
  44. zap.Int("用户ID", shield.Uid),
  45. zap.String("商品", shield.AppName),
  46. zap.Time("过期时间", time.Unix(shield.ExpireTime, 0)))
  47. // 检查用户是否已续费(检查nextduedate字段)
  48. nextduedate, err := t.gameShieldRepo.GetGameShieldNextduedate(ctx, int64(shield.Uid), shield.HostId)
  49. if err != nil {
  50. t.logger.Error("获取nextduedate失败", zap.Int("用户ID", shield.Uid), zap.Error(err))
  51. continue
  52. }
  53. nextduedateTime, err := strconv.ParseInt(nextduedate, 10, 64)
  54. if err != nil {
  55. t.logger.Error("解析nextduedate失败", zap.Error(err))
  56. continue
  57. }
  58. currentTime := time.Now().Unix()
  59. renewed := nextduedateTime > currentTime
  60. if renewed {
  61. // 已过期但已续费,更新过期时间
  62. shield.ExpireTime = nextduedateTime
  63. if err := t.gameShieldRepo.UpdateGameShield(ctx, shield); err != nil {
  64. t.logger.Error("更新过期游戏盾的过期时间失败",
  65. zap.String("商品", shield.AppName),
  66. zap.Error(err))
  67. continue
  68. }
  69. // 更新蜗牛的过期时间
  70. if _, _, err := t.gameShieldBackendService.GameShieldBackend(ctx, &v1.GameShieldBackendArrayRequest{Uid: shield.Uid, HostId: shield.HostId, Items: nil}); err != nil {
  71. t.logger.Error("更新shd_game_shield_backend表失败", zap.Int("产品id:", shield.HostId), zap.Int("用户id:", shield.Uid), zap.String("商品名:", shield.AppName), zap.Error(err))
  72. continue
  73. }
  74. t.logger.Info("已过期商品续期成功",
  75. zap.Int("用户ID", shield.Uid),
  76. zap.String("商品", shield.AppName),
  77. zap.Time("新过期时间", time.Unix(nextduedateTime, 0)))
  78. } else {
  79. // 已过期且未续费,执行过期操作
  80. t.logger.Info("商品已过期且未续费",
  81. zap.Int("用户ID", shield.Uid),
  82. zap.String("商品", shield.AppName))
  83. // TODO: 添加您的过期处理逻辑,例如:
  84. // - 发送过期通知
  85. // - 禁用服务
  86. // - 标记记录状态
  87. }
  88. }
  89. return nil
  90. }
  91. // CheckSoonExpiredGameShields 检查即将过期的记录并处理续费
  92. func (t gameShieldTask) CheckSoonExpiredGameShields(ctx context.Context) error {
  93. // 获取7天内即将过期的商品
  94. soonExpiredShields, err := t.gameShieldRepo.GetSoonExpiredGameShields(ctx, 1)
  95. if err != nil {
  96. t.logger.Error("查询即将过期的游戏盾失败", zap.Error(err))
  97. return err
  98. }
  99. t.logger.Info("找到 %d 个即将过期的游戏盾商品", zap.Int("数量", len(soonExpiredShields)))
  100. // 遍历即将过期的商品
  101. for _, shield := range soonExpiredShields {
  102. t.logger.Info("即将过期商品",
  103. zap.Int("ID", shield.Id),
  104. zap.Int("用户ID", shield.Uid),
  105. zap.String("商品", shield.AppName),
  106. zap.Int("主机ID", shield.HostId),
  107. zap.Time("过期时间", time.Unix(shield.ExpireTime, 0)))
  108. currentTime := time.Now().Unix()
  109. // 检查用户是否已续费(检查nextduedate字段)
  110. nextduedate, err := t.gameShieldRepo.GetGameShieldNextduedate(ctx, int64(shield.Uid), shield.HostId)
  111. nextduedateTime, err := strconv.ParseInt(nextduedate, 10, 64)
  112. if err != nil {
  113. t.logger.Error("解析nextduedate失败", zap.Error(err))
  114. continue
  115. }
  116. renewed := nextduedateTime > currentTime
  117. if renewed {
  118. // 用户已续费,更新shd_game_shield表中的ExpireTime字段
  119. // 使用shd_host表中的nextduedate作为新的过期时间
  120. shield.ExpireTime = nextduedateTime
  121. if err := t.gameShieldRepo.UpdateGameShield(ctx, shield); err != nil {
  122. t.logger.Error("更新shd_game_shield表失败: %v", zap.Error(err))
  123. continue
  124. }
  125. // 更新蜗牛的过期时间
  126. if _, _, err := t.gameShieldBackendService.GameShieldBackend(ctx, &v1.GameShieldBackendArrayRequest{Uid: shield.Uid, HostId: shield.HostId, Items: nil}); err != nil {
  127. t.logger.Error("更新shd_game_shield_backend表失败", zap.Int("产品id:", shield.HostId), zap.Int("用户id:", shield.Uid), zap.String("商品名:", shield.AppName), zap.Error(err))
  128. continue
  129. }
  130. t.logger.Info("自动续期成功: ",
  131. zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Time("新过期时间", time.Unix(shield.ExpireTime, 0)))
  132. } else {
  133. // 用户未续费,可以发送提醒通知
  134. t.logger.Info("用户未续费:", zap.Int("用户ID", shield.Uid), zap.String("商品", shield.AppName), zap.Int("hostid", shield.HostId))
  135. }
  136. }
  137. return nil
  138. }
  139. // SyncAllExpireTimeFromHost 同步所有记录的过期时间
  140. func (t gameShieldTask) SyncAllExpireTimeFromHost(ctx context.Context) error {
  141. // 获取所有游戏盾记录
  142. shields, err := t.gameShieldRepo.GetAllGameShield(ctx)
  143. if err != nil {
  144. t.logger.Error("查询所有游戏盾记录失败", zap.Error(err))
  145. return err
  146. }
  147. t.logger.Info("找到 %d 条游戏盾记录", zap.Int("数量", len(shields)))
  148. // 同步每条记录的过期时间
  149. for _, shield := range shields {
  150. if err := t.gameShieldRepo.SyncExpireTimeFromHostNextDueDate(ctx, shield.Uid, shield.HostId); err != nil {
  151. t.logger.Error("同步记录过期时间失败: %v", zap.Int("ID", shield.Id), zap.Error(err))
  152. continue
  153. }
  154. t.logger.Info("同步记录过期时间成功", zap.Int("ID", shield.Id))
  155. }
  156. return nil
  157. }
  158. // 综合处理已过期和即将过期的记录
  159. func (t gameShieldTask) CheckGameShield(ctx context.Context) error {
  160. // 先检查已过期的记录
  161. if err := t.CheckExpiredGameShields(ctx); err != nil {
  162. return err
  163. }
  164. // 再检查即将过期的记录
  165. if err := t.CheckSoonExpiredGameShields(ctx); err != nil {
  166. return err
  167. }
  168. return nil
  169. }