package main import ( "encoding/json" "fmt" "io" "log" "net/http" "strings" "time" pkgaes "github.com/perfect-panel/server/pkg/aes" ) // 替换为您实际的服务器地址 const BaseURL = "https://api.hifast.biz" // 替换为您实际的用户登录 Token (Authorization: Bearer ) const UserToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJEZXZpY2VJZCI6MzgzLCJMb2dpblR5cGUiOiJkZXZpY2UiLCJTZXNzaW9uSWQiOiIwMTliMmFmZC1jMjUwLTc1YmItODQzMy04NDMyNWVmZGRkMzMiLCJVc2VySWQiOjM4MywiZXhwIjoxNzY2NTU3NjMyLCJpYXQiOjE3NjU5NTI4MzJ9.kkcT4ojXG9qn_aVqMaGqUUXhHcZXHy49k5Vn05Et9OM" // 替换为您在后台配置的设备通信密钥 (Security Secret) const DeviceSecret = "c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx" // 替换为您要测试的 Transaction ID const TestTransactionID = "2000001083238483" func main() { fmt.Println("开始测试 Restore 接口 (AES 加密模式)...") fmt.Printf("目标 Transaction ID: %s\n", TestTransactionID) // 1. 构造原始请求数据 payload := map[string]interface{}{ "transactions": []string{TestTransactionID}, } payloadBytes, _ := json.Marshal(payload) fmt.Printf("原始请求体: %s\n", string(payloadBytes)) // 2. 加密数据 if DeviceSecret == "YOUR_DEVICE_SECRET_HERE" { log.Fatal("❌ 请在代码中设置 DeviceSecret (对应后台配置的 Security Secret)") } encryptedData, iv, err := pkgaes.Encrypt(payloadBytes, DeviceSecret) if err != nil { log.Fatalf("加密失败: %v", err) } // 3. 构造最终的请求体 (符合 DeviceMiddleware 要求的格式) // DeviceMiddleware 期望的格式是: { "data": "Base64Cipher", "time": "Nonce/IV" } // 或者直接在 URL Query 中传 ?data=...&time=... // 这里我们模拟 POST JSON body 的方式 finalPayload := map[string]interface{}{ "data": encryptedData, "time": iv, } finalBytes, _ := json.Marshal(finalPayload) fmt.Printf("加密后请求体: %s\n", string(finalBytes)) url := fmt.Sprintf("%s/v1/public/iap/apple/restore", BaseURL) req, _ := http.NewRequest("POST", url, strings.NewReader(string(finalBytes))) req.Header.Set("Content-Type", "application/json") // 添加必要的 Header 以通过 DeviceMiddleware req.Header.Set("Login-Type", "device") // 触发 DeviceMiddleware 的解密逻辑 // 注意:这里需要替换为真实有效的 Bearer Token,否则会报 401 // 您可以先登录后台或者使用 cmd/test_apple_iap 工具生成的 token 也是不可用的,必须是业务系统的 token // 为了演示,这里留空,实际运行前请填入 if UserToken != "YOUR_USER_TOKEN_HERE" { req.Header.Set("Authorization", "Bearer "+UserToken) } else { fmt.Println("⚠️ 警告: 未设置 UserToken,请求可能会失败 (401 Unauthorized)") } client := &http.Client{Timeout: 10 * time.Second} start := time.Now() resp, err := client.Do(req) if err != nil { log.Fatalf("请求失败: %v", err) } defer resp.Body.Close() duration := time.Since(start) body, _ := io.ReadAll(resp.Body) fmt.Printf("请求耗时: %v\n", duration) fmt.Printf("状态码: %d\n", resp.StatusCode) fmt.Printf("响应内容: %s\n", string(body)) if resp.StatusCode == 200 { var result map[string]interface{} if err := json.Unmarshal(body, &result); err == nil { // 检查业务状态码 if code, ok := result["code"].(float64); ok && int(code) != 200 { fmt.Printf("❌ 业务处理失败: code=%d, msg=%s\n", int(code), result["msg"]) return } fmt.Println("✅ Restore 接口调用成功!") if data, ok := result["data"].(map[string]interface{}); ok { if success, ok := data["success"].(bool); ok && success { fmt.Println(" 业务处理成功: success=true") } else { fmt.Println(" 业务处理结果未知:", data) } } else { fmt.Println(" 无数据返回或格式不符") } } } else { fmt.Println("❌ 接口调用失败") } }