Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"cache_test.go",
"dao_test.go",
"question_bank_bind_test.go",
"question_bank_test.go",
"question_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/service/openplatform/anti-fraud/conf:go_default_library",
"//app/service/openplatform/anti-fraud/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"cache.go",
"dao.go",
"payShield.go",
"question.go",
"question_bank.go",
"question_bank_bind.go",
"risk.go",
],
importpath = "go-common/app/service/openplatform/anti-fraud/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/service/openplatform/anti-fraud/conf:go_default_library",
"//app/service/openplatform/anti-fraud/model:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/xstr:go_default_library",
"//vendor/github.com/json-iterator/go:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,600 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"time"
"go-common/app/service/openplatform/anti-fraud/model"
"go-common/library/cache/redis"
"go-common/library/ecode"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_keyBankQuestions = "AntiFraud:BANK_%d:QUESTIONS"
_keyQuestionFetchTime = "AntiFraud:USER_%s:ITEM_%d_%d_%s_PLATFORM:%d_Date"
// 上次调起组件的id
_keyComponentID = "AntiFraud:USER_%s:ITEM_%d_%d_%s_PLATFORM:%d_COMID"
// 回答过的问题 id
_keyAnsweredIds = "AntiFraud:USER_%s:ITEM_%d_%d_%s_PLATFORM:%d_ANSWER_IDS"
// 组件内获取题目次数
_keyBindBank = "AntiFraud:BIND_BANK_ITEM_%s"
_keyComponentTimes = "AntiFraud:USER_%s:ITEM_%d_%d_%s_PLATFORM:%d_ANSWERTIMES"
_keyBankID = "AntiFraud:BANKID_%d"
//答案ids缓存
_keyAnswerIds = "AntiFraud:AnswerIds_%d"
// 图片id
_keyPicID = "AntiFraud:AnswerAllPic"
// 缓存所有图片id
_keyPicIds = "AntiFraud:AnswerPic_%d"
//默认100条数据
_limit = 100
// 缓存问题
_keyQusInfo = "AntiFraud:QusInfo_%d"
// 缓存图片
_keyAnswerPicID = "AntiFraud:USER_%s:ITEM_%d_%d_%s_AnswerPic:%d_COMID"
//答题日志list
_keyAddLog = "AntiFraud:AddLog"
//答案缓存
_keyAnswer = "AntiFraud:Answer_%d"
// 5分钟缓存
_fiveMinuts = 5 * time.Minute
)
// PingRedis check redis connection
func (d *Dao) PingRedis(c context.Context) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
_, err = conn.Do("PING")
return
}
// GetUserQuestionCache get
func (d *Dao) GetUserQuestionCache(c context.Context, args *model.ArgGetQuestion, bankID int64) {
key := fmt.Sprintf("USER_%s_ITEM_%d_%d_%s_PLATFORM_%d_BANK_%d", args.UID, args.Source, args.TargetItemType, args.TargetItem, args.Platform, bankID)
d.RedisDo(c, "GET", key)
}
// RedisDo redis cmd
func (d *Dao) RedisDo(c context.Context, cmd string, args ...interface{}) (reply interface{}, err error) {
conn := d.redis.Get(c)
defer conn.Close()
return conn.Do(cmd, args...)
}
// SetBankQuestionsCache 将题库下的全部问题存入缓存
func (d *Dao) SetBankQuestionsCache(c context.Context, bankID int64, ids []int64) (err error) {
key := fmt.Sprintf(_keyBankQuestions, bankID)
err = d.SetObj(c, key, ids, time.Hour)
if err != nil {
log.Error("d.SetBankQuestionsCache() error(%v)", err)
return
}
return
}
// GetBankQuestionsCache 从缓存获取题库下的全部问题
func (d *Dao) GetBankQuestionsCache(c context.Context, bankID int64) (ids []int64) {
key := fmt.Sprintf(_keyBankQuestions, bankID)
reply, err := redis.Bytes(d.RedisDo(c, "GET", key))
if err == redis.ErrNil {
return
}
if err != nil {
log.Error("查询 redis 出错 d.GetBankQuestionsCache(%d) error(%v)", bankID, err)
return
}
err = json.Unmarshal(reply, &ids)
if err != nil {
return
}
return
}
// QusFetchTime 上次题目拉取时间
func (d *Dao) QusFetchTime(c context.Context, args *model.ArgGetQuestion) (ts int64) {
ts, _ = redis.Int64(d.RedisDo(c, "GET", d.GetQusKey(_keyQuestionFetchTime, args)))
return
}
// SetQusFetchTime 设置上次题目拉取时间
func (d *Dao) SetQusFetchTime(c context.Context, args *model.ArgGetQuestion, ts int64) (err error) {
err = d.Setex(c, d.GetQusKey(_keyQuestionFetchTime, args), ts, _fiveMinuts)
if err != nil {
log.Error("d.SetQusFetchTime(%v, %d) error(%v)", args, ts, err)
}
return
}
// GetQusKey getkey
func (d *Dao) GetQusKey(format string, args *model.ArgGetQuestion) (s string) {
s = fmt.Sprintf(format, args.UID, args.Source, args.TargetItemType, args.TargetItem, args.Platform)
return
}
// Setex set
func (d *Dao) Setex(c context.Context, key string, data interface{}, exp time.Duration) error {
log.Info(" d.setex(%s, %v, %d)", key, data, exp)
_, err := d.RedisDo(c, "SETEX", key, int(exp/1e9), data)
if err != nil {
log.Error("d.Setex(%s, %v) error(%v)", key, data, err)
}
return err
}
// SetObj set
func (d *Dao) SetObj(c context.Context, key string, obj interface{}, exp time.Duration) error {
log.Info(" d.setex(%s, %v, %d)", key, obj, exp)
data, err := json.Marshal(obj)
if err != nil {
return err
}
_, err = d.RedisDo(c, "SETEX", key, int(exp/1e9), data)
if err != nil {
log.Error("d.Setex(%s, %v) error(%v)", key, string(data), err)
}
return err
}
//GetObj get
func (d *Dao) GetObj(c context.Context, key string, obj interface{}) (err error) {
reply, err := redis.Bytes(d.RedisDo(c, "GET", key))
if err != nil {
return
}
err = json.Unmarshal(reply, obj)
if err != nil {
return
}
return
}
// GetAnsweredID 获取已回答问题
func (d *Dao) GetAnsweredID(c context.Context, args *model.ArgGetQuestion) (ids []int64) {
key := d.GetQusKey(_keyAnsweredIds, args)
ids, err := redis.Int64s(d.RedisDo(c, "SMEMBERS", key))
if err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("d.GetAnsweredID(%v) error(%v)", args, err)
}
}
return
}
// SetAnsweredID 设置已回答问题
func (d *Dao) SetAnsweredID(c context.Context, args *model.ArgGetQuestion, questionID int64) (err error) {
key := d.GetQusKey(_keyAnsweredIds, args)
_, err = d.RedisDo(c, "SADD", key, questionID)
if err != nil {
log.Error("d.SetAnsweredID(%v, %d) error(%v)", args, questionID, err)
}
_, err = d.RedisDo(c, "EXPIRE", key, int(_fiveMinuts/1e9))
if err != nil {
log.Error("d.SetAnsweredID expire (%v, %d) error(%v)", args, questionID, err)
}
return
}
// RmAnsweredID 删除已回答问题
func (d *Dao) RmAnsweredID(c context.Context, args *model.ArgGetQuestion) (err error) {
key := d.GetQusKey(_keyAnsweredIds, args)
_, err = d.RedisDo(c, "DEL", key)
if err != nil {
log.Error("d.SetAnsweredID(%v, %d) error(%v)", args, err)
}
return
}
// GetComponentID 获取组件id
func (d *Dao) GetComponentID(c context.Context, args *model.ArgGetQuestion) (cID int, err error) {
key := d.GetQusKey(_keyComponentID, args)
if cID, err = redis.Int(d.RedisDo(c, "GET", key)); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("d.GetComponentID(%v) error(%v)", args, err)
}
}
return
}
// SetComponentID 设置组件id
func (d *Dao) SetComponentID(c context.Context, args *model.ArgGetQuestion) (err error) {
key := d.GetQusKey(_keyComponentID, args)
err = d.Setex(c, key, args.ComponentID, _fiveMinuts)
if err != nil {
log.Error("d.SetComponentID(%v) error(%v)", args, err)
}
return
}
// GetComponentTimes 获取组件答题次数
func (d *Dao) GetComponentTimes(c context.Context, args *model.ArgGetQuestion) (cID int64, err error) {
key := d.GetQusKey(_keyComponentTimes, args)
if cID, err = redis.Int64(d.RedisDo(c, "GET", key)); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("d.GetComponentTimes(%v) error(%v)", args, err)
}
}
return
}
// SetComponentTimes 设置组件答题次数
func (d *Dao) SetComponentTimes(c context.Context, args *model.ArgGetQuestion) (err error) {
key := d.GetQusKey(_keyComponentTimes, args)
err = d.Setex(c, key, 0, _fiveMinuts)
if err != nil {
log.Error("d.SetComponentID(%v) error(%v)", args, err)
}
return
}
// IncrComponentTimes 组件计数
func (d *Dao) IncrComponentTimes(c context.Context, args *model.ArgGetQuestion) (err error) {
key := d.GetQusKey(_keyComponentTimes, args)
_, err = d.RedisDo(c, "INCR", key)
if err != nil {
log.Error("d.GetComponentTimes(%v) error(%v)", args, err)
}
return
}
// GetQusBankInfoCache get
func (d *Dao) GetQusBankInfoCache(c context.Context, qbid int64) (oi *model.QuestionBank, err error) {
oi = &model.QuestionBank{}
key := fmt.Sprintf(_keyBankID, qbid)
err = d.GetObj(c, key, oi)
if err == redis.ErrNil {
err = nil
oi, err = d.GetQusBankInfo(c, qbid)
if err != nil {
log.Error("d.GetQusBankInfoCache error(%v)", err)
return
}
err = d.SetObj(c, key, oi, _fiveMinuts)
}
return
}
// GetBindBankInfo get
func (d *Dao) GetBindBankInfo(c context.Context, source, targetItemType int8, targetItem string) (bind *model.QuestionBankBind, err error) {
bind = &model.QuestionBankBind{}
key := fmt.Sprintf(_keyBindBank, targetItem)
err = d.GetObj(c, key, bind)
if err == redis.ErrNil {
//err = nil
binds, err1 := d.GetBindBank(c, source, targetItemType, []string{targetItem})
if err1 != nil {
log.Error("s.GetQuestion(%v) error(%v)", targetItem, err)
err = err1
return
}
if len(binds) < 1 {
log.Warn("s.GetQuestion(%v) 未找到题库绑定关系", targetItem)
err = ecode.BindBankNotFound
return
}
bind = binds[0]
if bind.QuestionBank == nil {
log.Error("s.GetQuestion(%v) 未找到已绑定的题库", targetItem)
err = ecode.QusbNotFound
return
}
err = d.SetObj(c, key, bind, time.Hour)
//return
}
return
}
// CorrectAnswerIds id
func (d *Dao) CorrectAnswerIds(c context.Context, qid int64) (ids []int64, err error) {
key := fmt.Sprintf(_keyAnswerIds, qid)
err = d.GetObj(c, key, &ids)
if err == redis.ErrNil {
err = nil
answers, err1 := d.GetAnswerList(c, qid)
for _, answer := range answers {
if answer.IsCorrect == 1 {
ids = append(ids, answer.AnswerID)
}
}
if err1 != nil {
err = err1
log.Error("d.GetQusBankInfoCache error(%v)", err)
return
}
err1 = d.SetObj(c, key, ids, time.Hour)
err = err1
return
}
return
}
// GetRandPic 背景图
func (d *Dao) GetRandPic(c context.Context, args *model.ArgGetQuestion) (oi *model.QuestBkPic, err error) {
key := _keyPicID
cnt, err := redis.Int(d.RedisDo(c, "LLen", key))
if err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("GetStatisticsCache do(RPOP, %s) error(%v)", key, err)
}
return
}
if cnt == 0 {
err1 := d.PushAllPic(c)
if err1 != nil {
if err1 == redis.ErrNil {
err = nil
} else {
log.Error("PushAllPic do(RPOP, %s) error(%v)", key, err)
}
return
}
}
id, err := redis.Int(d.RedisDo(c, "RPOP", key))
if err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("GetStatisticsCache do(RPOP, %s) error(%v)", key, err)
}
return
}
oi, err = d.GetPic(c, id)
if err != nil {
return
}
//缓存坐标
picKey := d.GetQusKey(_keyAnswerPicID, args)
err = d.SetObj(c, picKey, oi, time.Hour)
if err != nil {
return
}
return
}
// PushAllPic 事先放入redis list中
func (d *Dao) PushAllPic(c context.Context) (err error) {
cnt, err := d.GetPicCount(c)
limit := _limit
page := (int)(cnt / limit)
for i := 0; i <= page; i++ {
key := _keyPicID
ids, _ := d.GetAllPicIds(c, i*limit, limit)
a := make([]interface{}, 0)
a = append(a, key)
for _, id := range ids {
a = append(a, id)
}
if len(a) > 1 {
_, err := d.RedisDo(c, "LPUSH", a...)
if err != nil {
log.Error("[PushAllPic]conn.Do(lpush, %s) error(%v)", key, err)
}
}
}
return
}
// GetPic 获取背景图
func (d *Dao) GetPic(c context.Context, id int) (oi *model.QuestBkPic, err error) {
key := fmt.Sprintf(_keyPicIds, id)
oi = &model.QuestBkPic{}
err = d.GetObj(c, key, oi)
if err == redis.ErrNil {
err = nil
picInfo, err1 := d.GetRandomPic(c, id)
if err1 != nil {
err = err1
log.Error("d.GetPic error(%v)", err1)
return
}
err1 = d.SetObj(c, key, picInfo, time.Hour)
oi = picInfo
err = err1
return
}
return
}
// PushAnswer push
func (d *Dao) PushAnswer(c context.Context, answer *model.ArgCheckAnswer, isCorrect int8) (affect int64, err error) {
ids := xstr.JoinInts(answer.Answers)
obj := model.AddLog{
UID: answer.UID,
QsID: answer.QsID,
Platform: answer.Platform,
Source: answer.Source,
Ids: ids,
IsCorrect: isCorrect,
}
data, err := json.Marshal(obj)
if err != nil {
return
}
_, err = d.RedisDo(c, "LPUSH", _keyAddLog, data)
if err != nil {
log.Error("[PushAllPic]conn.Do(RPOP,%s) error(%v)", "_keyAddLog", err)
}
affect = obj.QsID
return
}
// PopAnswer pop
func (d *Dao) PopAnswer(c context.Context) {
for {
reply, err := redis.Bytes(d.RedisDo(c, "RPOP", _keyAddLog))
if len(reply) > 0 && err == nil {
answer := &model.AddLog{}
err = json.Unmarshal(reply, answer)
if err == nil {
_, err = d.db.Exec(c, _addUserAnswerSQL, answer.UID, answer.QsID, answer.Platform, answer.Source, answer.Ids, answer.IsCorrect)
if err != nil {
log.Error("d.PopAnswer error(%v)", err)
time.Sleep(time.Second * 1)
continue
}
}
}
time.Sleep(time.Second * 5)
}
}
// GetCacheQus get
func (d *Dao) GetCacheQus(c context.Context, id int64) (oi *model.Question, err error) {
key := fmt.Sprintf(_keyQusInfo, id)
oi = &model.Question{}
err = d.GetObj(c, key, oi)
if err == redis.ErrNil {
err = nil
info, err1 := d.GetQusInfo(c, id)
if err1 != nil {
err = err1
log.Error("d.GetPic error(%v)", err1)
return
}
err1 = d.SetObj(c, key, info, time.Hour)
oi = info
err = err1
return
}
return
}
// GetCacheAnswerPic get
func (d *Dao) GetCacheAnswerPic(c context.Context, args *model.ArgGetQuestion) (oi *model.QuestBkPic, err error) {
picKey := d.GetQusKey(_keyAnswerPicID, args)
oi = &model.QuestBkPic{}
err = d.GetObj(c, picKey, oi)
if err != nil {
return
}
return
}
// DelTargetItemBindCache del cache
func (d *Dao) DelTargetItemBindCache(c context.Context, skuID string) (err error) {
key := fmt.Sprintf(_keyBindBank, skuID)
_, err = d.RedisDo(c, "DEL", key)
if err != nil {
if err != redis.ErrNil {
log.Error("d.DelTargetItemBind(%v, %d) error(%v)", skuID, err)
return
}
err = nil
}
return
}
// DelQusCache del cache
func (d *Dao) DelQusCache(c context.Context, id int64) (err error) {
key := fmt.Sprintf(_keyQusInfo, id)
_, err = d.RedisDo(c, "DEL", key)
if err != nil {
if err != redis.ErrNil {
log.Error("d.DelQusCache(%v, %d) error(%v)", id, err)
return
}
err = nil
}
return
}
// GetAnswersByCache cache
func (d *Dao) GetAnswersByCache(c context.Context, id int64) (oi []*model.Answer, err error) {
key := fmt.Sprintf(_keyAnswer, id)
err = d.GetObj(c, key, &oi)
if err == redis.ErrNil {
err = nil
info, err1 := d.GetAnswerList(c, id)
if err1 != nil {
err = err1
log.Error("d.GetPic error(%v)", err1)
return
}
err1 = d.SetObj(c, key, info, time.Hour)
oi = info
err = err1
return
}
return
}
// DelAnswerCache del cache
func (d *Dao) DelAnswerCache(c context.Context, id int64) (err error) {
key := fmt.Sprintf(_keyAnswer, id)
_, err = d.RedisDo(c, "DEL", key)
if err != nil {
if err != redis.ErrNil {
log.Error("d.DelAnswerCache(%v, %d) error(%v)", id, err)
return
}
err = nil
}
return
}
// DelQusBankCache del cache
func (d *Dao) DelQusBankCache(c context.Context, id int64) (err error) {
key := fmt.Sprintf(_keyBankID, id)
_, err = d.RedisDo(c, "DEL", key)
if err != nil {
if err != redis.ErrNil {
log.Error("d.DelQusBankCache(%v, %d) error(%v)", id, err)
return
}
err = nil
}
return
}

