WXGame/sever/test/server2.go
DESKTOP-DDTRVOR\asus 91aedfe56b 修改解析
2025-01-09 15:17:36 +08:00

295 lines
8.7 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 (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
credential "github.com/bytedance/douyin-openapi-credential-go/client"
openApiSdkClient "github.com/bytedance/douyin-openapi-sdk-go/client"
)
type APIResponse struct {
BaseResp struct {
StatusCode int `json:"StatusCode"`
StatusMessage string `json:"StatusMessage"`
} `json:"BaseResp"`
Data struct {
Records []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"`
} `json:"records"`
Total int `json:"total"`
} `json:"data"`
ErrMsg string `json:"err_msg"`
ErrNo int `json:"err_no"`
LogID string `json:"log_id"`
}
// 获取 access_token 的函数
func GetAccessToken() (string, error) {
// 初始化 SDK 客户端,设置 app_id 和 secret
opt := new(credential.Config).
SetClientKey("tt8b32fd8f14071db707"). // 替换为你的 app_id
SetClientSecret("44018e80b1bde34395a52de67ce1e0c37c572d80") // 替换为你的 secret
// 创建 SDK 客户端
sdkClient, err := openApiSdkClient.NewClient(opt)
if err != nil {
return "", fmt.Errorf("SDK 初始化失败: %v", err)
}
// 构造获取 token 的请求参数
sdkRequest := &openApiSdkClient.AppsV2TokenRequest{}
sdkRequest.SetAppid("tt8b32fd8f14071db707") // 设置应用 ID
sdkRequest.SetGrantType("client_credential") // 设置授权类型client_credentials 模式)
sdkRequest.SetSecret("44018e80b1bde34395a52de67ce1e0c37c572d80") // 设置密钥
// 调用 SDK 获取 access_token
sdkResponse, err := sdkClient.AppsV2Token(sdkRequest)
if err != nil {
fmt.Println("sdk call err:", err)
return "", nil
}
fmt.Println("sdk数据", sdkResponse.Data)
// 返回 access_token
return *sdkResponse.Data.AccessToken, nil
}
func DecryptAES128CBC(encryptedData, sessionKey, iv string) ([]byte, error) {
// Base64 解码 key 和 iv
aesKey, err := base64.StdEncoding.DecodeString(sessionKey)
if err != nil {
return nil, fmt.Errorf("sessionKey Base64 解码失败: %v", err)
}
initialVector, err := base64.StdEncoding.DecodeString(iv)
if err != nil {
return nil, fmt.Errorf("iv Base64 解码失败: %v", err)
}
// 检查 key 和 iv 长度是否为 16 字节
if len(aesKey) != 16 {
return nil, fmt.Errorf("AES key 长度必须为 16 字节")
}
if len(initialVector) != 16 {
return nil, fmt.Errorf("IV 长度必须为 16 字节")
}
// Base64 解码密文
ciphertext, err := base64.StdEncoding.DecodeString(encryptedData)
if err != nil {
return nil, fmt.Errorf("encryptedData Base64 解码失败: %v", err)
}
// 创建 AES 块
block, err := aes.NewCipher(aesKey)
if err != nil {
return nil, fmt.Errorf("创建 AES Cipher 失败: %v", err)
}
// 检查密文长度是否为块大小的倍数
if len(ciphertext)%aes.BlockSize != 0 {
return nil, fmt.Errorf("密文长度必须是 AES 块大小的倍数")
}
// 创建 CBC 解密器
mode := cipher.NewCBCDecrypter(block, initialVector)
// 解密数据
decrypted := make([]byte, len(ciphertext))
mode.CryptBlocks(decrypted, ciphertext)
// 去除 PKCS#7 填充
decrypted, err = PKCS7Unpad(decrypted)
if err != nil {
return nil, fmt.Errorf("去除 PKCS#7 填充失败: %v", err)
}
return decrypted, nil
}
// PKCS#7 填充去除函数
func PKCS7Unpad(data []byte) ([]byte, error) {
length := len(data)
if length == 0 {
return nil, fmt.Errorf("解密后数据长度为 0")
}
padding := int(data[length-1])
if padding > length || padding == 0 {
return nil, fmt.Errorf("无效的填充数据")
}
return data[:length-padding], nil
}
func main() {
// 定义 HTTP 路由和处理函数
http.HandleFunc("/get-ecpm", func(w http.ResponseWriter, r *http.Request) {
// 检查 HTTP 请求方法是否为 GET
if r.Method != http.MethodGet {
http.Error(w, "无效的请求方法", http.StatusMethodNotAllowed)
return
}
// 从请求中获取参数
openID := r.URL.Query().Get("open_id") // 获取 open_id
mpID := r.URL.Query().Get("mp_id") // 获取 mp_id
dateHour := r.URL.Query().Get("date_hour") // 获取 date_hour
pageNo := r.URL.Query().Get("pageNo") // 获取 date_hour
pageSize := r.URL.Query().Get("pageSize") // 获取 date_hour
// 检查是否有缺少参数
if mpID == "" || dateHour == "" {
http.Error(w, "缺少必要的参数", http.StatusBadRequest)
return
}
// 动态获取 access_token
accessToken, err := GetAccessToken()
apiURL := "https://minigame.zijieapi.com/mgplatform/api/apps/data/get_ecpm"
if err != nil {
http.Error(w, fmt.Sprintf("获取 access_token 失败: %v", err), http.StatusInternalServerError)
return
}
fmt.Println("动态token为", accessToken)
params := url.Values{}
params.Add("open_id", openID)
params.Add("mp_id", mpID)
params.Add("date_hour", dateHour)
params.Add("access_token", accessToken)
params.Add("page_no", pageNo)
params.Add("page_size", pageSize)
// 构造请求体
// requestBody := map[string]string{
// "open_id": openID,
// "mp_id": mpID,
// "date_hour": dateHour,
// "access_token": accessToken,
// "page_no": pageNo,
// "page_size": pageSize,
// }
fullURL := fmt.Sprintf("%s?%s", apiURL, params.Encode())
// requestBodyJSON, err := json.Marshal(requestBody) // 转为 JSON 格式
// if err != nil {
// http.Error(w, "请求体编码失败", http.StatusInternalServerError)
// return
// }
resp, err := http.Get(fullURL)
if err != nil {
http.Error(w, "调用抖音 API 失败", http.StatusInternalServerError)
return
}
defer resp.Body.Close()
// 读取抖音 API 的响应
responseBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
http.Error(w, "读取抖音 API 响应失败", http.StatusInternalServerError)
return
}
var apiResponse APIResponse
err = json.Unmarshal(responseBody, &apiResponse)
if err != nil {
fmt.Printf("Error while parsing response JSON: %v\n", err)
return
}
if apiResponse.ErrNo != 0 {
fmt.Printf("API Error: %s (ErrNo: %d)\n", apiResponse.ErrMsg, apiResponse.ErrNo)
return
}
totalCost := 0
totalRecords := len(apiResponse.Data.Records)
for _, record := range apiResponse.Data.Records {
totalCost += record.Cost
}
if totalRecords == 0 {
fmt.Println("No records found. Unable to calculate ECPM.")
return
}
ecpm := float64(totalCost) / 100000 * 1000 / float64(totalRecords)
fmt.Println("返回值为", responseBody)
// 根据key返回相应的值这里可以替换为实际的业务逻辑
value := fmt.Sprintf("Value for key '%s'", ecpm)
// 将抖音 API 的响应返回给客户端
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(resp.StatusCode)
w.Write([]byte(value))
})
http.HandleFunc("/Login", func(w http.ResponseWriter, r *http.Request) {
// 检查请求方法是否为GET
if r.Method != http.MethodGet {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return
}
// 从请求参数中获取"code"和"Anonymous"
code := r.URL.Query().Get("code")
Anonymous := r.URL.Query().Get("Anonymous")
fmt.Println("code:", code)
fmt.Println("Anonymous:", Anonymous)
// 参数校验
if code == "" {
http.Error(w, "Missing 'code' or 'Anonymous' parameter", http.StatusBadRequest)
return
}
// 初始化 SDK 客户端
opt := new(credential.Config).
SetClientKey("tt8b32fd8f14071db707").
SetClientSecret("44018e80b1bde34395a52de67ce1e0c37c572d80")
sdkClient, err := openApiSdkClient.NewClient(opt)
if err != nil {
fmt.Println("sdk init err:", err)
http.Error(w, "SDK 初始化失败", http.StatusInternalServerError)
return
}
// 构建请求参数
sdkRequest := &openApiSdkClient.V2Jscode2sessionRequest{}
sdkRequest.SetAnonymousCode(Anonymous)
sdkRequest.SetAppid("tt8b32fd8f14071db707")
sdkRequest.SetCode(code)
sdkRequest.SetSecret("44018e80b1bde34395a52de67ce1e0c37c572d80")
// 调用 SDK
sdkResponse, err := sdkClient.V2Jscode2session(sdkRequest)
if err != nil {
fmt.Println("sdk call err:", err)
http.Error(w, "SDK 调用失败", http.StatusInternalServerError)
return
}
// 打印登录数据
fmt.Println("登录数据:", sdkResponse)
// 返回响应
value := fmt.Sprintf("Session Data: %v", sdkResponse.Data)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(value))
})
// 启动 HTTP 服务器
fmt.Println("服务器已启动http://localhost:8080")
err := http.ListenAndServe(":8080", nil) // 监听 8080 端口
if err != nil {
fmt.Println("服务器启动失败:", err)
}
}