WXGame/sever/test/server2.go
DESKTOP-DDTRVOR\asus 9c94786d7c 保存服务器代码
2025-01-08 15:52:20 +08:00

188 lines
5.6 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 (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
credential "github.com/bytedance/douyin-openapi-credential-go/client"
openApiSdkClient "github.com/bytedance/douyin-openapi-sdk-go/client"
)
// 获取 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
iv := r.URL.Query().Get("iv") // 获取初始向量
dateHour := r.URL.Query().Get("date_hour") // 获取 date_hour
// 检查是否有缺少参数
if openID == "" || mpID == "" || dateHour == "" {
http.Error(w, "缺少必要的参数", http.StatusBadRequest)
return
}
// 解密 encryptedData
decryptedOpenID, err := DecryptAES128CBC(openID, sessionKey, iv)
if err != nil {
http.Error(w, fmt.Sprintf("解密失败: %v", err), http.StatusInternalServerError)
return
}
// 动态获取 access_token
accessToken, err := GetAccessToken()
if err != nil {
http.Error(w, fmt.Sprintf("获取 access_token 失败: %v", err), http.StatusInternalServerError)
return
}
fmt.Println("动态token为", accessToken)
// 构造请求体
requestBody := map[string]string{
"open_id": openID,
"mp_id": mpID,
"date_hour": dateHour,
"access_token": accessToken,
}
requestBodyJSON, err := json.Marshal(requestBody) // 转为 JSON 格式
if err != nil {
http.Error(w, "请求体编码失败", http.StatusInternalServerError)
return
}
// 向抖音 API 发起请求
apiURL := "https://minigame.zijieapi.com/mgplatform/api/apps/data/get_ecpm" // 抖音 API 地址
resp, err := http.Post(apiURL, "application/json", bytes.NewBuffer(requestBodyJSON))
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
}
// 将抖音 API 的响应返回给客户端
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(resp.StatusCode)
w.Write(responseBody)
})
// 启动 HTTP 服务器
fmt.Println("服务器已启动http://localhost:8080")
err := http.ListenAndServe(":8080", nil) // 监听 8080 端口
if err != nil {
fmt.Println("服务器启动失败:", err)
}
}