View File

@@ -0,0 +1,145 @@
package dao
import (
"context"
"encoding/json"
"flag"
"fmt"
"testing"
"time"
"go-common/app/service/openplatform/anti-fraud/conf"
"go-common/app/service/openplatform/anti-fraud/model"
. "github.com/smartystreets/goconvey/convey"
)
const _key = "AntiFraud:BANKID_1527233672941"
var qustion = &model.ArgGetQuestion{UID: "1111", TargetItem: "1111", TargetItemType: 1, Source: 1, Platform: 1, ComponentID: 123}
func init() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(fmt.Errorf("conf.Init() error(%v)", err))
}
d = New(conf.Conf)
}
func TestSetex(t *testing.T) {
Convey("TestSetex", t, func() {
err := d.Setex(context.TODO(), "BANK_1527061216377_QUESTIONS", 1, time.Hour)
So(err, ShouldBeNil)
})
}
func TestSetObj(t *testing.T) {
Convey("TestSetex", t, func() {
obj := &model.QuestionBank{}
reply := []byte(`{"qb_id":1527233672941,"qb_name":"wlt","cd_time":0,"max_retry_time":22,"is_deleted":0}`)
err := json.Unmarshal(reply, obj)
if err != nil {
return
}
d.GetObj(context.TODO(), _key, obj)
data, err := d.GetQusBankInfoCache(context.TODO(), 1527233672941)
So(err, ShouldBeNil)
So(data, ShouldNotBeNil)
})
}
//
func TestGetObj(t *testing.T) {
Convey("TestSetex", t, func() {
data := &model.QuestionBank{}
err := d.GetObj(context.TODO(), _key, data)
So(err, ShouldBeNil)
})
}
func TestGetPic(t *testing.T) {
Convey("TestGetPic", t, func() {
oi, _ := d.GetPic(context.TODO(), 4)
So(oi, ShouldNotBeNil)
})
}
func TestPushAllPic(t *testing.T) {
Convey("TestGetPic", t, func() {
data := &model.ArgGetQuestion{
UID: "111111",
TargetItem: "1111",
TargetItemType: 1,
Source: 1,
Platform: 1,
ComponentID: 123,
}
_, err := d.GetRandPic(context.TODO(), data)
So(err, ShouldBeNil)
})
}
func TestGetCacheQus(t *testing.T) {
Convey("TestGetCacheQus", t, func() {
_, err := d.GetCacheQus(context.TODO(), 1527241107344)
So(err, ShouldBeNil)
})
}
func TestGetQusKey(t *testing.T) {
Convey("TestGetQusKey", t, func() {
oi := d.GetQusKey(_keyAnsweredIds, qustion)
So(oi, ShouldNotBeNil)
})
}
func TestQusFetchTime(t *testing.T) {
Convey("TestQusFetchTime", t, func() {
oi := d.QusFetchTime(context.TODO(), qustion)
So(oi, ShouldNotBeNil)
})
}
func TestSetComponentId(t *testing.T) {
Convey("TestSetComponentId", t, func() {
err := d.SetComponentID(context.TODO(), qustion)
So(err, ShouldBeNil)
})
}
func TestGetComponentId(t *testing.T) {
Convey("TestGetComponentId", t, func() {
oi, err := d.GetComponentID(context.TODO(), qustion)
So(oi, ShouldNotBeNil)
So(err, ShouldBeNil)
})
}
func TestIncrComponentTimes(t *testing.T) {
Convey("TestIncrComponentTimes", t, func() {
err := d.IncrComponentTimes(context.TODO(), qustion)
So(err, ShouldBeNil)
})
}
func TestGetRandPic(t *testing.T) {
Convey("TestGetRandPic", t, func() {
oi, err := d.GetRandPic(context.TODO(), qustion)
So(err, ShouldBeNil)
So(oi, ShouldNotBeNil)
})
}
func TestSetAnsweredID(t *testing.T) {
Convey("TestSetAnsweredID", t, func() {
_, err := d.RedisDo(context.TODO(), "SADD", "wlt", 1222)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,64 @@
package dao
import (
"context"
"go-common/app/service/openplatform/anti-fraud/conf"
"go-common/app/service/openplatform/anti-fraud/model"
"go-common/library/cache/redis"
"go-common/library/database/sql"
"go-common/library/log"
httpx "go-common/library/net/http/blademaster"
)
// Dao init dao
type Dao struct {
c *conf.Config
db *sql.DB // db
payShieldDb *sql.DB // payShieldDb
redis *redis.Pool // redis
client *httpx.Client
payData chan *model.ShieldData
}
// New new a Dao and return.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: sql.NewMySQL(c.DB.AntiFraud),
payShieldDb: sql.NewMySQL(c.DB.PayShield),
redis: redis.NewPool(c.Redis.Config),
client: httpx.NewClient(conf.Conf.HTTPClient.Read),
payData: make(chan *model.ShieldData, 2000),
}
go d.SyncPayShield(context.Background())
go d.PopAnswer(context.TODO())
return
}
// Close close connections.
func (d *Dao) Close() {
if d.db != nil {
d.db.Close()
}
if d.redis != nil {
d.redis.Close()
}
}
// Ping ping health.
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.db.Ping(c); err != nil {
log.Error("PingDb error(%v)", err)
return
}
if err = d.PingRedis(c); err != nil {
log.Error("PingRedis error(%v)", err)
return
}
return
}
// BeginTran begin mysql transaction
func (d *Dao) BeginTran(c context.Context) (*sql.Tx, error) {
return d.db.Begin(c)
}

