2026-02-03 04:40:23 -08:00

255 lines
6.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"
)
const (
// OpenInstall 数据接口基础 URL
apiBaseURL = "https://data.openinstall.com"
// 您的 ApiKey (数据接口密钥)
apiKey = "a7596bc007f31a98ca551e33a75d3bb5997b0b94027c6e988d3c0af1"
)
// 通用响应结构
type APIResponse struct {
Code int `json:"code"`
Error *string `json:"error"`
Body json.RawMessage `json:"body"`
}
// 新增安装数据
type GrowthData struct {
Date string `json:"date"`
Visit int64 `json:"visit"` // 点击量
Click int64 `json:"click"` // 访问量
Install int64 `json:"install"` // 安装量
Register int64 `json:"register"` // 注册量
SurviveD1 int64 `json:"survive_d1"` // 1日留存
SurviveD7 int64 `json:"survive_d7"` // 7日留存
SurviveD30 int64 `json:"survive_d30"` // 30日留存
}
// 渠道列表数据
type ChannelData struct {
ChannelCode string `json:"channelCode"`
ChannelName string `json:"channelName"`
LinkURL string `json:"linkUrl"`
CreateTime string `json:"createTime"`
GroupName string `json:"groupName"`
}
func main() {
fmt.Println("========================================")
fmt.Println("OpenInstall API 测试程序")
fmt.Println("========================================")
fmt.Printf("ApiKey: %s\n", apiKey)
fmt.Printf("API Base URL: %s\n", apiBaseURL)
fmt.Println()
ctx := context.Background()
// 测试1: 获取新增安装数据最近7天
fmt.Println("测试1: 获取新增安装数据最近7天")
fmt.Println("========================================")
testGrowthData(ctx, 7)
fmt.Println()
// 测试2: 获取新增安装数据最近30天
fmt.Println("测试2: 获取新增安装数据最近30天")
fmt.Println("========================================")
testGrowthData(ctx, 30)
fmt.Println()
// 测试3: 获取渠道列表
fmt.Println("测试3: 获取渠道列表")
fmt.Println("========================================")
testChannelList(ctx)
fmt.Println()
fmt.Println("========================================")
fmt.Println("测试完成!")
fmt.Println("========================================")
}
// 测试获取新增安装数据
func testGrowthData(ctx context.Context, days int) {
// 设置查询时间范围
endDate := time.Now()
startDate := endDate.AddDate(0, 0, -days)
// 构建 API URL
apiURL := fmt.Sprintf("%s/data/event/growth", apiBaseURL)
params := url.Values{}
params.Add("apiKey", apiKey)
params.Add("startDate", startDate.Format("2006-01-02"))
params.Add("endDate", endDate.Format("2006-01-02"))
params.Add("statType", "daily") // daily = 按天统计, hourly = 按小时统计, total = 合计
fullURL := fmt.Sprintf("%s?%s", apiURL, params.Encode())
fmt.Printf("请求 URL: %s\n", fullURL)
body, statusCode, err := makeRequest(ctx, fullURL)
if err != nil {
fmt.Printf("❌ 请求失败: %v\n", err)
return
}
fmt.Printf("HTTP 状态码: %d\n", statusCode)
if statusCode == 200 {
// 解析响应
var apiResp APIResponse
if err := json.Unmarshal(body, &apiResp); err != nil {
fmt.Printf("❌ JSON 解析失败: %v\n", err)
printRawResponse(body)
return
}
if apiResp.Code == 0 {
fmt.Println("✅ 成功获取数据!")
// 解析业务数据
var growthData []GrowthData
if err := json.Unmarshal(apiResp.Body, &growthData); err != nil {
fmt.Printf("⚠️ 业务数据解析失败: %v\n", err)
printRawResponse(body)
return
}
// 格式化输出数据
fmt.Printf("\n共获取 %d 天的数据:\n", len(growthData))
fmt.Println("----------------------------------------")
for _, data := range growthData {
fmt.Printf("日期: %s\n", data.Date)
fmt.Printf(" 访问量(visit): %d\n", data.Visit)
fmt.Printf(" 点击量(click): %d\n", data.Click)
fmt.Printf(" 安装量(install): %d\n", data.Install)
fmt.Printf(" 注册量(register): %d\n", data.Register)
fmt.Printf(" 1日留存: %d\n", data.SurviveD1)
fmt.Printf(" 7日留存: %d\n", data.SurviveD7)
fmt.Printf(" 30日留存: %d\n", data.SurviveD30)
fmt.Println("----------------------------------------")
}
} else {
errMsg := "未知错误"
if apiResp.Error != nil {
errMsg = *apiResp.Error
}
fmt.Printf("❌ API 返回错误 (code=%d): %s\n", apiResp.Code, errMsg)
printRawResponse(body)
}
} else {
fmt.Printf("❌ HTTP 请求失败\n")
printRawResponse(body)
}
}
// 测试获取渠道列表
func testChannelList(ctx context.Context) {
// 构建 API URL
apiURL := fmt.Sprintf("%s/data/channel/list", apiBaseURL)
params := url.Values{}
params.Add("apiKey", apiKey)
params.Add("pageNum", "0")
params.Add("pageSize", "20")
fullURL := fmt.Sprintf("%s?%s", apiURL, params.Encode())
fmt.Printf("请求 URL: %s\n", fullURL)
body, statusCode, err := makeRequest(ctx, fullURL)
if err != nil {
fmt.Printf("❌ 请求失败: %v\n", err)
return
}
fmt.Printf("HTTP 状态码: %d\n", statusCode)
if statusCode == 200 {
// 解析响应
var apiResp APIResponse
if err := json.Unmarshal(body, &apiResp); err != nil {
fmt.Printf("❌ JSON 解析失败: %v\n", err)
printRawResponse(body)
return
}
if apiResp.Code == 0 {
fmt.Println("✅ 成功获取渠道列表!")
// 直接打印原始数据
printJSONResponse(apiResp.Body)
} else {
errMsg := "未知错误"
if apiResp.Error != nil {
errMsg = *apiResp.Error
}
fmt.Printf("❌ API 返回错误 (code=%d): %s\n", apiResp.Code, errMsg)
printRawResponse(body)
}
} else {
fmt.Printf("❌ HTTP 请求失败\n")
printRawResponse(body)
}
}
// 发送 HTTP 请求
func makeRequest(ctx context.Context, url string) ([]byte, int, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, 0, fmt.Errorf("创建请求失败: %w", err)
}
client := &http.Client{
Timeout: 10 * time.Second,
}
resp, err := client.Do(req)
if err != nil {
return nil, 0, fmt.Errorf("发送请求失败: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, resp.StatusCode, fmt.Errorf("读取响应失败: %w", err)
}
return body, resp.StatusCode, nil
}
// 打印原始响应
func printRawResponse(body []byte) {
fmt.Println("\n原始响应内容:")
var prettyJSON map[string]interface{}
if err := json.Unmarshal(body, &prettyJSON); err == nil {
formatted, _ := json.MarshalIndent(prettyJSON, "", " ")
fmt.Println(string(formatted))
} else {
fmt.Println(string(body))
}
}
// 打印 JSON 响应
func printJSONResponse(data json.RawMessage) {
var prettyJSON interface{}
if err := json.Unmarshal(data, &prettyJSON); err == nil {
formatted, _ := json.MarshalIndent(prettyJSON, "", " ")
fmt.Println(string(formatted))
} else {
fmt.Println(string(data))
}
}