Kaynağa Gözat

代码上传

wucan 4 ay önce
ebeveyn
işleme
c832c8cdb0

+ 2 - 1
config/app.go

@@ -38,7 +38,8 @@ func App() *ConfigNode {
 		"admin_secret": env("ADMIN_SECRET", "123456"),   //默认管理密码
 		"user_total":   env("USER_TOTAL", "user_total"), //所有用户的集合
 
-		"check_user_active": env("CHECK_USER_ACTIVE", "http://127.0.0.1:8001/user/checkUserActive"), //curl 接口
+		"check_user_active": env("CHECK_USER_ACTIVE", "http://127.0.0.1:8001/user/checkUserActive"),   //curl 接口
+		"check_retention":   env("CHECK_USER_RETENTION", "http://127.0.0.1:8001/user/checkRetention"), //curl 接口
 		"local":             env("LOCAL", ""),
 	}
 }

+ 1 - 1
config/database.go

@@ -11,7 +11,7 @@ func Database() *ConfigNode {
 		"charset":             "utf8mb4",
 		"maxIdleConns":        "10",
 		"maxOpenConns":        "50",
-		"logMode":             env("MYSQL_LOG_MODE", "warn"),
+		"logMode":             env("MYSQL_LOG_MODE", "info"),
 		"enableFileLogWriter": env("MYSQL_ENABLE_LOG_WRITE", "true"),
 	}
 }

+ 21 - 0
controller/v1/behavior.go

@@ -109,6 +109,8 @@ import (
 //}
 
 func CheckUserBehavior(c *gin.Context) {
+	//response.Success(c, gin.H{"data": "success"})
+	//return
 	gid := c.GetString("gid")
 	pf := c.GetString("pf")
 	openId := c.GetString("openid")
@@ -394,3 +396,22 @@ func CheckUserActive(gid string, pf string, openId string) {
 	}
 	fmt.Println(res)
 }
+
+func CheckRetention(gid string, pf string, openId string) {
+	request := map[string]interface{}{
+		"gid":      gid,
+		"platform": pf,
+		"openId":   openId,
+	}
+	data, err := service.CurlPost(config.Get("app.check_retention"), request, nil)
+	if err != nil {
+		global.App.Log.Error("CheckUserActive err: ", err)
+		return
+	}
+
+	res := make(map[string]interface{})
+	err = json.Unmarshal([]byte(data), &res)
+	if err != nil {
+		global.App.Log.Error("解析返回json错误: ", err)
+	}
+}

+ 256 - 0
controller/v1/ecpm.go

@@ -0,0 +1,256 @@
+package v1
+
+import (
+	"context"
+	"designs/app/common/request"
+	"designs/app/common/response"
+	"designs/global"
+	"designs/service"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"net/http"
+	"net/url"
+	"strconv"
+	"time"
+)
+
+func TestEcpm(c *gin.Context) {
+	form := request.Check(c, &struct {
+		Gid string `form:"gid" json:"gid" binding:"required"`
+	}{})
+	err := Ecpm("gid:" + form.Gid)
+	if err != nil {
+		response.Fail(c, 1001, err.Error())
+		return
+	}
+
+	////读取所有游戏
+	//gidKey := config.Get("app.gid") + "*"
+	//keys, _ := global.App.Redis.Keys(context.Background(), gidKey).Result()
+	//for _, gid := range keys {
+	//	fmt.Println(gid)
+	//	continue
+	//	err := Ecpm(gid)
+	//	if err != nil {
+	//		global.App.Log.Error("Set "+gid+" Ecpm error:", err)
+	//	} else {
+	//		global.App.Log.Info("Set " + gid + " Ecpm success")
+	//	}
+	//
+	//}
+
+	response.Success(c, gin.H{})
+}
+
+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()
+	fmt.Println(res)
+	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, -1).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
+	}
+	//查询出当日的所有数据
+	var userSeeAds []UserJoinSeeAds
+
+	fmt.Println(gid)
+	gid = gid[4:]
+	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 {
+		//跳过数据对不上的
+		//fmt.Println(k, userSeeAdsMap[k])
+		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;"`
+			}{}
+			fmt.Println(v.Id, "asdasdas")
+			global.App.DB.Table("ecpm_data").Where("ecmpId", v.Id).Select("id").First(&ecpmData)
+			if ecpmData.Id == 0 {
+				fmt.Println(v.Id)
+				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
+}

