package crons import ( "context" "designs/config" "designs/global" "designs/service" "encoding/json" "fmt" "github.com/pkg/errors" "net/http" "net/url" "strconv" "time" ) func SetEcpm() { //读取所有游戏 gidKey := config.Get("app.gid") + "*" keys, _ := global.App.Redis.Keys(context.Background(), gidKey).Result() for _, gid := range keys { err := Ecpm(gid) if err != nil { global.App.Log.Error("Set "+gid+" Ecpm error:", err) } else { global.App.Log.Info("Set " + gid + " Ecpm success") } } ////先只统计linkup的 //err := Ecpm("linkup") //if err != nil { // global.App.Log.Error("Ecpm error", err) //} //global.App.Log.Info("ser Ecpm success") } func GetAccessToken(gid string, ttAppid string, ttSecret string) (string, error) { tokenKey := gid + "||" + "ttToken" AccessToken := global.App.Redis.Get(context.Background(), tokenKey).Val() if AccessToken == "" { reportDat := map[string]string{ "appid": ttAppid, "secret": ttSecret, "grant_type": "client_credential", } //请求接口获取token content, err := service.CurlPost("https://minigame.zijieapi.com/mgplatform/api/apps/v2/token", reportDat, nil) if err != nil { return "", err } var resp struct { Data struct { AccessToken string `json:"access_token"` ExpiresIn int `json:"expires_in"` ExpiresAt int `json:"expiresAt"` } `json:"data"` ErrTips string `json:"err_tips"` ErrNo int `json:"err_no"` } str2oErr := json.Unmarshal([]byte(content), &resp) if str2oErr != nil { return "", err } if resp.ErrNo != 0 { return "", errors.New(resp.ErrTips) } AccessToken = resp.Data.AccessToken global.App.Redis.Set(context.Background(), tokenKey, AccessToken, time.Second*30) } return AccessToken, nil } type UserJoinSeeAds struct { ID int `json:"id" gorm:"not null;"` Pf string `json:"pf" gorm:"not null;"` Gid string `json:"gid" gorm:"not null;"` UserId int `json:"userId" gorm:"not null;column:userId;"` OpenId string `json:"openId" gorm:"not null;column:openId;"` Date string `json:"date" gorm:"not null;"` CreatedAt time.Time `json:"createdAt" gorm:"column:createdAt;"` StartTime time.Time `json:"startTime" gorm:"column:startTime;"` AdsId string `json:"adsId" gorm:"not null;column:adsId;"` AdsType string `json:"adsType" gorm:"not null;column:adsType;"` AdsScene string `json:"adsScene" gorm:"not null;column:adsScene;"` AdsState int `json:"adsState" gorm:"not null;column:adsState;"` } func Ecpm(gid string) error { res, _ := global.App.Redis.HGetAll(context.Background(), gid).Result() if len(res["ttAppid"]) == 0 || len(res["ttSecret"]) == 0 { return errors.New("ttAppid/ttSecret is empty") } //获取和存储accessToken accessToken, err := GetAccessToken(gid, res["ttAppid"], res["ttSecret"]) if err != nil { return err } //请求获取结果 dateHour := time.Now().AddDate(0, 0, 0).Format("2006-01-02") ecpmRes, err := GetEcpm(res["ttAppid"], accessToken, dateHour) if err != nil { return err } //ecpm没数据的话,就不需要往后走 if ecpmRes.Data.Total == 0 { global.App.Log.Info(fmt.Sprintf("%s 没有需要写入的ecpm数据", gid)) return nil } //查询出当日的所有数据 gid = gid[4:] var userSeeAds []UserJoinSeeAds err = global.App.DB.Table("user_see_ads"). LeftJoin("user", "user.userId = user_see_ads.userId and user.gid = user_see_ads.gid"). Where("user_see_ads.createdAt", ">=", dateHour). Select("user_see_ads.*", "user.openId"). Where("user_see_ads.gid", gid). Where("user_see_ads.pf", "tt"). Order("user_see_ads.createdAt asc"). Scan(&userSeeAds).Error if err != nil { return err } //按照openId 分组 userSeeAdsMap := make(map[string][]UserJoinSeeAds) for _, userSeeAd := range userSeeAds { userSeeAdsMap[userSeeAd.OpenId] = append(userSeeAdsMap[userSeeAd.OpenId], userSeeAd) } ecpmMap := make(map[string][]EcpmItem) for _, record := range ecpmRes.Data.Records { ecpmMap[record.OpenId] = append(ecpmMap[record.OpenId], record) } for k, item := range ecpmMap { //跳过数据对不上的 if len(userSeeAdsMap[k]) == 0 { continue } pf := userSeeAdsMap[k][0].Pf openId := userSeeAdsMap[k][0].OpenId userId := userSeeAdsMap[k][0].UserId for key, v := range item { ecpmData := struct { Id int `json:"id" gorm:"not null;"` }{} global.App.DB.Table("ecpm_data").Where("ecmpId", v.Id).Select("id").First(&ecpmData) if ecpmData.Id == 0 { err = global.App.DB.Table("ecpm_data").Create(map[string]interface{}{ "gid": gid, "pf": pf, "openId": openId, "cost": v.Cost, "userId": userId, "ecmpId": v.Id, "createdAt": v.EventTime, }).Error if err != nil { return err } } //关联到看广告表中 if key < len(userSeeAdsMap[k]) { err = global.App.DB.Table("user_see_ads").Where("id", userSeeAdsMap[k][key].ID).Update("cost", v.Cost).Error if err != nil { global.App.Log.Error("id:"+strconv.Itoa(userSeeAdsMap[k][key].ID)+"user_see_ads update cost err:", err.Error()) return err } } } } return nil } type EcpmItem struct { Aid string `json:"aid"` Cost int `json:"cost"` Did string `json:"did"` EventName string `json:"event_name"` EventTime string `json:"event_time"` OpenId string `json:"open_id"` Id int `json:"id"` } type Result struct { ErrMsg string `json:"err_msg"` ErrNo int `json:"err_no"` LogId string `json:"log_id"` Data struct { Total int `json:"total"` Records []EcpmItem `json:"records"` } `json:"data"` } // GetEcpm 获取用户的ecpm值,用于巨量引擎下小游戏的关键行为转化指标 func GetEcpm(appId string, accessToken string, dateHour string) (*Result, error) { pageNo := 0 pageSize := 100 var resData Result header := http.Header{ "Content-type": []string{"application/json"}, } for { pageNo++ params := url.Values{ "access_token": {accessToken}, "mp_id": {appId}, "date_hour": {dateHour}, "page_no": {strconv.Itoa(pageNo)}, "page_size": {strconv.Itoa(pageSize)}, } res, err := service.CurlGet("https://minigame.zijieapi.com/mgplatform/api/apps/data/get_ecpm", params, header) if err != nil { return nil, err } var resp Result err = json.Unmarshal([]byte(res), &resp) if err != nil { return nil, err } resData.Data.Records = append(resData.Data.Records, resp.Data.Records...) resData.Data.Total = resp.Data.Total //当获取到所有数据的时候,停止获取数据 if pageNo*pageSize >= resp.Data.Total { break } } return &resData, nil }