openapi-helper/douyin.go
2025-01-21 16:19:02 +08:00

148 lines
3.9 KiB
Go

package douyin_openapi
import (
"errors"
douyinopenapi "gitea.youtukeji.com.cn/youtu/openapi-helper/douyin"
"gitea.youtukeji.com.cn/youtu/openapi-helper/douyin/access-token"
"github.com/silenceper/wechat/v2/cache"
"sync"
)
type DouYinOpenApiClient struct {
m *sync.Map
}
type DouYinApi struct {
Api *douyinopenapi.DouYinOpenApi // 抖音openapi客户端
ecpmValue uint32 // ECPM值
viewCount uint32 //浏览数
}
type GetEcpmParams struct {
AppId string `json:"app_id" form:"app_id"`
OpenId string `json:"open_id" form:"open_id"`
AccessToken string `json:"access_token" form:"access_token"`
DateHour string `json:"date_hour" form:"date_hour"`
PageSize int `json:"page_size" form:"page_size"`
PageNo int `json:"page_no" form:"page_no"`
}
func NewDouYinOpenApiClient() *DouYinOpenApiClient {
//DouYinOpenApi = douyinopenapi.NewDouYinOpenApi(douyinopenapi.DouYinOpenApiConfig{
// AppId: "1259819191",
// AppSecret: "0b7d7c0d0c8c0a0b0a0c0d0e0f0f0e0d0c0b0a090807060504030201000",
// IsSandbox: true,
// AccessToken: nil,
// Cache: nil,
//})
return &DouYinOpenApiClient{
m: &sync.Map{},
}
}
// GetDouYinOpenApi 获取抖音client
// appId: 小程序id
func (d *DouYinOpenApiClient) GetDouYinOpenApi(appId string) (api *DouYinApi, err error) {
if v, ok := d.m.Load(appId); !ok {
err = errors.New("未找到抖音client")
return
} else {
api = v.(*DouYinApi)
return
}
}
// SetDouYinOpenApi 存储抖音client
// appId: 小程序id
func (d *DouYinOpenApiClient) SetDouYinOpenApi(appId string, api *DouYinApi) {
d.m.Store(appId, api)
}
// NewAndStoreDouYinOpenApi 创建抖音client并存储
// appId: 小程序id
// appSecret: 小程序secret
// cache: 缓存
func (d *DouYinOpenApiClient) NewAndStoreDouYinOpenApi(appId, appSecret string, ecpmValue uint32, viewCount uint32, cache cache.Cache) {
token := access_token.NewDefaultAccessToken(appId, appSecret, cache, false)
api := douyinopenapi.NewDouYinOpenApi(douyinopenapi.DouYinOpenApiConfig{
AppId: appId,
AppSecret: appSecret,
AccessToken: token,
Cache: cache,
IsSandbox: false,
})
d.SetDouYinOpenApi(appId, &DouYinApi{
Api: api,
ecpmValue: ecpmValue,
viewCount: viewCount,
})
}
// GetEcpmValue 获取ECPM值
// appId: 小程序id,map的key
func (d *DouYinOpenApiClient) GetEcpmValue(appId string) uint32 {
douyin, err := d.GetDouYinOpenApi(appId)
if err != nil || douyin == nil {
return 0
}
return douyin.ecpmValue
}
// GetEcpmViewCount 获取ECPM浏览数
// appId: 小程序id,map的key
func (d *DouYinOpenApiClient) GetEcpmViewCount(appId string) uint32 {
douyin, err := d.GetDouYinOpenApi(appId)
if err != nil || douyin == nil {
return 0
}
return douyin.viewCount
}
// GetEcpmData 获取ECPM数据
// appId: 小程序id
// openId: 抖音openId
// dateHour: 日期
func (d *DouYinOpenApiClient) GetEcpmData(appId, openId, dateHour string) (list []douyinopenapi.Record, err error) {
douyin, err := d.GetDouYinOpenApi(appId)
if err != nil {
return
}
//获取accessToken
accessToken, err := douyin.Api.GetAccessToken()
if err != nil {
return
}
list, err = douyin.Api.GetEcpm(douyin.GetEcpmParams{
AppId: appId,
OpenId: openId,
AccessToken: accessToken,
DateHour: dateHour,
PageSize: 500,
PageNo: 1,
})
return
}
// GetEcpm 计算ECPM
// https://bytedance.larkoffice.com/docx/Vg4yd0RDSovZINxJDyIc6THhnod
func (d *DouYinOpenApiClient) GetEcpm(res []douyinopenapi.Record) (ecpm float64, err error) {
// 计算 ECPM
totalCost := 0
totalRecords := len(res)
for _, record := range res {
totalCost += record.Cost
}
// 如果没有记录,则返回错误
if totalRecords == 0 {
err = errors.New("未找到记录,无法计算 ECPM")
return
}
// 总 cost / 100000 * 1000 / 总记录数
ecpm = float64(totalCost) / 100000 * 1000 / float64(totalRecords)
return
}