update
This commit is contained in:
parent
9ab243733d
commit
75d43bc3b7
@ -12,9 +12,6 @@ import (
|
||||
// 正式地址
|
||||
const accessTokenURL = "https://developer.toutiao.com/api/apps/v2/token"
|
||||
|
||||
// 沙盒地址
|
||||
const sandBoxTokenURL = "https://open-sandbox.douyin.com/api/apps/v2/token"
|
||||
|
||||
// AccessToken 管理AccessToken 的基础接口
|
||||
type AccessToken interface {
|
||||
GetCacheKey() string // 获取缓存的key
|
||||
@ -37,7 +34,7 @@ type DefaultAccessToken struct {
|
||||
}
|
||||
|
||||
// NewDefaultAccessToken 实例化默认的token管理类
|
||||
func NewDefaultAccessToken(appId, appSecret string, cache cache.Cache, IsSandbox bool) AccessToken {
|
||||
func NewDefaultAccessToken(appId, appSecret string, cache cache.Cache, IsSandbox bool) *DefaultAccessToken {
|
||||
if cache == nil {
|
||||
panic(any("cache is need"))
|
||||
}
|
||||
@ -80,11 +77,7 @@ func (dd *DefaultAccessToken) GetAccessToken() (string, error) {
|
||||
}
|
||||
|
||||
// 开始调用接口获取token
|
||||
api := accessTokenURL
|
||||
if dd.SandBox {
|
||||
api = sandBoxTokenURL
|
||||
}
|
||||
reqAccessToken, err := GetTokenFromServer(api, dd.AppId, dd.AppSecret)
|
||||
reqAccessToken, err := GetTokenFromServer(accessTokenURL, dd.AppId, dd.AppSecret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -2,14 +2,19 @@ package douyin_openapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
accessToken "gitea.youtukeji.com.cn/xiabin/douyin-openapi/access-token"
|
||||
"gitea.youtukeji.com.cn/xiabin/douyin-openapi/cache"
|
||||
"gitea.youtukeji.com.cn/xiabin/douyin-openapi/util"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
code2Session = "/api/apps/v2/jscode2session" // 小程序登录地址
|
||||
getEcpm = "https://minigame.zijieapi.com/mgplatform/api/apps/data/get_ecpm" // 获取ECPM
|
||||
)
|
||||
|
||||
// DouYinOpenApiConfig 实例化配置
|
||||
@ -104,3 +109,88 @@ func (d *DouYinOpenApi) Code2Session(code, anonymousCode string) (code2SessionRe
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Record 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"`
|
||||
}
|
||||
|
||||
// GetEcpmParams 获取ECPM参数
|
||||
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"`
|
||||
}
|
||||
|
||||
// GetEcpmResponseData 获取ECPM响应数据
|
||||
type GetEcpmResponseData struct {
|
||||
BaseResp struct {
|
||||
StatusCode int `json:"StatusCode"`
|
||||
StatusMessage string `json:"StatusMessage"`
|
||||
} `json:"BaseResp"`
|
||||
Data struct {
|
||||
Records []Record `json:"records"`
|
||||
Total int `json:"total"`
|
||||
} `json:"data"`
|
||||
ErrMsg string `json:"err_msg"`
|
||||
ErrNo int `json:"err_no"`
|
||||
LogID string `json:"log_id"`
|
||||
}
|
||||
|
||||
// GetEcpm 获取ECPM
|
||||
// https://bytedance.larkoffice.com/docx/Vg4yd0RDSovZINxJDyIc6THhnod
|
||||
// 根据分页大小循环获取,聚合总数返回
|
||||
func (d *DouYinOpenApi) GetEcpm(params GetEcpmParams) (list []Record, err error) {
|
||||
fullURL := fmt.Sprintf("%s?open_id=%s&mp_id=%s&access_token=%s&date_hour=%s&page_size=500&page_no=", getEcpm, params.OpenId, params.AppId, params.AccessToken, params.DateHour)
|
||||
for {
|
||||
fullURL += strconv.Itoa(params.PageNo)
|
||||
var responseBody []byte
|
||||
func() {
|
||||
// 调用抖音 API
|
||||
var resp *http.Response
|
||||
resp, err = http.Get(fullURL)
|
||||
if err != nil {
|
||||
err = errors.New("调用抖音 API 失败")
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// 读取抖音 API 响应数据
|
||||
responseBody, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
err = errors.New("读取抖音 API 响应失败")
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
// 解析抖音 API 响应数据
|
||||
var apiResponse GetEcpmResponseData
|
||||
err = json.Unmarshal(responseBody, &apiResponse)
|
||||
if err != nil {
|
||||
err = errors.New("解析 API 响应数据失败")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查 API 是否返回错误
|
||||
if apiResponse.ErrNo != 0 {
|
||||
err = fmt.Errorf("抖音 API 返回错误: %s (错误码: %d)", apiResponse.ErrMsg, apiResponse.ErrNo)
|
||||
return
|
||||
}
|
||||
|
||||
list = append(list, apiResponse.Data.Records...)
|
||||
|
||||
// 当页数据小于总页数时,无更多数据,返回
|
||||
if len(apiResponse.Data.Records) <= params.PageSize {
|
||||
return
|
||||
}
|
||||
|
||||
params.PageNo++
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,13 @@ import (
|
||||
accessToken "gitea.youtukeji.com.cn/xiabin/douyin-openapi/access-token"
|
||||
"gitea.youtukeji.com.cn/xiabin/douyin-openapi/cache"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 声明测试常量
|
||||
const (
|
||||
AppId = ""
|
||||
AppSecret = ""
|
||||
AppId = "tt8b32fd8f14071db707"
|
||||
AppSecret = "44018e80b1bde34395a52de67ce1e0c37c572d80"
|
||||
Token = ""
|
||||
Salt = ""
|
||||
)
|
||||
@ -60,3 +61,30 @@ func TestDouYinOpenApi_Code2Session(t *testing.T) {
|
||||
}
|
||||
t.Logf("got a value %+v", session)
|
||||
}
|
||||
|
||||
func TestDouYinOpenApi_GetEcpm(t *testing.T) {
|
||||
|
||||
// 获取动态的 access_token
|
||||
token := accessToken.NewDefaultAccessToken(AppId, AppSecret, Cache, true)
|
||||
|
||||
at, err := token.GetAccessToken()
|
||||
if err != nil {
|
||||
t.Errorf("got a error: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
list, err := OpenApi.GetEcpm(GetEcpmParams{
|
||||
AppId: AppId,
|
||||
OpenId: "_000aG3MQTzVW-yCUH-ndwv90JIyvdTSD0gf",
|
||||
AccessToken: at,
|
||||
DateHour: time.Now().Format(time.DateOnly),
|
||||
PageSize: 500,
|
||||
PageNo: 1,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("got a error %s", err.Error())
|
||||
return
|
||||
}
|
||||
t.Logf("got a value %+v", list)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user