goods.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. package model
  2. import (
  3. "active/constant"
  4. "active/tools"
  5. "database/sql"
  6. "encoding/json"
  7. "fmt"
  8. "strconv"
  9. "strings"
  10. "sync"
  11. "time"
  12. "git.jiaxianghudong.com/go/gsdkclient"
  13. "git.jiaxianghudong.com/go/logs"
  14. "git.jiaxianghudong.com/go/xlog"
  15. "git.jiaxianghudong.com/webs/pkg/dbx"
  16. "git.jiaxianghudong.com/webs/pkg/rds"
  17. )
  18. //GoodsCache 调用到的计费点缓存
  19. var GoodsCache sync.Map
  20. var PayBlackCache sync.Map
  21. //PayBlackCacheNew 锁机制
  22. var PayBlackCacheNew *PbCacheMap
  23. var VerIPBlackCacheNew *VerIpCacheMap
  24. const MaxIpNum = 50
  25. type PbCacheMap struct {
  26. Data map[int]int
  27. Lock *sync.RWMutex
  28. }
  29. func NewPayBlackCacheNew() *PbCacheMap {
  30. return &PbCacheMap{
  31. Data: make(map[int]int),
  32. Lock: &sync.RWMutex{},
  33. }
  34. }
  35. func (d *PbCacheMap) Get(k int) (int, bool) {
  36. d.Lock.RLock()
  37. defer d.Lock.RUnlock()
  38. v, ok := d.Data[k]
  39. return v, ok
  40. }
  41. func (d *PbCacheMap) Set(k int, v int) {
  42. d.Lock.Lock()
  43. defer d.Lock.Unlock()
  44. d.Data[k] = v
  45. }
  46. type VerIpCacheMap struct {
  47. Data map[string][]string
  48. Lock *sync.RWMutex
  49. }
  50. func NewVerIpCacheNew() *VerIpCacheMap {
  51. return &VerIpCacheMap{
  52. Data: make(map[string][]string),
  53. Lock: &sync.RWMutex{},
  54. }
  55. }
  56. func (d *VerIpCacheMap) Get(k string) ([]string, bool) {
  57. d.Lock.RLock()
  58. defer d.Lock.RUnlock()
  59. v, ok := d.Data[k]
  60. return v, ok
  61. }
  62. func (d *VerIpCacheMap) Set(k string, v []string) {
  63. d.Lock.Lock()
  64. defer d.Lock.Unlock()
  65. d.Data[k] = v
  66. }
  67. //BlackIPDuan 审核人员IP段
  68. var BlackIPDuan = []string{"182.254.115", "59.37.125"}
  69. //BlackIPs 审核人员IP
  70. var BlackIPs = []string{"111.222.19.134"}
  71. var TestUserIDS = []int{101832265, 125660976, 101758654, 101616296, 56409319}
  72. func GetBlackByVerIP(ver, ip string, appid int) bool {
  73. vkey := fmt.Sprintf("%d-%s", appid, ver)
  74. //判断大于 50个不同IP就返回 黑名单关闭
  75. if barr, ok := VerIPBlackCacheNew.Get(vkey); !ok {
  76. VerIPBlackCacheNew.Set(vkey, []string{ip})
  77. return true
  78. } else {
  79. if len(barr) >= MaxIpNum {
  80. return false
  81. } else {
  82. //未达到50次
  83. if !tools.InStringArray(ip, barr) {
  84. barr = append(barr, ip)
  85. VerIPBlackCacheNew.Set(vkey, barr)
  86. }
  87. return true
  88. }
  89. }
  90. }
  91. //GetGoods 获取计费点缓存
  92. func GetGoods(vcfrom string) map[string]interface{} {
  93. //先读取缓存
  94. var goodsret string
  95. goodsKey := fmt.Sprintf("%s%s", vcfrom, constant.GOODSKEY)
  96. if data, ok := GoodsCache.Load(goodsKey); ok {
  97. logs.Debugf("cache key: %s", goodsKey)
  98. return data.(map[string]interface{})
  99. }
  100. allgoods := make(map[string]interface{})
  101. goodsret = rds.Redis8.Get(goodsKey).Val()
  102. err := json.Unmarshal([]byte(goodsret), &allgoods)
  103. if err != nil {
  104. logs.Error(fmt.Sprintf("goodsret: %s err: %v", goodsret, err))
  105. return allgoods
  106. }
  107. var goodsconfigs = make(map[string]interface{})
  108. if data, ok := allgoods[constant.GOODSVERSION]; ok {
  109. if val, ok := data.(map[string]interface{}); ok {
  110. goodsconfigs = val
  111. }
  112. }
  113. fmt.Printf("【goods configs】: key:%s %+v", goodsKey, goodsconfigs)
  114. GoodsCache.Store(goodsKey, goodsconfigs)
  115. return goodsconfigs
  116. }
  117. //InBlacklist 获取黑名单
  118. func InBlacklist(userid string) bool {
  119. if data, ok := PayBlackCache.Load(constant.PAYBLACKLIST); ok {
  120. logs.Debugf("PayBlackCache cache key: %s", constant.PAYBLACKLIST)
  121. return tools.InStringArray(userid, data.([]string))
  122. }
  123. blist := rds.Redis8.SMembers(constant.PAYBLACKLIST).Val()
  124. fmt.Printf(" \n【pay black configs】: %+v", blist)
  125. PayBlackCache.Store(constant.PAYBLACKLIST, blist)
  126. return tools.InStringArray(userid, blist)
  127. }
  128. //GetBlackList 获取黑名单
  129. func GetBlackList(userid string, ip, UA string) bool {
  130. var ipDuan string
  131. ipArr := strings.Split(ip, ".")
  132. if len(ipArr) >= 3 {
  133. ipDuan = strings.Join(ipArr[0:3], ".")
  134. }
  135. // 1. 根据ip段来判断如果是黑名单IP段, 用户直接拉入黑名单
  136. if GetBlackIPDuanCache(ipDuan) {
  137. var count int
  138. uID, _ := strconv.Atoi(userid)
  139. userInfo := gsdkclient.Client().UserInfoNoLoginData(uID)
  140. temp := gsdkclient.Client().GetEffortEx(uint(uID), []int{2}, false) //获取局数
  141. if temp != nil {
  142. count = int(temp[2]) //局数
  143. }
  144. xlog.Infof("【 黑名单网段玩家 】 %v ip:%s agent:%v", userid, ip, UA)
  145. if userIp := rds.Redis8.HGet(constant.PAYBLACKUSERHASH, userid).Val(); userIp != "" {
  146. rds.Redis8.HSet(constant.PAYBLACKUSERHASHTMP, userid, fmt.Sprintf("%s|局数:%d|注册时间:%s", ip, count, userInfo.RegDate))
  147. }
  148. return true
  149. }
  150. if userIp := rds.Redis8.HGet(constant.PAYBLACKUSERHASH, userid).Val(); userIp != "" {
  151. xlog.Infof("【 审核玩家 】 %v ip:%s agent:%v", userid, ip, UA)
  152. rds.Redis8.HIncrBy(constant.PAYBLACKIPHASH, ip, 1) //黑名单玩家计入使用该ip次数
  153. return true
  154. }
  155. // hour := time.Now().Hour() //高峰期不执行查询操作, 小于晚上8点,或者大于等于10点 进行特定IP认证
  156. // if hour < 20 || hour >= 22 {
  157. // //2. 不是IP段再确认玩家是否黑名单玩家
  158. // if userIp := rds.Redis8.HGet(constant.PAYBLACKUSERHASH, userid).Val(); userIp != "" {
  159. // rds.Redis8.HIncrBy(constant.PAYBLACKIPHASH, ip, 1) //黑名单玩家计入使用该ip次数
  160. // return true
  161. // }
  162. // // //3. 不是黑名单玩家再判断是否 具体黑名单IP并且达到拉黑值
  163. // // if blackip := rds.Redis8.HGet(constant.PAYBLACKIPHASH, ip).Val(); blackip != "" { //观察黑名单IP列表名单
  164. // // if c, _ := strconv.Atoi(blackip); c >= 5 { //超过黑名单IP次数,加入黑名单用户
  165. // // rds.Redis8.HSet(constant.PAYBLACKUSERHASH, userid, ip)
  166. // // return true
  167. // // }
  168. // // }
  169. // }
  170. return false
  171. }
  172. //GetBlackIPDuanCache 获取黑名单ip段缓存
  173. func GetBlackIPDuanCache(ipDuan string) bool {
  174. // if data, ok := PayBlackIPDuanCache.Load(constant.PAYBLACKIPRANGE); ok {
  175. // logs.Debugf("PayBlackIPDuanCache cache key: %s", constant.PAYBLACKIPRANGE)
  176. // return tools.InStringArray(ipDuan, data.([]string))
  177. // }
  178. //blist := rds.Redis8.SMembers(constant.PAYBLACKIPRANGE).Val()
  179. //fmt.Printf(" \n【PayBlackIPDuanCache configs】: %+v", blist)
  180. //PayBlackCache.Store(constant.PAYBLACKIPRANGE, blist)
  181. //return tools.InStringArray(ipDuan, blist)
  182. return tools.InStringArray(ipDuan, BlackIPDuan)
  183. }
  184. //GetBlackListVer2 黑名单新算法尝试 黑名单 A,B,C,D, E
  185. func GetBlackListVer2(userid, ip, UA string, totalmoney int, nickname string) (int, bool) {
  186. var ipDuan string
  187. ipArr := strings.Split(ip, ".")
  188. if len(ipArr) >= 3 {
  189. ipDuan = strings.Join(ipArr[0:3], ".")
  190. }
  191. uID, _ := strconv.Atoi(userid)
  192. if tools.InStringArray(ip, BlackIPs) {
  193. return 0, true
  194. }
  195. // 1. 根据ip段来判断如果是黑名单IP段, 用户直接拉入黑名单分区
  196. if GetBlackIPDuanCache(ipDuan) {
  197. xlog.Infof("【 黑名单网段玩家 】 %v ip:%s agent:%v", userid, ip, UA)
  198. //获取用户信息
  199. userInfo := gsdkclient.Client().UserInfoNoLoginData(uID)
  200. var count int
  201. temp := gsdkclient.Client().GetEffortEx(uint(uID), []int{2}, false) //获取局数
  202. if temp != nil {
  203. count = int(temp[2]) //局数
  204. }
  205. //CheckBlackAB 判断黑名单AB
  206. if typ, ok := CheckBlackABE(ip, userInfo.NickName, userInfo.RegDate, uID, 2, totalmoney, count); ok {
  207. return typ, ok
  208. }
  209. if totalmoney == 0 { //判断黑名单C 无特征,无支付 不影响审核人员判断依据,但是不开放支付功能
  210. b := &BlackUsers{
  211. Type: 3,
  212. Ip: ip,
  213. Count: count,
  214. Createtime: userInfo.RegDate,
  215. Nickname: userInfo.NickName,
  216. Totalmoney: totalmoney,
  217. Userid: uID,
  218. }
  219. b.Add()
  220. return b.Type, true
  221. } else { //黑名单D 无特征,有支付过玩家,不开放支付,进入审核名单没问题可以对外开放
  222. b := &BlackUsers{
  223. Type: 4,
  224. Ip: ip,
  225. Count: count,
  226. Createtime: userInfo.RegDate,
  227. Nickname: userInfo.NickName,
  228. Totalmoney: totalmoney,
  229. Userid: uID,
  230. }
  231. b.Add()
  232. return b.Type, true
  233. }
  234. } else {
  235. //非黑名单认证用户nick是不是审核人员
  236. if typ, ok := CheckBlackA(ip, nickname, uID); ok {
  237. return typ, ok
  238. }
  239. }
  240. //判断是不是黑名单成员 如果是等级AB 记录他使用的IP, 等级CD只限制不统计IP
  241. //规则 A|182.254.115.151|局数:0|注册时间:2021-07-15 17:22:33.000000|昵称:WL_368879456|历史支付:10元
  242. if typ := GetBlackLevel(uID); typ > 0 {
  243. if tools.InIntArray(typ, []int{1, 2}) {
  244. xlog.Infof("【 黑名单明确审核玩家切换IP 】 %v ip:%s agent:%v", userid, ip, UA)
  245. // rds.Redis8.HIncrBy(constant.PAYBLACKLEVELIP, ip, 1) //黑名单玩家计入使用该ip次数
  246. return 0, true
  247. }
  248. xlog.Infof("【 黑名单不确定审核人员玩家切换IP 】 %v ip:%s agent:%v", userid, ip, UA)
  249. return 0, true
  250. }
  251. hour := time.Now().Hour() //高峰期不执行查询操作, 小于晚上8点,或者大于等于10点 进行特定IP认证
  252. if hour < 20 || hour >= 23 {
  253. //判断用户IP是不是 黑名单用户使用过的IP
  254. countX := rds.Redis8.HGet(constant.PAYBLACKLEVELIP, ip).Val()
  255. if c, _ := strconv.Atoi(countX); c >= 5 {
  256. userInfo := gsdkclient.Client().UserInfoNoLoginData(uID)
  257. var count int
  258. temp := gsdkclient.Client().GetEffortEx(uint(uID), []int{2}, false) //获取局数
  259. if temp != nil {
  260. count = int(temp[2]) //局数
  261. }
  262. //CheckBlackAE 判断黑名单AE
  263. if typ, ok := CheckBlackABE(ip, userInfo.NickName, userInfo.RegDate, uID, 5, totalmoney, count); ok {
  264. xlog.Infof("【 通过黑名单IP进来的审核人员 】 %v ip:%s agent:%v", userid, ip, UA)
  265. return typ, ok
  266. }
  267. var day int
  268. regTime := strings.Replace(userInfo.RegDate, "T", " ", -1)
  269. if len(regTime) >= 19 {
  270. parse, _ := time.Parse("2006-01-02 15:04:05", regTime)
  271. day = CheckSubDay(parse)
  272. }
  273. //2个月未支付玩家,拉入黑名单C
  274. if day >= 60 && totalmoney == 0 {
  275. b := &BlackUsers{
  276. Type: 3,
  277. Ip: ip,
  278. Count: count,
  279. Createtime: userInfo.RegDate,
  280. Nickname: userInfo.NickName,
  281. Totalmoney: totalmoney,
  282. Userid: uID,
  283. }
  284. b.Add()
  285. return b.Type, true
  286. } else {
  287. //用了黑名单用户ip, 但是充值过,或者只是近期没充值加入观察名单
  288. r := &RedUsers{
  289. Type: 1,
  290. Ip: ip,
  291. Count: count,
  292. Createtime: userInfo.RegDate,
  293. Nickname: userInfo.NickName,
  294. Totalmoney: totalmoney,
  295. Userid: uID,
  296. }
  297. r.Add()
  298. return 0, false
  299. }
  300. }
  301. }
  302. return 0, false
  303. }
  304. func CheckBlackA(ip, nickname string, userid int) (int, bool) {
  305. if len(nickname) > 7 {
  306. //判断是否符合黑名单A特征 含有关键字
  307. if strings.HasPrefix(nickname, "tencent_game") ||
  308. strings.HasPrefix(nickname, "rdgztest_") ||
  309. strings.HasPrefix(nickname, "minigamecheck") {
  310. b := &BlackUsers{
  311. Type: 1,
  312. Ip: ip,
  313. Count: 0,
  314. Createtime: "2022-01-01 00:00:00",
  315. Nickname: nickname,
  316. Totalmoney: 0,
  317. Userid: userid,
  318. }
  319. b.Add()
  320. return b.Type, true
  321. }
  322. }
  323. return 0, false
  324. }
  325. func CheckBlackABE(ip, nickname, reg string, userid, paytype, totalmoney, count int) (int, bool) {
  326. //判断是否符合黑名单A特征 含有关键字
  327. if strings.Contains(nickname, "tencent_game") ||
  328. strings.Contains(nickname, "rdgztest_") ||
  329. strings.Contains(nickname, "minigamecheck") ||
  330. strings.Contains(nickname, "city") {
  331. b := &BlackUsers{
  332. Type: 1,
  333. Ip: ip,
  334. Count: count,
  335. Createtime: reg,
  336. Nickname: nickname,
  337. Totalmoney: totalmoney,
  338. Userid: userid,
  339. }
  340. b.Add()
  341. return b.Type, true
  342. }
  343. //判断黑名单B,E情况 局数0注册时间久
  344. regTime := strings.Replace(reg, "T", " ", -1)
  345. if len(regTime) >= 19 {
  346. parse, _ := time.Parse("2006-01-02 15:04:05", regTime)
  347. if day := CheckSubDay(parse); day >= 180 && count == 0 {
  348. b := &BlackUsers{
  349. Type: paytype,
  350. Ip: ip,
  351. Count: count,
  352. Createtime: reg,
  353. Nickname: nickname,
  354. Totalmoney: totalmoney,
  355. Userid: userid,
  356. }
  357. b.Add()
  358. return b.Type, true
  359. }
  360. }
  361. return 0, false
  362. }
  363. //GetBlackLevel 获取黑名单等级
  364. func GetBlackLevel(userid int) int {
  365. if v, ok := PayBlackCacheNew.Get(userid); ok {
  366. return v
  367. }
  368. return -1
  369. }
  370. //RedUsers 观察名单
  371. type RedUsers struct {
  372. Id int `json:"id" sql:"id"` //自增ID
  373. Userid int `json:"userid" sql:"userid"` //用户ID
  374. Nickname string `json:"nickname" sql:"nickname"` //用户昵称
  375. Count int `json:"count" sql:"count"` //局数
  376. Totalmoney int `json:"total_money" sql:"total_money"` //支付历史金额
  377. Ip string `json:"ip" sql:"ip"` //ip
  378. Createtime string `json:"create_time" sql:"create_time"` //注册时间
  379. Time string `json:"time" sql:"time"` //创建时间
  380. Type int `json:"type" sql:"type"` //等级 1观察名单 3 排除名单
  381. }
  382. //BlackUsers 黑名单
  383. type BlackUsers struct {
  384. Id int `json:"id" sql:"id"` //自增ID
  385. Userid int `json:"userid" sql:"userid"` //用户ID
  386. Nickname string `json:"nickname" sql:"nickname"` //用户昵称
  387. Count int `json:"count" sql:"count"` //局数
  388. Totalmoney int `json:"total_money" sql:"total_money"` //支付历史金额
  389. Ip string `json:"ip" sql:"ip"` //ip
  390. Createtime string `json:"create_time" sql:"create_time"` //注册时间
  391. Time string `json:"time" sql:"time"` //创建时间
  392. Type int `json:"type" sql:"type"` //等级 1(关键字) 2(无游戏) 3(无支付) 4(IP段其他) 5(单IP无游戏)
  393. }
  394. func (b *BlackUsers) Add() (int64, error) {
  395. var last int64
  396. var err error
  397. sqlQuery := fmt.Sprintf("INSERT IGNORE INTO black_users (`userid`,`nickname`,`count`,`total_money`,`ip`, `create_time`, `type`) VALUE(?,?,?,?,?,?,?)")
  398. last, err = dbx.MySQL.Insert(sqlQuery, b.Userid, b.Nickname, b.Count, b.Totalmoney, b.Ip, strings.Replace(b.Createtime, "T", " ", -1), b.Type)
  399. if err != nil {
  400. logs.Error(fmt.Sprintf("black_users param:%#v err:%v", b, err))
  401. return 0, err
  402. }
  403. return last, nil
  404. }
  405. func GetBlackUsersType(userid int) int {
  406. var typ int
  407. err := dbx.MySQL.QueryRow("SELECT type from `black_users` where userid = ? ",
  408. userid).Scan(&typ)
  409. if nil != err {
  410. if err == sql.ErrNoRows {
  411. return typ
  412. }
  413. logs.Errorf("GetBlackUsersType err:%v", err)
  414. }
  415. return typ
  416. }
  417. func GetBlackAlLUsers() {
  418. PayBlackCacheNew = NewPayBlackCacheNew()
  419. t1 := time.Now()
  420. rows, err := dbx.MySQL.Query("SELECT userid, type from `black_users` where type in (1,2)")
  421. defer rows.Close()
  422. if err != nil && err != sql.ErrNoRows {
  423. logs.Errorf("GetBlackAlLUsers err:%v", err)
  424. return
  425. }
  426. var userid, typ int
  427. for rows.Next() {
  428. err = rows.Scan(&userid, &typ)
  429. if err != nil {
  430. logs.Errorf("GetBlackAlLUsers err:%v", err)
  431. return
  432. }
  433. PayBlackCacheNew.Set(userid, typ)
  434. }
  435. t2 := time.Now()
  436. xlog.Infof("加载黑名单配置时长:%s 数据:%+v", t2.Sub(t1), PayBlackCacheNew)
  437. }
  438. func (b *RedUsers) Add() (int64, error) {
  439. var last int64
  440. var err error
  441. sqlQuery := "INSERT IGNORE INTO red_users (`userid`,`nickname`,`count`,`total_money`,`ip`, `create_time`, `type`) VALUE(?,?,?,?,?,?,?)"
  442. last, err = dbx.MySQL.Insert(sqlQuery, b.Userid, b.Nickname, b.Count, b.Totalmoney, b.Ip, strings.Replace(b.Createtime, "T", " ", -1), b.Type)
  443. if err != nil {
  444. logs.Error(fmt.Sprintf("red_users param:%#v err:%v", b, err))
  445. return 0, err
  446. }
  447. return last, nil
  448. }
  449. func GetBUserInfo(tag string, st int64, level string) []BlackUsers {
  450. start := tools.TimeParseForMat(st, "2006-01-02 15:04:05")
  451. end := tools.TimeParseForMat(st+86400, "2006-01-02 15:04:05")
  452. var table, where string
  453. if tag == "red" {
  454. table = "red_users"
  455. } else if tag == "black" {
  456. table = "black_users"
  457. } else {
  458. return nil
  459. }
  460. if level != "" {
  461. l, _ := strconv.Atoi(level)
  462. where = fmt.Sprintf(" and type = %d", l)
  463. }
  464. var bu []BlackUsers
  465. sql := fmt.Sprintf("select * from `%s` where time >= '%s' and time <= '%s' %s ORDER BY time DESC", table, start, end, where)
  466. dbx.MySQL.Query2(sql, &bu)
  467. return bu
  468. }