123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- package service
- import (
- "bytes"
- "context"
- "crypto/md5"
- "crypto/sha256"
- "encoding/base64"
- "encoding/hex"
- "fmt"
- "net/url"
- "strconv"
- "strings"
- "time"
- hmdl "go-common/app/interface/main/history/model"
- hrpc "go-common/app/interface/main/history/rpc/client"
- "go-common/app/interface/main/report-click/conf"
- "go-common/app/interface/main/report-click/dao"
- "go-common/app/interface/main/report-click/service/crypto/aes"
- "go-common/app/interface/main/report-click/service/crypto/padding"
- accmdl "go-common/app/service/main/account/model"
- accrpc "go-common/app/service/main/account/rpc/client"
- "go-common/library/ecode"
- "go-common/library/log"
- "go-common/library/net/metadata"
- "go-common/library/stat/prom"
- "go-common/library/sync/pipeline/fanout"
- )
- // 0 1 2 3 4 5 6 7 8 9 : <-> d w o i k p s x m q l
- // 48 49 50 51 52 53 54 55 56 57 58 <-> 100 119 111 105 107 112 115 120 109 113 108
- var ecKeys = map[rune]rune{
- 48: 119,
- 49: 111,
- 50: 105,
- 51: 107,
- 52: 112,
- 53: 115,
- 54: 120,
- 55: 109,
- 56: 113,
- 57: 108,
- 58: 100,
- 119: 48,
- 111: 49,
- 105: 50,
- 107: 51,
- 112: 52,
- 115: 53,
- 120: 54,
- 109: 55,
- 113: 56,
- 108: 57,
- 100: 58,
- }
- // Service service struct info.
- type Service struct {
- c *conf.Config
- d *dao.Dao
- accRPC *accrpc.Service3
- hisRPC *hrpc.Service
- cache *fanout.Fanout
- promErr *prom.Prom
- promInfo *prom.Prom
- }
- // New service.
- func New(c *conf.Config) (s *Service) {
- s = &Service{
- c: c,
- d: dao.New(c),
- accRPC: accrpc.New3(c.AccRPC),
- hisRPC: hrpc.New(c.HisRPC),
- cache: fanout.New("cache", fanout.Worker(1), fanout.Buffer(1024)),
- promErr: prom.BusinessErrCount,
- promInfo: prom.BusinessInfoCount,
- }
- return
- }
- // FlashSigned flash Signed.
- func (s *Service) FlashSigned(params url.Values, secret string, now time.Time) (err error) {
- st := params.Get("stime")
- stime, err := strconv.ParseInt(st, 10, 64)
- if err != nil {
- err = ecode.ClickQueryFormatErr
- return
- }
- if now.Unix()-stime > 60 {
- err = ecode.ClickServerTimeout
- return
- }
- sign := params.Get("sign")
- params.Del("sign")
- mh := md5.Sum([]byte(strings.ToLower(params.Encode()) + secret))
- if hex.EncodeToString(mh[:]) != sign {
- err = ecode.ClickQuerySignErr
- }
- return
- }
- // Decrypt decrypt bytes by aes key and iv.
- func (s *Service) Decrypt(src []byte, aesKey, aesIv string) (res []byte, err error) {
- res, err = aes.CBCDecrypt(src, []byte(aesKey), []byte(aesIv), padding.PKCS5)
- if err != nil {
- log.Error("aes.CBCDecrypt(%s, %s, %s) error(%v)", base64.StdEncoding.EncodeToString(src), s.c.Click.AesKey, s.c.Click.AesIv, err)
- err = ecode.ClickAesDecryptErr
- }
- return
- }
- // Verify verify bytes from post body.
- func (s *Service) Verify(src []byte, aesSalt string, now time.Time) (p url.Values, err error) {
- p, err = url.ParseQuery(string(src))
- if err != nil {
- err = ecode.ClickQueryFormatErr
- return
- }
- // check server time
- st := p.Get("stime")
- stime, err := strconv.ParseInt(st, 10, 64)
- if err != nil {
- err = ecode.ClickQueryFormatErr
- return
- }
- if now.Unix()-stime > 60*3 {
- err = ecode.ClickServerTimeout
- return
- }
- // verify sign
- sign := p.Get("sign")
- sbs, err := hex.DecodeString(sign)
- if err != nil {
- log.Error("hex.DecodeString(%s) error(%v)", sign, err)
- err = ecode.ClickQuerySignErr
- return
- }
- p.Del("sign")
- // sha 256
- h := sha256.New()
- // h.Write([]byte(strings.ToLower(p.Encode())))
- h.Write([]byte(p.Encode()))
- h.Write([]byte(aesSalt))
- bs := h.Sum(nil)
- // bytes queal
- if !bytes.Equal(sbs, bs) {
- log.Error("hmac.Equal(%s, %x) params(%s) not equal", sign, bs, p.Encode())
- err = ecode.ClickHmacSignErr
- }
- return
- }
- // Play send play count to kafka.
- func (s *Service) Play(c context.Context, plat, aid, cid, part, mid, level, ftime, stime, did, ip, agent, buvid, cookieSid, refer, typeID, subType, sid, epid, playMode, platform, device, mobiAapp, autoPlay, session string) {
- if aid == "" || aid == "0" {
- return
- }
- m, errP := strconv.ParseInt(mid, 10, 64)
- if errP != nil {
- log.Warn("strconv.ParseInt(%s) error(%v)", mid, errP)
- mid = "0"
- }
- if m != 0 {
- arg := &accmdl.ArgMid{Mid: m}
- res, err := s.accRPC.Card3(c, arg)
- if err != nil {
- log.Error("s.accRPC.UserInfo() error(%v)", err)
- return
- }
- if res.Silence == 1 {
- log.Warn("user mid(%d) spacesta(%d) too lower", m, res.Silence)
- return
- }
- level = fmt.Sprintf("%d", res.Level)
- }
- s.cache.Do(c, func(ctx context.Context) {
- s.d.Play(ctx, plat, aid, cid, part, mid, level, ftime, stime, did, ip, agent, buvid, cookieSid, refer, typeID, subType, sid, epid, playMode, platform, device, mobiAapp, autoPlay, session)
- })
- }
- // GenDid gen did.
- func (s *Service) GenDid(ip string, now time.Time) string {
- var src string
- ft := now.Unix() - int64(now.Second())
- uip, ok := parseIP(ip)
- if uip == nil {
- return ""
- }
- if ok {
- src = fmt.Sprintf("%d:%d", netAtoN(uip), ft)
- return myEncryptDecrypt(src)
- }
- fs := encode(uint64(ft))
- ipRes := ipv6AtoN(uip)
- if len(ipRes) > 25 { // total 32, 25 for ip, 1 for :, 6 for ftime
- ipRes = ipRes[:25]
- }
- return fmt.Sprintf("%s:%s", ipRes, fs)
- }
- // CheckDid check did.
- func (s *Service) CheckDid(did string) (ip, ft string) {
- params := strings.Split(did, ":")
- if len(params) == 4 {
- log.Warn("report click did:%s", did)
- return ntoIPv6(params[:3]), fmt.Sprintf("%d", decode([]byte(params[3])))
- }
- dst := myEncryptDecrypt(did)
- params = strings.Split(dst, ":")
- if len(params) != 2 {
- return
- }
- ipInt, _ := strconv.ParseInt(params[0], 10, 64)
- ip = netNtoA(uint32(ipInt))
- ft = params[1]
- return
- }
- func myEncryptDecrypt(src string) (dst string) {
- var tmp []rune
- for _, k := range src {
- if _, ok := ecKeys[k]; !ok {
- return ""
- }
- tmp = append(tmp, ecKeys[k])
- }
- dst = string(tmp)
- return
- }
- // Report report to history.
- func (s *Service) Report(c context.Context, proStr, cidStr, tpStr, subType, realtimeStr, aidStr, midstr, sidStr, epidStr, dtStr, tsStr string) (err error) {
- var (
- tp, stp, dt int
- )
- if tp, err = strconv.Atoi(tpStr); err != nil {
- log.Warn("Report type:%s", tpStr)
- }
- stp, _ = strconv.Atoi(subType)
- mid, _ := strconv.ParseInt(midstr, 10, 64)
- aid, _ := strconv.ParseInt(aidStr, 10, 64)
- sid, _ := strconv.ParseInt(sidStr, 10, 64)
- epid, _ := strconv.ParseInt(epidStr, 10, 64)
- cid, _ := strconv.ParseInt(cidStr, 10, 64)
- if aid == 0 && cid == 0 {
- return ecode.RequestErr
- }
- pro, _ := strconv.ParseInt(proStr, 10, 64)
- realtime, _ := strconv.ParseInt(realtimeStr, 10, 64)
- if dt, err = strconv.Atoi(dtStr); err != nil {
- dt = 2
- }
- ip := metadata.String(c, metadata.RemoteIP)
- ts, _ := strconv.ParseInt(tsStr, 10, 64)
- history := &hmdl.History{Aid: aid, Sid: sid, Epid: epid, TP: int8(tp), STP: int8(stp), Cid: cid, DT: int8(dt), Pro: pro, Unix: ts}
- arg := &hmdl.ArgHistory{Mid: mid, Realtime: realtime, RealIP: ip, History: history}
- return s.hisRPC.Add(c, arg)
- }
|