package service import ( "errors" "fmt" "go-admin/app/admin/models" "go-admin/app/admin/service/dto" "go-admin/utils/utility" "github.com/go-admin-team/go-admin-core/sdk/service" "github.com/shopspring/decimal" "gorm.io/gorm" ) type MemberRenewalLog struct { service.Service } // 定时过期 func (e MemberRenewalLog) ExpireProxy() error { if err := e.Orm.Exec("UPDATE member_proxy SET status =2 WHERE expired < NOW() AND status =1").Error; err != nil { return err } return nil } // AutoRenewal 自动续费 func (e *MemberRenewalLog) AutoRenewal() error { proxyService := MemberProxy{Service: e.Service} balanceService := MemberBalance{Service: e.Service} configService := SysConfig{Service: e.Service} configResp := dto.GetSysConfigByKEYForServiceResp{} configService.GetWithKey(&dto.SysConfigByKeyReq{ConfigKey: "ip_renew_deduction_standard"}, &configResp) if configResp.ConfigValue == "" { e.Log.Error("没有设置扣费标准,不自动续期") return nil } amount, err := decimal.NewFromString(configResp.ConfigValue) if err != nil { e.Log.Error("扣费标准设置错误,不自动续期") return nil } autoProxys, err := proxyService.GetAutoRenewalProxys() if err != nil { e.Log.Errorf("获取需要自动续费的代理,%v", err) return err } if len(autoProxys) == 0 { return nil } userIds := make([]int, 0) for _, proxy := range autoProxys { if !utility.ContainsInt(userIds, proxy.UserId) { userIds = append(userIds, proxy.UserId) } } userBalanceMap := balanceService.GetUserBalanceMap(userIds) if userBalanceMap == nil { e.Log.Error("用户余额获取失败,userBalanceMap 为 nil") return fmt.Errorf("userBalanceMap is nil") } for _, proxy := range autoProxys { if proxy.Type == 0 { continue } if balance, ok := userBalanceMap[proxy.UserId]; ok { if balance.GreaterThan(decimal.Zero) { err = e.DoRenewal(proxy, amount) if err == nil { userBalanceMap[proxy.UserId] = balance.Sub(amount) } } } } return nil } // 执行续费 func (e *MemberRenewalLog) DoRenewal(proxy models.MemberProxy, amount decimal.Decimal) error { renewalLog := models.MemberRenewalLog{} renewalLog.UserId = proxy.UserId renewalLog.Type = proxy.Type renewalLog.Amount = amount renewalLog.Day = 30 renewalLog.ProxyId = proxy.Id cliproxyService := CliProxyService{Service: e.Service} err := e.Orm.Transaction(func(tx *gorm.DB) error { if err := tx.Save(&renewalLog).Error; err != nil { return err } db := tx.Exec("UPDATE member_balance SET balance = balance -? WHERE user_id =? AND balance >= ?", amount, proxy.UserId, amount) if db.RowsAffected != 1 { e.Log.Errorf("续费扣费失败,ip:%s,err:%s", proxy.Ip, "余额不足") return errors.New("余额不足") } if db.Error != nil { e.Log.Errorf("续费扣费失败,ip:%s,err:%s", proxy.Ip, db.Error.Error()) return db.Error } if err := tx.Model(&proxy).Update("expired", proxy.Expired.AddDate(0, 0, 30)).Error; err != nil { e.Log.Errorf("续费修改过期时间失败,ip:%s,err:%s", proxy.Ip, err.Error()) return err } if err := cliproxyService.Renewal(proxy.Ip, 30); err != nil { e.Log.Errorf("续费失败,ip:%s,err:%s", proxy.Ip, err.Error()) return err } return nil }) return err } // UserRenewal 用户续费 func (e *MemberRenewalLog) UserRenewal(req *dto.MemberProxyUserRenewalReq, userId int) (decimal.Decimal, error) { configService := SysConfig{Service: e.Service} configResp := dto.GetSysConfigByKEYForServiceResp{} configService.GetWithKey(&dto.SysConfigByKeyReq{ConfigKey: "ip_renew_deduction_standard"}, &configResp) if configResp.ConfigValue == "" { e.Log.Error("没有设置扣费标准,无法续期") return decimal.Zero, nil } amount, err := decimal.NewFromString(configResp.ConfigValue) if err != nil { e.Log.Error("扣费标准设置错误,无法续期") return decimal.Zero, errors.New("续费失败,请联系管理员") } balanceService := MemberBalance{Service: e.Service} balance := balanceService.GetBalance(userId) if balance.GreaterThan(amount) { } else { return balance, errors.New("余额不足,请充值") } proxyService := MemberProxy{Service: e.Service} proxy, err := proxyService.GetProxyById(req.ProxyId) if err != nil { return balance, errors.New("代理不存在") } if proxy.Type == 0 { return balance, errors.New("短效ip不支持续费") } err = e.DoRenewal(proxy, amount) return balance, err }