View File

@@ -0,0 +1,17 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
var d *Dao
func TestPing(t *testing.T) {
Convey("TestPing: ", t, func() {
err := d.Ping(context.TODO())
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,102 @@
package dao
import (
"context"
"go-common/app/service/openplatform/anti-fraud/model"
"go-common/library/log"
)
const (
_ipList = "select ip,count(1) as num from shield_ip_log where mtime >= ? group by ip order by num desc limit 50"
_ipDetail = "select ip,uid from shield_ip_log where ip = ? and mtime >= ? and mtime <= ?"
_uidList = "select uid,count(1) as num from shield_user_log where mtime >= ? group by uid order by num desc limit 50"
_uidDetail = "select ip,uid from shield_user_log where uid = ? and mtime >= ? and mtime <= ?"
)
// ShieldIPList .
func (d *Dao) ShieldIPList(c context.Context, mtime string) (res []*model.IPListDetail, err error) {
res = make([]*model.IPListDetail, 0)
rows, err := d.payShieldDb.Query(c, _ipList, mtime)
if err != nil {
log.Warn("select err %s %v", _ipList, err)
return
}
for rows.Next() {
r := new(model.IPListDetail)
if err = rows.Scan(&r.IP, &r.Num); err != nil {
log.Warn("scan err %v", err)
return
}
res = append(res, r)
}
return
}
// ShieldIPDetail .
func (d *Dao) ShieldIPDetail(c context.Context, ip, stime, etime string) (res []*model.ListDetail, err error) {
res = make([]*model.ListDetail, 0)
rows, err := d.payShieldDb.Query(c, _ipDetail, ip, stime, etime)
if err != nil {
log.Warn("select err %s %v", _ipDetail, err)
return
}
for rows.Next() {
r := new(model.ListDetail)
if err = rows.Scan(&r.IP, &r.UID); err != nil {
log.Warn("scan err %v", err)
return
}
res = append(res, r)
}
return
}
// ShieldUIDList .
func (d *Dao) ShieldUIDList(c context.Context, mtime string) (res []*model.UIDListDetail, err error) {
res = make([]*model.UIDListDetail, 0)
rows, err := d.payShieldDb.Query(c, _uidList, mtime)
if err != nil {
log.Warn("select err %s %v", _uidList, err)
return
}
for rows.Next() {
r := new(model.UIDListDetail)
if err = rows.Scan(&r.UID, &r.Num); err != nil {
log.Warn("scan err %v", err)
return
}
res = append(res, r)
}
return
}
// ShieldUIDDetail .
func (d *Dao) ShieldUIDDetail(c context.Context, uid, stime, etime string) (res []*model.ListDetail, err error) {
res = make([]*model.ListDetail, 0)
rows, err := d.payShieldDb.Query(c, _uidDetail, uid, stime, etime)
if err != nil {
log.Warn("select err %s %v", _uidDetail, err)
return
}
for rows.Next() {
r := new(model.ListDetail)
if err = rows.Scan(&r.IP, &r.UID); err != nil {
log.Warn("scan err %v", err)
return
}
res = append(res, r)
}
return
}

View File

@@ -0,0 +1,299 @@
package dao
import (
"context"
"fmt"
"strings"
"time"
"go-common/app/service/openplatform/anti-fraud/model"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_getQusSQL = "SELECT question_id ,question_type,answer_type,question_name,question_bank_id,difficulty,is_deleted FROM question where question_id=? and is_deleted =0 "
_addQusSQL = "INSERT INTO question(question_id ,question_type,answer_type,question_name,question_bank_id,difficulty) VALUES(?,?,?,?,?,?)"
_getQuslistBywhereSQL = "SELECT question_id ,question_type,answer_type,question_name,question_bank_id,difficulty,is_deleted FROM question where is_deleted = 0 and question_bank_id = ? order by id desc limit ? ,? "
_getAllQusByBankID = "SELECT question_id FROM question WHERE question_bank_id = ? AND is_deleted = 0"
_getQuslistSQL = "SELECT question_id ,question_type,answer_type,question_name,question_bank_id,difficulty,is_deleted FROM question where is_deleted = ? limit ? ,? "
_getQusCntSQL = "SELECT COUNT(*) FROM question where is_deleted = 0 "
_delQusSQL = "UPDATE question set is_deleted = ? where question_id =? "
_updateQusSQL = "UPDATE question set question_type = ? ,answer_type=? ,question_name = ? , question_bank_id = ? ,difficulty = ? where question_id =? and is_deleted =0 "
_addAnswerSQL = "INSERT INTO question_answer(answer_id ,question_id,answer_content,is_correct ) VALUES(?,?,?,?)"
_multyAddAnswerSQL = "INSERT INTO question_answer(answer_id ,question_id,answer_content,is_correct ) VALUES %s "
_updateAnswerSQL = "UPDATE question_answer set answer_content = ? , is_correct =? , is_deleted =0 where answer_id = ? "
_delAnswerSQL = "UPDATE question_answer set is_deleted = 1 where question_id =? "
_getAnswerListSQL = "select answer_id ,question_id, answer_content,is_correct from question_answer where question_id =? and is_deleted =0 "
_addUserAnswerSQL = "INSERT INTO question_user_answer(uid ,question_id,platform,source,answers,is_correct ) VALUES(?,?,?,?,?,?)"
_checkAnswerSQL = "SELECT count(1) from question_answer where is_correct =1 and question_id = ? and answer_id IN(%s) "
_getRandomPicSQL = "SELECT x,y,src from question_verify_pic where id =? "
_getListPicSQL = "SELECT id from question_verify_pic limit ? ,? "
_getPicCntSQL = "SELECT COUNT(*) FROM question_verify_pic "
)
// GetQusInfo info
func (d *Dao) GetQusInfo(c context.Context, qid int64) (oi *model.Question, err error) {
oi = &model.Question{}
row := d.db.QueryRow(c, _getQusSQL, qid)
if err = row.Scan(&oi.QsID, &oi.QsType, &oi.AnswerType, &oi.QsName, &oi.QsBId, &oi.QsDif, &oi.IsDeleted); err != nil {
if err == sql.ErrNoRows {
oi = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// InsertQus add
func (d *Dao) InsertQus(c context.Context, oi *model.Question) (lastID int64, err error) {
res, err := d.db.Exec(c, _addQusSQL, oi.QsID, oi.QsType, oi.AnswerType, oi.QsName, oi.QsBId, oi.QsDif)
if err != nil {
log.Error("[dao.question|GetQusList] d.db.Query err: %v", err)
return
}
lastID, err = res.LastInsertId()
return
}
// GetQusList list
func (d *Dao) GetQusList(c context.Context, offset int, limitnum int, qBid int64) (res []*model.Question, err error) {
res = make([]*model.Question, 0)
_sql := _getQuslistSQL
if qBid > 0 {
_sql = _getQuslistBywhereSQL
}
rows, err := d.db.Query(c, _sql, qBid, offset, limitnum)
if err != nil {
log.Error("[dao.question|GetQusList] d.db.Query err: %v %d,%d", err, offset, limitnum)
return
}
defer rows.Close()
for rows.Next() {
oi := &model.Question{}
if err = rows.Scan(&oi.QsID, &oi.QsType, &oi.AnswerType, &oi.QsName, &oi.QsBId, &oi.QsDif, &oi.IsDeleted); err != nil {
log.Error("[dao.question|GetOrder] rows.Scan err: %v", res)
return
}
res = append(res, oi)
}
return
}
// GetQusIds ids
func (d *Dao) GetQusIds(c context.Context, bankID int64) (ids []int64, err error) {
if ids = d.GetBankQuestionsCache(c, bankID); len(ids) > 1 {
return
}
rows, err := d.db.Query(c, _getAllQusByBankID, bankID)
if err != nil {
log.Error("d.GetQusIds(%d) error(%v)", bankID, err)
return
}
defer rows.Close()
for rows.Next() {
var temp int64
if err = rows.Scan(&temp); err != nil {
log.Error("d.GetQusIds(%d) rows.Scan() error(%v)", bankID, err)
return
}
ids = append(ids, temp)
}
d.SetBankQuestionsCache(c, bankID, ids)
return
}
// DelQus del
func (d *Dao) DelQus(c context.Context, qid int64) (affect int64, err error) {
res, err := d.db.Exec(c, _delQusSQL, 1, qid)
if err != nil {
log.Error("d.DelQus(qbid:%d, dmid:%d) error(%v)", qid, 1, err)
return
}
return res.RowsAffected()
}
// UpdateQus update
func (d *Dao) UpdateQus(c context.Context, update *model.ArgUpdateQus, answers []model.Answer) (affect int64, err error) {
res, err := d.db.Exec(c, _updateQusSQL, update.Type, update.AnType, update.Name, update.BId, update.Dif, update.QsID)
if err != nil {
log.Error("d.UpdateQus(qbid:%d, dmid:%d) error(%v)", update.QsID, update.QsID, err)
return
}
return res.RowsAffected()
}
// GetQusCount cnt
func (d *Dao) GetQusCount(c context.Context, bid int64) (total int64, err error) {
var cntSQL string
if bid == 0 {
cntSQL = _getQusCntSQL
err = d.db.QueryRow(c, cntSQL).Scan(&total)
} else {
cntSQL = _getQusCntSQL + "and question_bank_id = ?"
err = d.db.QueryRow(c, cntSQL, bid).Scan(&total)
}
if err != nil {
log.Error("d.GetQusCount error(%v)", err)
return
}
return
}
// InserAnwser add
func (d *Dao) InserAnwser(c context.Context, answer *model.AnswerAdd) (affect int64, err error) {
res, err := d.db.Exec(c, _addAnswerSQL, answer.AnswerID, answer.QsID, answer.AnswerContent, answer.IsCorrect)
if err != nil {
log.Error("d.InserAnwser() error(%v)", err)
return
}
affect, err = res.LastInsertId()
return
}
// MultiAddAnwser add
func (d *Dao) MultiAddAnwser(c context.Context, answers []*model.AnswerAdd) (err error) {
length := len(answers)
if length == 0 {
return
}
values := strings.Trim(strings.Repeat("(?, ?, ?, ?),", length), ",")
args := make([]interface{}, 0)
for _, ins := range answers {
AnswerID := time.Now().UnixNano() / 1e6
time.Sleep(time.Millisecond)
args = append(args, AnswerID, ins.QsID, ins.AnswerContent, ins.IsCorrect)
}
_, err = d.db.Exec(c, fmt.Sprintf(_multyAddAnswerSQL, values), args...)
if err != nil {
log.Error("d.InserAnwser() error(%v)", err)
return
}
return
}
// UpdateAnwser upd
func (d *Dao) UpdateAnwser(c context.Context, answer *model.AnswerAdd) (affect int64, err error) {
res, err := d.db.Exec(c, _updateAnswerSQL, answer.AnswerContent, answer.IsCorrect, answer.AnswerID)
if err != nil {
log.Error("d.UpdateAnwser() error(%v)", err)
return
}
affect, err = res.RowsAffected()
return
}
// DelAnwser del
func (d *Dao) DelAnwser(c context.Context, qusID int64) (affect int64, err error) {
res, err := d.db.Exec(c, _delAnswerSQL, qusID)
if err != nil {
log.Error("d.UpdateAnwser() error(%v)", err)
return
}
affect, err = res.RowsAffected()
return
}
// GetAnswerList list
func (d *Dao) GetAnswerList(c context.Context, qusID int64) (res []*model.Answer, err error) {
res = make([]*model.Answer, 0)
rows, err := d.db.Query(c, _getAnswerListSQL, qusID)
if err != nil {
log.Error("[dao.GetAnswerList] d.db.Query err: %v", err)
return
}
defer rows.Close()
for rows.Next() {
oi := &model.Answer{}
if err = rows.Scan(&oi.AnswerID, &oi.QsID, &oi.AnswerContent, &oi.IsCorrect); err != nil {
log.Error("[dao.question|GetOrder] rows.Scan err: %v", res)
return
}
res = append(res, oi)
}
return
}
// AddUserAnwser add
func (d *Dao) AddUserAnwser(c context.Context, answer *model.ArgCheckAnswer, isCorrect int8) (affect int64, err error) {
ids := xstr.JoinInts(answer.Answers)
res, err := d.db.Exec(c, _addUserAnswerSQL, answer.UID, answer.QsID, answer.Platform, answer.Source, ids, isCorrect)
if err != nil {
log.Error("d.InserAnwser() error(%v)", err)
return
}
affect, err = res.LastInsertId()
return
}
// CheckAnswer check
func (d *Dao) CheckAnswer(c context.Context, qsid int64, ids []int64) (total int, err error) {
err = d.db.QueryRow(c, fmt.Sprintf(_checkAnswerSQL, xstr.JoinInts(ids)), qsid).Scan(&total)
if err != nil {
log.Error("d.GetQusBankCount error(%v)", err)
return
}
return
}
// GetRandomPic get
func (d *Dao) GetRandomPic(c context.Context, id int) (oi *model.QuestBkPic, err error) {
oi = &model.QuestBkPic{}
row := d.db.QueryRow(c, _getRandomPicSQL, id)
if err = row.Scan(&oi.X, &oi.Y, &oi.Src); err != nil {
if err == sql.ErrNoRows {
oi = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// GetAllPicIds ids
func (d *Dao) GetAllPicIds(c context.Context, offset int, limitnum int) (ids []int, err error) {
rows, err := d.db.Query(c, _getListPicSQL, offset, limitnum)
if err != nil {
log.Error("[dao.GetAllPicIds] d.db.Query err: %v %d,%d", err, offset, limitnum)
return
}
defer rows.Close()
for rows.Next() {
var oi int
if err = rows.Scan(&oi); err != nil {
log.Error("[dao.question|GetOrder] rows.Scan err: %v", ids)
return
}
ids = append(ids, oi)
}
return
}
// GetPicCount cnt
func (d *Dao) GetPicCount(c context.Context) (total int, err error) {
err = d.db.QueryRow(c, _getPicCntSQL).Scan(&total)
if err != nil {
log.Error("d.GetQusCount error(%v)", err)
return
}
return
}

View File

@@ -0,0 +1,256 @@
package dao
import (
"bytes"
"context"
"fmt"
"strconv"
"go-common/app/service/openplatform/anti-fraud/model"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_QusBankInfo = "SELECT qb_id ,qb_name,cd_time,max_retry_time,is_deleted FROM question_bank where qb_id= ? and is_deleted= 0 "
_addQusBank = "insert into question_bank(qb_id ,qb_name,cd_time,max_retry_time,is_deleted) values(?,?,?,?,?)"
_qusBanklist = "SELECT qb_id ,qb_name,cd_time,max_retry_time,is_deleted FROM question_bank where is_deleted= 0 and total_cnt < ? and qb_id IN(%s) order by id desc "
_qusBankcnt = "SELECT COUNT(*) FROM question_bank where is_deleted= 0 "
_delQusBank = "update question_bank set is_deleted = ? where qb_id =? "
_searchQusBank = "SELECT qb_id ,qb_name,cd_time,max_retry_time,is_deleted FROM question_bank where is_deleted= 0 and qb_name LIKE ? "
_updateQusBank = "update question_bank set qb_name = ? ,max_retry_time=? ,cd_time = ? where qb_id =? "
_qusBanklistByids = "SELECT qb_id, qb_name, cd_time, max_retry_time, is_deleted FROM question_bank WHERE is_deleted = 0 and qb_id IN(%s)"
_getStaticQusBankList = "SELECT id, qb_id,qb_name,cd_time,max_retry_time,is_deleted,total_cnt ,easy_cnt,normal_cnt,hard_cnt from question_bank where is_deleted =0 "
_getQbID = "SELECT qb_id FROM question_bank where id= ? and is_deleted= 0"
_getQusBankByID = "select a.qb_id,a.qb_name,a.cd_time,a.max_retry_time , a.is_deleted, count(if(b.is_deleted = 0,true,null)) total " +
"from question_bank a left join question b on a.qb_id = b.question_bank_id WHERE a.qb_id IN(%s) GROUP BY a.qb_id HAVING a.is_deleted = 0 "
_getQusBankCnt = "SELECT sum(case when difficulty = 1 then 1 else 0 end ) 'easy', sum(case when difficulty = 2 then 1 else 0 end ) 'normal'," +
"sum(case when difficulty = 3 then 1 else 0 end ) 'hard',count(id) 'total' from question WHERE is_deleted =0 and `question_bank_id`= ?"
_updateQusBankCnt = "update question_bank set easy_cnt = ? ,normal_cnt=? ,hard_cnt = ?,total_cnt = ? where qb_id =? "
)
// GetQusBankInfo info
func (d *Dao) GetQusBankInfo(c context.Context, qbid int64) (oi *model.QuestionBank, err error) {
oi = &model.QuestionBank{}
row := d.db.QueryRow(c, _QusBankInfo, qbid)
if err = row.Scan(&oi.QsBId, &oi.QBName, &oi.CdTime, &oi.MaxRetryTime, &oi.IsDeleted); err != nil {
if err == sql.ErrNoRows {
oi = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// InsertQusBank add
func (d *Dao) InsertQusBank(c context.Context, oi *model.QuestionBank) (lastID int64, err error) {
res, err := d.db.Exec(c, _addQusBank, oi.QsBId, oi.QBName, oi.CdTime, oi.MaxRetryTime, oi.IsDeleted)
if err != nil {
log.Error("[dao.question|GetQusBankList] d.db.Query err: %v", err)
return
}
lastID, err = res.LastInsertId()
return
}
// StatisticsQusBank 统计bank
func (d *Dao) StatisticsQusBank(c context.Context, offset int, limitnum int, name string) (res []*model.QusBankSt, err error) {
res = make([]*model.QusBankSt, 0)
var rows *sql.Rows
var _sql string
if name == "" {
_sql = _getStaticQusBankList + " order by id desc limit ? ,? "
rows, err = d.db.Query(c, _sql, offset, limitnum)
} else {
_sql = _getStaticQusBankList + " and qb_name LIKE ? order by id desc limit ? ,? "
name = "%" + name + "%"
rows, err = d.db.Query(c, _sql, name, offset, limitnum)
}
if err != nil {
log.Error("[dao.question|GetQusBankList] d.db.Query err: %v %d,%d", err, offset, limitnum)
return
}
defer rows.Close()
for rows.Next() {
oi := &model.QusBankSt{}
if err = rows.Scan(&oi.ID, &oi.QsBId, &oi.QBName, &oi.CdTime, &oi.MaxRetryTime, &oi.IsDeleted, &oi.TotalCnt, &oi.EasyCnt, &oi.NormalCnt, &oi.HardCnt); err != nil {
log.Error("[dao.question|GetOrder] rows.Scan err: %v", res)
return
}
res = append(res, oi)
}
return
}
// GetQusBankList list
func (d *Dao) GetQusBankList(c context.Context, cnt int, ids []int64) (res []*model.QuestionBank, err error) {
res = make([]*model.QuestionBank, 0)
rows, err := d.db.Query(c, fmt.Sprintf(_qusBanklist, xstr.JoinInts([]int64(ids))), cnt)
if err != nil {
log.Error("[dao.question|GetQusBankList] d.db.Query err: %v %d,%d", err)
return
}
defer rows.Close()
for rows.Next() {
oi := &model.QuestionBank{}
if err = rows.Scan(&oi.QsBId, &oi.QBName, &oi.CdTime, &oi.MaxRetryTime, &oi.IsDeleted); err != nil {
log.Error("[dao.question|GetOrder] rows.Scan err: %v", res)
return
}
res = append(res, oi)
}
return
}
// DelQusBank del
func (d *Dao) DelQusBank(c context.Context, qbID int64, status int8) (affect int64, err error) {
res, err := d.db.Exec(c, _delQusBank, status, qbID)
if err != nil {
log.Error("d.UpdateQusBank(qbid:%d, dmid:%d) error(%v)", qbID, status, err)
return
}
s, e := res.RowsAffected()
log.Error("d.UpdateQusBank(qbxxxxxid:%d, dxxxxxmid:%d) error(%v)", qbID, s, e)
return res.RowsAffected()
}
// UpdateQusBank update
func (d *Dao) UpdateQusBank(c context.Context, qbID int64, name string, trytime int64, cdtime int64) (affect int64, err error) {
res, err := d.db.Exec(c, _updateQusBank, name, trytime, cdtime, qbID)
if err != nil {
log.Error("d.UpdateQusBank(qbid:%d, dmid:%d) error(%v)", qbID, trytime, err)
return
}
return res.RowsAffected()
}
// GetQusBankCount cnt
func (d *Dao) GetQusBankCount(c context.Context, name string) (total int64, err error) {
var cntSQL string
if name == "" {
cntSQL = _qusBankcnt
err = d.db.QueryRow(c, cntSQL).Scan(&total)
} else {
cntSQL = _qusBankcnt + " and qb_name LIKE ? "
name = "%" + name + "%"
err = d.db.QueryRow(c, cntSQL, name).Scan(&total)
}
if err != nil {
log.Error("d.GetQusBankCount error(%v)", err)
return
}
return
}
// BankSearch search
func (d *Dao) BankSearch(c context.Context, name string) (res []*model.QuestionBank, err error) {
res = make([]*model.QuestionBank, 0)
rows, err := d.db.Query(c, _searchQusBank, "%"+name+"%")
if err != nil {
log.Error("[dao.question|BankSearch] d.db.Query err: %v", err)
return
}
defer rows.Close()
for rows.Next() {
oi := &model.QuestionBank{}
if err = rows.Scan(&oi.QsBId, &oi.QBName, &oi.CdTime, &oi.MaxRetryTime, &oi.IsDeleted); err != nil {
log.Error("[dao.question|GetOrder] rows.Scan err: %v", res)
return
}
res = append(res, oi)
}
return
}
// GetQusBankListByIds ids
func (d *Dao) GetQusBankListByIds(c context.Context, ids []int64) (res []*model.QuestionBank, err error) {
res = make([]*model.QuestionBank, 0)
rows, err := d.db.Query(c, fmt.Sprintf(_qusBanklistByids, xstr.JoinInts([]int64(ids))))
if err != nil {
log.Error("[dao.question|GetQusBankListByIds] d.db.Query err: %v", err)
return
}
defer rows.Close()
for rows.Next() {
oi := &model.QuestionBank{}
if err = rows.Scan(&oi.QsBId, &oi.QBName, &oi.CdTime, &oi.MaxRetryTime, &oi.IsDeleted); err != nil {
log.Error("[dao.question|GetOrder] rows.Scan err: %v", res)
return
}
res = append(res, oi)
}
return
}
// GetQBId id
func (d *Dao) GetQBId(c context.Context, id int64) (qbID int64, err error) {
err = d.db.QueryRow(c, _getQbID, id).Scan(&qbID)
if err != nil {
log.Error("d.GetQBId error(%v)", err.Error())
return
}
return
}
// GetBankInfoByQBid byids
func (d *Dao) GetBankInfoByQBid(c context.Context, qbID map[int64]int64) (res []*model.QusBankSt, err error) {
rows, err := d.db.Query(c, fmt.Sprintf(_getQusBankByID, d.CoverStr(qbID)))
fmt.Println(fmt.Sprintf(_getQusBankByID, d.CoverStr(qbID)))
if err != nil {
log.Error(fmt.Sprintf("d.mysql.Query(%s) error(%+v)", _getQusBankByID, err.Error()))
return
}
defer rows.Close()
for rows.Next() {
oi := &model.QusBankSt{}
if err = rows.Scan(&oi.QsBId, &oi.QBName, &oi.CdTime, &oi.MaxRetryTime, &oi.IsDeleted, &oi.TotalCnt); err != nil {
log.Error(fmt.Sprintf("d.mysql.Query(%s) error(%+v)", _getQusBankByID, err.Error()))
return
}
res = append(res, oi)
}
return
}
// CoverStr str
func (d *Dao) CoverStr(strs map[int64]int64) string {
var buf = bytes.NewBuffer(nil)
for _, str := range strs {
buf.WriteString("'")
buf.WriteString(strconv.FormatInt(str, 10))
buf.WriteString("'")
buf.WriteString(",")
}
buf.Truncate(buf.Len() - 1)
return buf.String()
}
// UpdateQsBankCnt 更新数量
func (d *Dao) UpdateQsBankCnt(c context.Context, qid int64) (effid int64, err error) {
oi := &model.QusBankCnt{}
err = d.db.QueryRow(c, _getQusBankCnt, qid).Scan(&oi.EasyCnt, &oi.NormalCnt, &oi.HardCnt, &oi.TotalCnt)
if err != nil {
log.Error("d.UpdateQsBankCnt error(%v)", err.Error())
return
}
res, err := d.db.Exec(c, _updateQusBankCnt, &oi.EasyCnt, &oi.NormalCnt, &oi.HardCnt, &oi.TotalCnt, qid)
if err != nil {
log.Error("d._updateQusBankCnt(qbid:%d, dmid:%d) error(%v)", err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,243 @@
package dao
import (
"context"
"fmt"
"strconv"
"strings"
"go-common/app/service/openplatform/anti-fraud/model"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_addQuestionBankBind = "INSERT INTO question_bank_bind (target_item, target_item_type, bank_id, use_in_time, source, is_deleted) VALUES %s"
_getQuestionBankBindWithDeletedNew = " SELECT a.target_item,a.target_item_type,a.bank_id,a.use_in_time,b.id,b.qb_name" +
" FROM question_bank_bind as a join question_bank as b" +
" ON a.bank_id = b.qb_id" +
" where a.target_item IN(%s) and a.target_item_type = ? and a.source = ?"
_getQuestionBankBind = _getQuestionBankBindWithDeletedNew + " AND a.is_deleted = 0"
_updateQuestionBankBind = "UPDATE question_bank_bind set bank_id = ?, use_in_time = ?, is_deleted = 0" +
" WHERE source = ?" +
" AND target_item_type = ?" +
" AND target_item IN(%s)"
_deleteQuestionBankBind = "UPDATE question_bank_bind SET is_deleted = 1 WHERE target_item IN(%s)" +
" AND target_item_type = ?" +
" AND source = ?"
_getBindItem = "SELECT id, target_item, target_item_type, bank_id, use_in_time, source, is_deleted, ctime, mtime FROM question_bank_bind WHERE bank_id = ? AND is_deleted = 0 limit ?,?"
_countBindItem = "SELECT COUNT(1) as count FROM question_bank_bind WHERE bank_id = ? AND is_deleted = 0"
)
// AddBankBind add
func (d *Dao) AddBankBind(c context.Context, update []model.ArgQuestionBankBind, insert []model.ArgQuestionBankBind) (err error) {
lenUpdate := len(update)
lenInsert := len(insert)
if lenUpdate == 0 && lenInsert == 0 {
return
}
updateItems := map[int64]*model.ArgQuestionBankBindToDb{}
insertItems := map[int64]*model.ArgQuestionBankBindToDb{}
for _, v := range update {
if _, ok := updateItems[v.QsBId]; !ok {
updateItems[v.QsBId] = &model.ArgQuestionBankBindToDb{
QsBId: v.QsBId,
Source: v.Source,
TargetItemType: v.TargetItemType,
UseInTime: v.UseInTime,
TargetItems: []string{v.TargetItems},
}
} else {
updateItems[v.QsBId].TargetItems = append(updateItems[v.QsBId].TargetItems, v.TargetItems)
}
d.DelTargetItemBindCache(c, v.TargetItems)
}
for _, v := range insert {
if _, ok := insertItems[v.QsBId]; !ok {
insertItems[v.QsBId] = &model.ArgQuestionBankBindToDb{
QsBId: v.QsBId,
Source: v.Source,
TargetItemType: v.TargetItemType,
UseInTime: v.UseInTime,
TargetItems: []string{v.TargetItems},
}
} else {
insertItems[v.QsBId].TargetItems = append(insertItems[v.QsBId].TargetItems, v.TargetItems)
}
}
tx, err := d.db.Begin(c)
if err != nil {
log.Error("d.AddBankBind(%v) error(%v)", err)
return
}
defer func() {
if err != nil {
if err = tx.Rollback(); err != nil {
log.Error("tx.Rollback() error(%v)", err)
}
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit() error(%v)", err)
return
}
}()
if len(updateItems) > 0 {
for _, v := range updateItems {
sql := fmt.Sprintf(_updateQuestionBankBind, `"`+strings.Join(v.TargetItems, `","`)+`"`)
_, err = tx.Exec(sql, v.QsBId, v.UseInTime, v.Source, v.TargetItemType)
if err != nil {
log.Error("d.AddBankBind(%v, %v) error(%v)", update, insert, err)
return
}
}
}
if len(insertItems) > 0 {
for _, v := range insertItems {
lenInsert = len(v.TargetItems)
if lenInsert > 0 {
placeholder := strings.Trim(strings.Repeat("(?, ?, ?, ?, ?, ?),", lenInsert), ",")
values := make([]interface{}, 0)
for _, ins := range v.TargetItems {
values = append(values, ins, v.TargetItemType, v.QsBId, v.UseInTime, v.Source, 0)
}
_, err = tx.Exec(fmt.Sprintf(_addQuestionBankBind, placeholder), values...)
if err != nil {
log.Error("d.AddBankBind() tx.Exec(%s) error(%v)", fmt.Sprintf(_addQuestionBankBind, values), err)
return
}
}
}
}
return
}
// GetBankBind 查询绑定关系
func (d *Dao) GetBankBind(c context.Context, source, targetItemType int8, targetItem []string, withDeleted bool) (list []*model.QuestionBankBind, err error) {
list = make([]*model.QuestionBankBind, 0)
if len(targetItem) == 0 {
return
}
sql := _getQuestionBankBind
if withDeleted {
sql = _getQuestionBankBindWithDeletedNew
}
sql = fmt.Sprintf(sql, `"`+strings.Join(targetItem, `","`)+`"`)
rows, err := d.db.Query(c, sql, targetItemType, source)
if err != nil {
log.Error("d.GetBankBind(%v, %v, %v) db.Query() error(%v)", source, targetItemType, targetItem, err)
return
}
defer rows.Close()
for rows.Next() {
tmp := &model.QuestionBankBind{QuestionBank: new(model.QuestionBank)}
err = rows.Scan(&tmp.TargetItem, &tmp.TargetItemType, &tmp.QsBId, &tmp.UseInTime, &tmp.ID, &tmp.QuestionBank.QBName)
if err != nil {
return
}
list = append(list, tmp)
}
return
}
// GetBindBank 获取已绑定的题库信息
func (d *Dao) GetBindBank(c context.Context, source, targetItemType int8, targetItem []string) (binds []*model.QuestionBankBind, err error) {
// list = make([]*model.QuestionBankBind, 0)
binds, err = d.GetBankBind(c, source, targetItemType, targetItem, false)
if len(binds) == 0 {
return
}
var bankIds []int64
for _, bind := range binds {
bankIds = append(bankIds, bind.QsBId)
}
banks, err := d.GetQusBankListByIds(c, bankIds)
if err != nil {
return
}
for _, bind := range binds {
for _, bank := range banks {
if bind.QsBId == bank.QsBId {
bind.QuestionBank = bank
break
}
}
}
return
}
// CountBindItem cnt
func (d *Dao) CountBindItem(c context.Context, bankID int64) (count int64, err error) {
if err = d.db.QueryRow(c, _countBindItem, bankID).Scan(&count); err != nil {
log.Error("d.CountBindItem(%d) error(%v)", bankID, err)
}
return
}
// QuestionBankUnbind 解绑
func (d *Dao) QuestionBankUnbind(c context.Context, delIds []int64, targetType int8, source int8) (err error) {
if len(delIds) > 0 {
sql := fmt.Sprintf(_deleteQuestionBankBind, xstr.JoinInts(delIds))
_, err = d.db.Exec(c, sql, targetType, source)
if err != nil {
log.Error("d.QuestionBankUnbind() tx.Exec(%s) error(%v)", fmt.Sprintf(_deleteQuestionBankBind, xstr.JoinInts(delIds)), err)
return
}
}
for _, delID := range delIds {
d.DelTargetItemBindCache(c, strconv.FormatInt(delID, 10))
}
return
}
// GetBindItem itm
func (d *Dao) GetBindItem(c context.Context, bankID int64, page, pageSize int) (list []*model.QuestionBankBind, total int64, err error) {
list = make([]*model.QuestionBankBind, 0)
rows, err := d.db.Query(c, _getBindItem, bankID, (page-1)*pageSize, pageSize)
if err != nil {
log.Error("d.GetBindItem(%d) error(%v)", bankID, err)
return
}
defer rows.Close()
for rows.Next() {
tmp := &model.QuestionBankBind{}
err = rows.Scan(&tmp.ID, &tmp.TargetItem, &tmp.TargetItemType, &tmp.QsBId, &tmp.UseInTime, &tmp.Source, &tmp.IsDeleted, &tmp.Ctime, &tmp.Mtime)
if err != nil {
return
}
list = append(list, tmp)
}
total, err = d.CountBindItem(c, bankID)
if err != nil {
log.Error("d.GetBindItem(%d, %d, %d) error(%v)", bankID, page, pageSize, err)
return
}
return
}

View File

@@ -0,0 +1,41 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestGetBankBind(t *testing.T) {
Convey("TestGetBankBind: ", t, func() {
res, err := d.GetBankBind(context.TODO(), 1, 1, []string{"1111"}, true)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestGetBindBank(t *testing.T) {
Convey("TestGetBindBank: ", t, func() {
res, err := d.GetBindBank(context.TODO(), 1, 1, []string{"1111"})
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestCountBindItem(t *testing.T) {
Convey("TestCountBindItem: ", t, func() {
res, err := d.CountBindItem(context.TODO(), _qbid)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestGetBindItem(t *testing.T) {
Convey("TestCountBindItem: ", t, func() {
res, cnt, err := d.GetBindItem(context.TODO(), _qbid, _page, _pagesize)
So(err, ShouldBeNil)
So(cnt, ShouldNotBeNil)
So(res, ShouldNotBeNil)
})
}

View File

@@ -0,0 +1,53 @@
package dao
import (
"context"
"flag"
"fmt"
"testing"
"go-common/app/service/openplatform/anti-fraud/conf"
. "github.com/smartystreets/goconvey/convey"
)
func init() {
flag.Parse()
if err := conf.Init(); err != nil {
panic(fmt.Errorf("conf.Init() error(%v)", err))
}
d = New(conf.Conf)
}
func TestGetQusBankListByIds(t *testing.T) {
Convey("TestGetQusBankListByIds: ", t, func() {
testIds := []int64{1527233672941, 2, 3}
res, err := d.GetQusBankListByIds(context.TODO(), testIds)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestBankSearch(t *testing.T) {
Convey("TestBankSearch: ", t, func() {
res, err := d.BankSearch(context.TODO(), "name")
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestGetQusBankCount(t *testing.T) {
Convey("GetQusBankCount: ", t, func() {
res, err := d.GetQusBankCount(context.TODO(), "wlt")
So(err, ShouldBeNil)
So(res, ShouldBeGreaterThanOrEqualTo, 0)
})
}
func TestUpdateQsBankCnt(t *testing.T) {
Convey("GetQusBankCount: ", t, func() {
res, err := d.UpdateQsBankCnt(context.TODO(), 1527233672941)
So(err, ShouldBeNil)
So(res, ShouldBeGreaterThanOrEqualTo, 0)
})
}

View File

@@ -0,0 +1,64 @@
package dao
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
const (
_qid = 1527480165645
_qbid = 1527233672941
_page = 0
_pagesize = 10
)
func TestGetQusInfo(t *testing.T) {
Convey("TestBankSearch: ", t, func() {
res, err := d.GetQusInfo(context.TODO(), _qid)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestGetQusList(t *testing.T) {
Convey("TestBankSearch: ", t, func() {
res, err := d.GetQusList(context.TODO(), _page, _pagesize, _qbid)
So(err, ShouldBeNil)
So(res, ShouldNotBeNil)
})
}
func TestGetQusIds(t *testing.T) {
Convey("TestGetQusIds: ", t, func() {
res, err := d.GetQusIds(context.TODO(), _qbid)
length := len(res)
So(err, ShouldBeNil)
So(length, ShouldBeGreaterThan, 0)
})
}
func TestGetQusCount(t *testing.T) {
Convey("TestGetQusCount: ", t, func() {
cnt, err := d.GetQusCount(context.TODO(), _qbid)
So(err, ShouldBeNil)
So(cnt, ShouldBeGreaterThan, 0)
})
}
func TestGetAnswerList(t *testing.T) {
Convey("TestGetAnswerList: ", t, func() {
cnt, err := d.GetAnswerList(context.TODO(), _qid)
So(err, ShouldBeNil)
So(cnt, ShouldNotBeNil)
})
}
func TestGDelQus(t *testing.T) {
Convey("TestGetAnswerList: ", t, func() {
cnt, err := d.DelQus(context.TODO(), 1527241107344)
So(err, ShouldBeNil)
So(cnt, ShouldNotBeNil)
})
}

View File

@@ -0,0 +1,222 @@
package dao
import (
"bytes"
"context"
"crypto/md5"
"encoding/binary"
"encoding/hex"
"encoding/json"
"github.com/json-iterator/go"
"go-common/app/service/openplatform/anti-fraud/conf"
"go-common/app/service/openplatform/anti-fraud/model"
"go-common/library/cache/redis"
"go-common/library/ecode"
"go-common/library/log"
"net/http"
"time"
)
//CheckSalesTime 检查售卖时间
func (d *Dao) CheckSalesTime(c context.Context, mid, itemID, salesTime, saleTimeOut int64) (err error) {
key := model.GetSalesLimitKey(mid)
conn := d.redis.Get(c)
defer conn.Close()
var (
flag int64
data []byte
)
data, _ = redis.Bytes(conn.Do("GET", key))
json.Unmarshal(data, &flag)
if flag == 1 {
return ecode.AntiSalesTimeErr
}
if salesTime > time.Now().Unix() {
conn.Do("SET", key, 1, "EX", saleTimeOut)
return ecode.AntiSalesTimeErr
}
return nil
}
//CheckIPChange 检查用户ip变更
func (d *Dao) CheckIPChange(c context.Context, mid int64, ip string, changeTime int64) (err error) {
key := model.GetIPChangeKey(mid)
conn := d.redis.Get(c)
defer conn.Close()
var (
flag string
data []byte
)
data, _ = redis.Bytes(conn.Do("GET", key))
json.Unmarshal(data, &flag)
go func(c context.Context, key string, ip string) {
conn := d.redis.Get(c)
defer conn.Close()
conn.Do("SET", key, ip, "EX", changeTime)
}(context.Background(), key, ip)
if flag != "" && flag != ip {
return ecode.AntiIPChangeLimit
}
return nil
}
//CheckLimitNum 检查限制次数
func (d *Dao) CheckLimitNum(c context.Context, key string, num int64, pastTime int64) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
pastTime = pastTime * 1e9
currentTime := time.Now().UnixNano()
conn.Do("ZADD", key, currentTime, currentTime)
data, _ := redis.Int64(conn.Do("ZCOUNT", key, currentTime-pastTime, currentTime))
go func(c context.Context, key string, pastTime, currentTime int64, flag bool) {
conn := d.redis.Get(c)
defer conn.Close()
conn.Do("EXPIRE", key, pastTime/1e9)
if flag {
conn.Do("ZREMRANGEBYRANK", key, 0, 0)
}
}(context.Background(), key, pastTime, currentTime, data > num)
if data > num {
return ecode.AntiLimitNumUpper
}
return nil
}
//Voucher 凭证
func (d *Dao) Voucher(c context.Context, mid int64, ip string, itemID, customer, voucherType int64) (voucher string) {
s := make([]byte, 0)
buf := bytes.NewBuffer(s)
binary.Write(buf, binary.BigEndian, mid)
binary.Write(buf, binary.BigEndian, []byte(ip))
binary.Write(buf, binary.BigEndian, itemID)
binary.Write(buf, binary.BigEndian, customer)
binary.Write(buf, binary.BigEndian, voucherType)
binary.Write(buf, binary.BigEndian, time.Now().UnixNano())
digest := md5.Sum(buf.Bytes())
voucher = hex.EncodeToString(digest[:])
conn := d.redis.Get(c)
defer conn.Close()
key := model.GetUserVoucherKey(mid, voucher, voucherType)
conn.Do("SET", key, 1, "EX", model.RedisUserVoucherKeyTimeOut)
return
}
//CheckVoucher 验证用户凭证,一次性
func (d *Dao) CheckVoucher(c context.Context, mid int64, voucher string, voucherType int64) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
key := model.GetUserVoucherKey(mid, voucher, voucherType)
data, _ := redis.Int64(conn.Do("INCR", key))
conn.Do("DEL", key)
if data < 2 {
return ecode.AntiCheckVoucherErr
}
return nil
}
//IncrGeetestCount 统计一小时内极验的请求数
func (d *Dao) IncrGeetestCount(c context.Context) {
conn := d.redis.Get(c)
defer conn.Close()
key := model.GetGeetestCountKey()
conn.Do("INCR", key)
conn.Do("EXPIRE", key, model.RedisGeetestCountKeyTimeOut)
}
//CheckGeetestCount 检查极验总数是否达到上限
func (d *Dao) CheckGeetestCount(c context.Context) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
key := model.GetGeetestCountKey()
var (
data []byte
count int64
)
data, _ = redis.Bytes(conn.Do("GET", key))
json.Unmarshal(data, &count)
if count > d.c.Geetest.Count {
log.Info("极验总数达到上限")
return ecode.AntiGeetestCountUpper
}
return
}
// CheckBlack 检测黑名单
func (d *Dao) CheckBlack(c context.Context, customerId, mid int64, clientIP string) (err error) {
conn := d.redis.Get(c)
defer conn.Close()
midKey := model.GetMIDBlackKey(customerId, mid)
ipKey := model.GetIPBlackKey(customerId, clientIP)
data, err := redis.Int64s(conn.Do("MGET", midKey, ipKey))
if err != nil {
log.Info("获取黑名单出错 %s %s", midKey, ipKey)
return nil
}
for _, value := range data {
if value == 1 {
return ecode.AntiBlackErr
}
}
return nil
}
// PayShield 支付风控
func (d *Dao) PayShield(c context.Context, data *model.ShieldData) {
var res struct {
errno int64
msg string
data interface{}
}
params, err := jsoniter.Marshal(data)
if err != nil {
log.Info("json marshal err %v", err)
return
}
log.Info("req pay shield params %s", string(params))
req, err := http.NewRequest("POST", conf.Conf.URL.Shield, bytes.NewBuffer(params))
if err != nil {
log.Warn("new request err url %s, err %v", conf.Conf.URL.Shield, err)
return
}
req.Header.Set("Content-Type", "application/json")
err = d.client.Do(c, req, &res)
if err != nil || res.errno != 0 {
log.Warn("client do err url %s, err %v", conf.Conf.URL.Shield, err)
return
}
}
// SetexRedisKey 设置redis key
func (d *Dao) SetexRedisKey(c context.Context, key string, timeout int64) {
conn := d.redis.Get(c)
defer conn.Close()
conn.Do("SET", key, 1, "EX", timeout)
}
// AddPayData .
func (d *Dao) AddPayData(data *model.ShieldData) {
d.payData <- data
}
// SyncPayShield .
func (d *Dao) SyncPayShield(c context.Context) {
for {
data := <-d.payData
d.PayShield(c, data)
}
}