offer.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. package offer
  2. import (
  3. "context"
  4. iaes "crypto/aes"
  5. icipher "crypto/cipher"
  6. "crypto/md5"
  7. "encoding/hex"
  8. "time"
  9. "go-common/app/interface/main/app-wall/conf"
  10. callbackdao "go-common/app/interface/main/app-wall/dao/callback"
  11. offerdao "go-common/app/interface/main/app-wall/dao/offer"
  12. "go-common/app/interface/main/app-wall/dao/padding"
  13. "go-common/app/interface/main/app-wall/model"
  14. "go-common/library/log"
  15. "github.com/pkg/errors"
  16. )
  17. type Service struct {
  18. c *conf.Config
  19. dao *offerdao.Dao
  20. cbdao *callbackdao.Dao
  21. }
  22. func New(c *conf.Config) (s *Service) {
  23. s = &Service{
  24. c: c,
  25. dao: offerdao.New(c),
  26. cbdao: callbackdao.New(c),
  27. }
  28. return
  29. }
  30. // Click
  31. func (s *Service) Click(c context.Context, ip uint32, cid, mac, idfa, cb string, now time.Time) (err error) {
  32. res, err := s.dao.InClick(c, ip, cid, mac, idfa, cb, now)
  33. if err != nil || res == 0 {
  34. log.Error("s.dao.InClick(%d, %s, %s, %s, %s) error(%v) or row==0", ip, cid, mac, idfa, cb, now, err)
  35. }
  36. return
  37. }
  38. // ANClick
  39. func (s *Service) ANClick(c context.Context, channel, imei, androidid, mac, cb string, ip uint32, now time.Time) (err error) {
  40. res, err := s.dao.InANClick(c, channel, imei, androidid, mac, cb, ip, now)
  41. if err != nil {
  42. return
  43. }
  44. if res == 0 {
  45. log.Error("s.dao.InANClick(%s, %s, %s, %s, %s, %d, %s) row==0", channel, imei, androidid, mac, cb, ip, now, err)
  46. }
  47. return
  48. }
  49. func (s *Service) ANActive(c context.Context, imei, androidid, mac string, now time.Time) (err error) {
  50. const (
  51. _typeUnactive = 0
  52. _typeActive = 1
  53. )
  54. //gdt
  55. gdtImei := model.GdtIMEI(imei)
  56. count, err := s.dao.ANActive(c, androidid, imei, gdtImei)
  57. if err != nil {
  58. return
  59. }
  60. if count > 0 {
  61. log.Warn("ANActive androidid(%s) imei(%s) gdtImei(%s) already count(%d) activated", androidid, imei, gdtImei, count)
  62. return
  63. }
  64. id, channel, cb, typ, err := s.dao.ANCallback(c, androidid, imei, gdtImei)
  65. if err != nil {
  66. return
  67. }
  68. if id == 0 {
  69. log.Warn("ANActive androidid(%s) imei(%s) gdtImei(%s) not exist", androidid, imei, gdtImei)
  70. return
  71. }
  72. if typ != _typeUnactive {
  73. log.Warn("ANActive androidid(%s) imei(%s) gdtImei(%s) already activated", androidid, imei, gdtImei)
  74. return
  75. }
  76. if err = s.newCallback(c, model.TypeAndriod, channel, imei, gdtImei, cb, now); err != nil {
  77. err = errors.Wrapf(err, "%d", id)
  78. return
  79. }
  80. if _, err = s.dao.ANClickAct(c, id, _typeActive); err != nil {
  81. return
  82. }
  83. return
  84. }
  85. func (s *Service) newCallback(c context.Context, appType, channel string, imei, gdtImei, cb string, now time.Time) (err error) {
  86. const (
  87. _eventActive = "0"
  88. )
  89. switch channel {
  90. case model.ChannelToutiao:
  91. err = s.cbdao.ToutiaoCallback(c, cb, _eventActive)
  92. // gdt
  93. case model.ChannelShike:
  94. err = s.cbdao.ShikeCallback(c, imei, cb, now)
  95. case model.ChannelDontin:
  96. err = s.cbdao.DontinCallback(c, imei, cb)
  97. default:
  98. if _, ok := model.ChannelGdt[channel]; ok {
  99. if appID, ok := model.AppIDGdt[appType]; ok {
  100. err = s.cbdao.GdtCallback(c, appID, appType, channel, gdtImei, cb, now)
  101. }
  102. } else {
  103. log.Warn("channel(%s) undefined", channel)
  104. }
  105. }
  106. return
  107. }
  108. func (s *Service) Active(c context.Context, ip uint32, mid, rmac, mac, idfa, device string, now time.Time) (err error) {
  109. var (
  110. count int
  111. )
  112. res, err := s.dao.InActive(c, ip, mid, rmac, mac, idfa, device, now)
  113. if err != nil {
  114. log.Error("s.dao.InActive(%d, %s, %s, %s, %s, %s) error(%v) or row==0", ip, mid, rmac, mac, idfa, device, err)
  115. return
  116. }
  117. if res == 0 {
  118. log.Warn("wall active(%s) exist", idfa)
  119. return
  120. }
  121. if rmac != "" {
  122. count, err = s.dao.RMacCount(c, rmac)
  123. if err != nil {
  124. log.Error("s.dao.RMacCount(%s) error(%d)", rmac, err)
  125. return
  126. }
  127. if count > 10 {
  128. log.Warn("wallService.RMacCount(%s) count(%d) more than 10", rmac, count)
  129. return
  130. }
  131. }
  132. return s.callback(c, model.TypeIOS, idfa, now)
  133. }
  134. func (s *Service) Exists(c context.Context, idfa string) (exist bool, err error) {
  135. exist, err = s.dao.Exists(c, idfa)
  136. if err != nil {
  137. log.Error("s.dao.Exists(%s) error(%v)", idfa, err)
  138. }
  139. return
  140. }
  141. // callback
  142. func (s *Service) callback(c context.Context, appType, idfa string, now time.Time) (err error) {
  143. if len(idfa) <= 20 {
  144. return
  145. }
  146. // only gdt
  147. allIdfa := idfa[0:8] + "-" + idfa[8:12] + "-" + idfa[12:16] + "-" + idfa[16:20] + "-" + idfa[20:]
  148. bs := md5.Sum([]byte(allIdfa))
  149. gdtIdfa := hex.EncodeToString(bs[:])
  150. // get callback
  151. channel, cb, err := s.dao.Callback(c, idfa, gdtIdfa, now)
  152. if err != nil {
  153. log.Error("s.dao.Callback(%s) error(%v)", idfa, err)
  154. return
  155. }
  156. if cb == "" {
  157. log.Info("callback idfa(%s) callback url is not exists", idfa)
  158. return
  159. }
  160. switch channel {
  161. case model.ChannelShike:
  162. s.cbdao.ShikeCallback(c, idfa, cb, now)
  163. s.dao.UpIdfaActive(c, allIdfa, idfa, now)
  164. case model.ChannelDontin:
  165. s.cbdao.DontinCallback(c, idfa, cb)
  166. s.dao.UpIdfaActive(c, allIdfa, idfa, now)
  167. default:
  168. if _, ok := model.ChannelGdt[channel]; ok {
  169. if appID, ok := model.AppIDGdt[appType]; ok {
  170. if err = s.cbdao.GdtCallback(c, appID, appType, channel, gdtIdfa, cb, now); err != nil {
  171. s.dao.UpIdfaActive(c, allIdfa, gdtIdfa, now)
  172. }
  173. }
  174. } else {
  175. log.Warn("channel(%s) undefined", channel)
  176. }
  177. }
  178. return
  179. }
  180. // CBCDecrypt aes cbc decrypt.
  181. func (s *Service) CBCDecrypt(src, key, iv []byte, p padding.Padding) ([]byte, error) {
  182. var (
  183. ErrAesSrcSize = errors.New("ciphertext too short")
  184. ErrAesIVSize = errors.New("iv size is not a block size")
  185. )
  186. // check src
  187. if len(src) < iaes.BlockSize || len(src)%iaes.BlockSize != 0 {
  188. log.Info("check src src(%v) blockSize (%v)", src, iaes.BlockSize)
  189. log.Info("len(src) < iaes.BlockSize (%v)", len(src) < iaes.BlockSize)
  190. log.Info("len(src)%iaes.BlockSize != 0 (%v)", len(src)%iaes.BlockSize != 0)
  191. return nil, ErrAesSrcSize
  192. }
  193. // check iv
  194. if len(iv) != iaes.BlockSize {
  195. log.Info("check iv iv(%v) blockSize (%v)", iv, iaes.BlockSize)
  196. return nil, ErrAesIVSize
  197. }
  198. block, err := iaes.NewCipher(key)
  199. if err != nil {
  200. log.Error("iaes.NewCipher err(%v)", err)
  201. return nil, err
  202. }
  203. mode := icipher.NewCBCDecrypter(block, iv)
  204. decryptText := make([]byte, len(src))
  205. mode.CryptBlocks(decryptText, src)
  206. if p == nil {
  207. return decryptText, nil
  208. } else {
  209. return p.Unpadding(decryptText, iaes.BlockSize)
  210. }
  211. }