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 }