risk.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package dao
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/md5"
  6. "encoding/binary"
  7. "encoding/hex"
  8. "encoding/json"
  9. "github.com/json-iterator/go"
  10. "go-common/app/service/openplatform/anti-fraud/conf"
  11. "go-common/app/service/openplatform/anti-fraud/model"
  12. "go-common/library/cache/redis"
  13. "go-common/library/ecode"
  14. "go-common/library/log"
  15. "net/http"
  16. "time"
  17. )
  18. //CheckSalesTime 检查售卖时间
  19. func (d *Dao) CheckSalesTime(c context.Context, mid, itemID, salesTime, saleTimeOut int64) (err error) {
  20. key := model.GetSalesLimitKey(mid)
  21. conn := d.redis.Get(c)
  22. defer conn.Close()
  23. var (
  24. flag int64
  25. data []byte
  26. )
  27. data, _ = redis.Bytes(conn.Do("GET", key))
  28. json.Unmarshal(data, &flag)
  29. if flag == 1 {
  30. return ecode.AntiSalesTimeErr
  31. }
  32. if salesTime > time.Now().Unix() {
  33. conn.Do("SET", key, 1, "EX", saleTimeOut)
  34. return ecode.AntiSalesTimeErr
  35. }
  36. return nil
  37. }
  38. //CheckIPChange 检查用户ip变更
  39. func (d *Dao) CheckIPChange(c context.Context, mid int64, ip string, changeTime int64) (err error) {
  40. key := model.GetIPChangeKey(mid)
  41. conn := d.redis.Get(c)
  42. defer conn.Close()
  43. var (
  44. flag string
  45. data []byte
  46. )
  47. data, _ = redis.Bytes(conn.Do("GET", key))
  48. json.Unmarshal(data, &flag)
  49. go func(c context.Context, key string, ip string) {
  50. conn := d.redis.Get(c)
  51. defer conn.Close()
  52. conn.Do("SET", key, ip, "EX", changeTime)
  53. }(context.Background(), key, ip)
  54. if flag != "" && flag != ip {
  55. return ecode.AntiIPChangeLimit
  56. }
  57. return nil
  58. }
  59. //CheckLimitNum 检查限制次数
  60. func (d *Dao) CheckLimitNum(c context.Context, key string, num int64, pastTime int64) (err error) {
  61. conn := d.redis.Get(c)
  62. defer conn.Close()
  63. pastTime = pastTime * 1e9
  64. currentTime := time.Now().UnixNano()
  65. conn.Do("ZADD", key, currentTime, currentTime)
  66. data, _ := redis.Int64(conn.Do("ZCOUNT", key, currentTime-pastTime, currentTime))
  67. go func(c context.Context, key string, pastTime, currentTime int64, flag bool) {
  68. conn := d.redis.Get(c)
  69. defer conn.Close()
  70. conn.Do("EXPIRE", key, pastTime/1e9)
  71. if flag {
  72. conn.Do("ZREMRANGEBYRANK", key, 0, 0)
  73. }
  74. }(context.Background(), key, pastTime, currentTime, data > num)
  75. if data > num {
  76. return ecode.AntiLimitNumUpper
  77. }
  78. return nil
  79. }
  80. //Voucher 凭证
  81. func (d *Dao) Voucher(c context.Context, mid int64, ip string, itemID, customer, voucherType int64) (voucher string) {
  82. s := make([]byte, 0)
  83. buf := bytes.NewBuffer(s)
  84. binary.Write(buf, binary.BigEndian, mid)
  85. binary.Write(buf, binary.BigEndian, []byte(ip))
  86. binary.Write(buf, binary.BigEndian, itemID)
  87. binary.Write(buf, binary.BigEndian, customer)
  88. binary.Write(buf, binary.BigEndian, voucherType)
  89. binary.Write(buf, binary.BigEndian, time.Now().UnixNano())
  90. digest := md5.Sum(buf.Bytes())
  91. voucher = hex.EncodeToString(digest[:])
  92. conn := d.redis.Get(c)
  93. defer conn.Close()
  94. key := model.GetUserVoucherKey(mid, voucher, voucherType)
  95. conn.Do("SET", key, 1, "EX", model.RedisUserVoucherKeyTimeOut)
  96. return
  97. }
  98. //CheckVoucher 验证用户凭证,一次性
  99. func (d *Dao) CheckVoucher(c context.Context, mid int64, voucher string, voucherType int64) (err error) {
  100. conn := d.redis.Get(c)
  101. defer conn.Close()
  102. key := model.GetUserVoucherKey(mid, voucher, voucherType)
  103. data, _ := redis.Int64(conn.Do("INCR", key))
  104. conn.Do("DEL", key)
  105. if data < 2 {
  106. return ecode.AntiCheckVoucherErr
  107. }
  108. return nil
  109. }
  110. //IncrGeetestCount 统计一小时内极验的请求数
  111. func (d *Dao) IncrGeetestCount(c context.Context) {
  112. conn := d.redis.Get(c)
  113. defer conn.Close()
  114. key := model.GetGeetestCountKey()
  115. conn.Do("INCR", key)
  116. conn.Do("EXPIRE", key, model.RedisGeetestCountKeyTimeOut)
  117. }
  118. //CheckGeetestCount 检查极验总数是否达到上限
  119. func (d *Dao) CheckGeetestCount(c context.Context) (err error) {
  120. conn := d.redis.Get(c)
  121. defer conn.Close()
  122. key := model.GetGeetestCountKey()
  123. var (
  124. data []byte
  125. count int64
  126. )
  127. data, _ = redis.Bytes(conn.Do("GET", key))
  128. json.Unmarshal(data, &count)
  129. if count > d.c.Geetest.Count {
  130. log.Info("极验总数达到上限")
  131. return ecode.AntiGeetestCountUpper
  132. }
  133. return
  134. }
  135. // CheckBlack 检测黑名单
  136. func (d *Dao) CheckBlack(c context.Context, customerId, mid int64, clientIP string) (err error) {
  137. conn := d.redis.Get(c)
  138. defer conn.Close()
  139. midKey := model.GetMIDBlackKey(customerId, mid)
  140. ipKey := model.GetIPBlackKey(customerId, clientIP)
  141. data, err := redis.Int64s(conn.Do("MGET", midKey, ipKey))
  142. if err != nil {
  143. log.Info("获取黑名单出错 %s %s", midKey, ipKey)
  144. return nil
  145. }
  146. for _, value := range data {
  147. if value == 1 {
  148. return ecode.AntiBlackErr
  149. }
  150. }
  151. return nil
  152. }
  153. // PayShield 支付风控
  154. func (d *Dao) PayShield(c context.Context, data *model.ShieldData) {
  155. var res struct {
  156. errno int64
  157. msg string
  158. data interface{}
  159. }
  160. params, err := jsoniter.Marshal(data)
  161. if err != nil {
  162. log.Info("json marshal err %v", err)
  163. return
  164. }
  165. log.Info("req pay shield params %s", string(params))
  166. req, err := http.NewRequest("POST", conf.Conf.URL.Shield, bytes.NewBuffer(params))
  167. if err != nil {
  168. log.Warn("new request err url %s, err %v", conf.Conf.URL.Shield, err)
  169. return
  170. }
  171. req.Header.Set("Content-Type", "application/json")
  172. err = d.client.Do(c, req, &res)
  173. if err != nil || res.errno != 0 {
  174. log.Warn("client do err url %s, err %v", conf.Conf.URL.Shield, err)
  175. return
  176. }
  177. }
  178. // SetexRedisKey 设置redis key
  179. func (d *Dao) SetexRedisKey(c context.Context, key string, timeout int64) {
  180. conn := d.redis.Get(c)
  181. defer conn.Close()
  182. conn.Do("SET", key, 1, "EX", timeout)
  183. }
  184. // AddPayData .
  185. func (d *Dao) AddPayData(data *model.ShieldData) {
  186. d.payData <- data
  187. }
  188. // SyncPayShield .
  189. func (d *Dao) SyncPayShield(c context.Context) {
  190. for {
  191. data := <-d.payData
  192. d.PayShield(c, data)
  193. }
  194. }