+ 15 - 1
controller/v1/user.go

@@ -19,6 +19,10 @@ import (
 )
 
 func ReceiveGameMsg(c *gin.Context) {
+
+	//response.Success(c, gin.H{})
+	//return
+
 	form := request.Check(c, &struct {
 		//Gid    string `form:"gid" json:"gid" binding:"required"`
 		//Pf     string `form:"pf" json:"pf" binding:"required"`
@@ -45,11 +49,17 @@ func ReceiveGameMsg(c *gin.Context) {
 	}
 
 	now := time.UnixMilli(form.Timestamp)
-	adStartTime := time.UnixMilli(form.AdStartTime)
+	var adStartTime time.Time
+	if form.AdStartTime > 0 {
+		adStartTime = time.UnixMilli(form.AdStartTime)
+	}
 	var err error
 	if form.Action == "login" {
 		//登录
 		err = login(gid, pf, openId, form.UserId, now)
+
+		//调用接口,上传留存
+		CheckRetention(gid, pf, openId)
 	} else if form.Action == "online" {
 		//活跃
 		err = online(gid, pf, openId, form.UserId, now)
@@ -336,6 +346,10 @@ func InitUser(c *gin.Context) {
 }
 
 func ReceiveAdsInfo(c *gin.Context) {
+
+	//response.Success(c, gin.H{"data": "success"})
+	//return
+
 	form := request.Check(c, &struct {
 		Aid string `form:"aid" json:"aid" binding:""`
 		Pid string `form:"pid" json:"pid" binding:""`

+ 33 - 10
crons/ecpm.go

@@ -2,9 +2,11 @@ package crons
 
 import (
 	"context"
+	"designs/config"
 	"designs/global"
 	"designs/service"
 	"encoding/json"
+	"fmt"
 	"github.com/pkg/errors"
 	"net/http"
 	"net/url"
@@ -13,12 +15,27 @@ import (
 )
 
 func SetEcpm() {
-	gid := "linkup"
-	err := Ecpm(gid)
-	if err != nil {
-		global.App.Log.Error("Ecpm error", err)
+
+	//读取所有游戏
+	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")
+		}
+
 	}
-	global.App.Log.Info("ser 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) {
@@ -75,9 +92,10 @@ type UserJoinSeeAds struct {
 }
 
 func Ecpm(gid string) error {
-
-	res, _ := global.App.Redis.HGetAll(context.Background(), "gid:"+gid).Result()
-
+	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 {
@@ -89,7 +107,14 @@ func Ecpm(gid string) error {
 	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").
@@ -112,14 +137,12 @@ func Ecpm(gid string) error {
 	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
 		}
 
-		gid := userSeeAdsMap[k][0].Gid
 		pf := userSeeAdsMap[k][0].Pf
 		openId := userSeeAdsMap[k][0].OpenId
 		userId := userSeeAdsMap[k][0].UserId

+ 40 - 47
middleware/auth.go

@@ -28,49 +28,42 @@ func LimitRequestBodySize(maxSize int64) gin.HandlerFunc {
 /* token中间件 */
 func TokenAuthMiddleware() gin.HandlerFunc {
 	return func(c *gin.Context) {
-		// c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 1)
-		// fmt.Println("fdagadgadgadgagag")
-		// if err := c.Request.ParseForm(); err != nil {
-		// 	fmt.Println("wwwwwwwwwwwwwwwwww")
-		// 	c.JSON(http.StatusRequestEntityTooLarge, gin.H{"error": "Request body too large"})
-		// 	c.Abort()
-		// 	return
-		// }
-		contentLength := c.Request.ContentLength
-		if contentLength > config.GetInt64("app.max_content") {
-			// 输出请求体的大小
-			// fmt.Printf("Request body size: %d bytes\n", contentLength)
-			common.RetJson(1003, "ruquest too max", "", c)
-			c.Abort()
-			return
-		}
-		token := c.GetHeader("Authorization")
-		//校验token
-		if token == "" {
-			common.RetJson(-2, "Unauthorized", "", c)
-			c.Abort()
-			return
-		}
-		ok, openid, gid, pf := isValidToken(token)
-		if !ok {
-			common.RetJson(-1, "authorized invalid!", "", c)
-			c.Abort()
-			return
-		}
 
-		//校验数据合法性(用户信息是否有效)
-		userKey := gid + ":" + pf + ":" + config.Get("app.user_table_key") + openid
-		userData, err := global.App.Redis.HGetAll(context.Background(), userKey).Result()
-		if err != nil {
-			common.RetJson(-1, "authorized invalid,redis cant find!", "", c)
-			c.Abort()
-			return
-		}
-		if len(userData) == 0 {
-			common.RetJson(-1, "用户信息不在数据库中", "", c)
-			c.Abort()
-			return
-		}
+		//contentLength := c.Request.ContentLength
+		//if contentLength > config.GetInt64("app.max_content") {
+		//	// 输出请求体的大小
+		//	// fmt.Printf("Request body size: %d bytes\n", contentLength)
+		//	common.RetJson(1003, "ruquest too max", "", c)
+		//	c.Abort()
+		//	return
+		//}
+		//token := c.GetHeader("Authorization")
+		////校验token
+		//if token == "" {
+		//	common.RetJson(-2, "Unauthorized", "", c)
+		//	c.Abort()
+		//	return
+		//}
+		//ok, openid, gid, pf := isValidToken(token)
+		//if !ok {
+		//	common.RetJson(-1, "authorized invalid!", "", c)
+		//	c.Abort()
+		//	return
+		//}
+		//
+		////校验数据合法性(用户信息是否有效)
+		//userKey := gid + ":" + pf + ":" + config.Get("app.user_table_key") + openid
+		//userData, err := global.App.Redis.HGetAll(context.Background(), userKey).Result()
+		//if err != nil {
+		//	common.RetJson(-1, "authorized invalid,redis cant find!", "", c)
+		//	c.Abort()
+		//	return
+		//}
+		//if len(userData) == 0 {
+		//	common.RetJson(-1, "用户信息不在数据库中", "", c)
+		//	c.Abort()
+		//	return
+		//}
 
 		////校验请求次数
 		//apiPath := c.FullPath()
@@ -90,11 +83,11 @@ func TokenAuthMiddleware() gin.HandlerFunc {
 		//	return
 		//}
 
-		//设置上下文数据
-		c.Set("openid", openid)
-		c.Set("gid", gid)
-		c.Set("pf", pf)
-		//如果校验通过
+		////设置上下文数据
+		//c.Set("openid", openid)
+		//c.Set("gid", gid)
+		//c.Set("pf", pf)
+		////如果校验通过
 
 	}
 }

+ 3 - 1
route/api.go

@@ -12,6 +12,8 @@ func SetApiGroupRoutes(router *gin.RouterGroup) {
 
 	router.POST("/admin/ss/initUser", v1.InitUser)
 
+	router.POST("/TestEcpm", v1.TestEcpm)
+
 	router.POST("/user/updateUserBehavior", v1.UpdateUserBehavior)
 
 	GroupV1 := router.Group("")
@@ -23,6 +25,6 @@ func SetApiGroupRoutes(router *gin.RouterGroup) {
 
 		//GroupV1.POST("/user/receiveUserBehavior", v1.ReceiveUserBehavior)
 		GroupV1.POST("/user/checkUserBehavior", v1.CheckUserBehavior)
-	}
 
+	}
 }

+ 2 - 1
service/oceanEngine.go

@@ -5,6 +5,7 @@ import (
 	"context"
 	"designs/global"
 	"encoding/json"
+	"fmt"
 	"go.mongodb.org/mongo-driver/v2/bson"
 	"io"
 	"net/http"
@@ -214,7 +215,7 @@ func CurlGet(url string, values url.Values, header http.Header) (string, error)
 	if values != nil {
 		req.URL.RawQuery = values.Encode()
 	}
-	//fmt.Println(req.URL.Host, req.URL.RawQuery)
+	fmt.Println(req.URL.Host, req.URL.RawQuery)
 	resp, resErr := http.DefaultClient.Do(req)
 	if resErr != nil {
 		return "", resErr