package deploy import ( "ALLinSSL/backend/app/dto/response" "ALLinSSL/backend/internal/access" "crypto/md5" "crypto/tls" "encoding/hex" "encoding/json" "fmt" "io" "net/http" "net/url" "strconv" "strings" "time" ) func generateSignature(timestamp, apiKey string) string { keyMd5 := md5.Sum([]byte(apiKey)) keyMd5Hex := strings.ToLower(hex.EncodeToString(keyMd5[:])) signMd5 := md5.Sum([]byte(timestamp + keyMd5Hex)) signMd5Hex := strings.ToLower(hex.EncodeToString(signMd5[:])) return signMd5Hex } func RequestBt(data *url.Values, method, providerID, requestUrl string) (map[string]any, error) { providerData, err := access.GetAccess(providerID) if err != nil { return nil, err } providerConfigStr, ok := providerData["config"].(string) if !ok { return nil, fmt.Errorf("api配置错误") } // 解析 JSON 配置 var providerConfig map[string]string err = json.Unmarshal([]byte(providerConfigStr), &providerConfig) if err != nil { return nil, err } timestamp := time.Now().Unix() token := generateSignature(fmt.Sprintf("%d", timestamp), providerConfig["api_key"]) data.Set("request_time", fmt.Sprintf("%d", timestamp)) data.Set("request_token", token) parsedURL, err := url.Parse(providerConfig["url"]) if err != nil { return nil, err } baseURL := fmt.Sprintf("%s://%s/", parsedURL.Scheme, parsedURL.Host) req, err := http.NewRequest(method, baseURL+requestUrl, strings.NewReader(data.Encode())) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36") // 自定义 Transport,跳过 SSL 证书验证 ignoreSsl := false if providerConfig["ignore_ssl"] == "1" { ignoreSsl = true } tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: ignoreSsl}, } client := &http.Client{Transport: tr} resp, err := client.Do(req) if err != nil { // fmt.Println(err) return nil, fmt.Errorf("请求BT失败: %v", err) } body, _ := io.ReadAll(resp.Body) defer resp.Body.Close() var res map[string]interface{} err = json.Unmarshal(body, &res) if err != nil { return nil, fmt.Errorf("返回值解析失败: %v,%s", err, string(body)) } if res["status"] != nil && !res["status"].(bool) { return nil, fmt.Errorf("请求出错: %s", res["msg"].(string)) } return res, nil } func UploadBt(key, csr, providerID string) (string, error) { data := url.Values{} data.Set("key", key) data.Set("csr", csr) response, err := RequestBt(&data, "POST", providerID, "ssl/cert/save_cert") if response == nil { return "", fmt.Errorf("证书上传失败: %v", err) } sslHash, ok := response["ssl_hash"].(string) if !ok { return "", fmt.Errorf("证书上传失败: ssl_hash 不存在") } return sslHash, nil } func DeployBt(cfg map[string]any) error { cert, ok := cfg["certificate"].(map[string]any) if !ok { return fmt.Errorf("证书不存在") } // 设置证书 keyPem, ok := cert["key"].(string) if !ok { return fmt.Errorf("证书错误:key") } certPem, ok := cert["cert"].(string) if !ok { return fmt.Errorf("证书错误:cert") } var providerID string switch v := cfg["provider_id"].(type) { case float64: providerID = strconv.Itoa(int(v)) case string: providerID = v default: return fmt.Errorf("参数错误:provider_id") } data := url.Values{} data.Set("cert_type", "1") data.Set("privateKey", keyPem) data.Set("certPem", certPem) _, err := RequestBt(&data, "POST", providerID, "config?action=SetPanelSSL") if err != nil { return fmt.Errorf("证书部署失败: %v", err) } return nil } func DeployBtSite(cfg map[string]any) error { cert, ok := cfg["certificate"].(map[string]any) if !ok { return fmt.Errorf("证书不存在") } // 设置证书 keyPem, ok := cert["key"].(string) if !ok { return fmt.Errorf("证书错误:key") } certPem, ok := cert["cert"].(string) if !ok { return fmt.Errorf("证书错误:cert") } var providerID string switch v := cfg["provider_id"].(type) { case float64: providerID = strconv.Itoa(int(v)) case string: providerID = v default: return fmt.Errorf("参数错误:provider_id") } siteNames, ok := cfg["siteName"].(string) if !ok { return fmt.Errorf("参数错误:siteName") } sslHash, err := UploadBt(keyPem, certPem, providerID) if err != nil { return err } batchInfo := []map[string]string{} siteNamesList := strings.Split(siteNames, ",") for _, siteName := range siteNamesList { batchInfo = append(batchInfo, map[string]string{ "siteName": siteName, "ssl_hash": sslHash, }) } batchs, err := json.Marshal(batchInfo) data := url.Values{} data.Set("BatchInfo", string(batchs)) _, err = RequestBt(&data, "POST", providerID, "ssl?action=SetBatchCertToSite") if err != nil { return fmt.Errorf("证书部署失败: %v", err) } return nil } func DeployBtDockerSite(cfg map[string]any) error { cert, ok := cfg["certificate"].(map[string]any) if !ok { return fmt.Errorf("证书不存在") } // 设置证书 keyPem, ok := cert["key"].(string) if !ok { return fmt.Errorf("证书错误:key") } certPem, ok := cert["cert"].(string) if !ok { return fmt.Errorf("证书错误:cert") } var providerID string switch v := cfg["provider_id"].(type) { case float64: providerID = strconv.Itoa(int(v)) case string: providerID = v default: return fmt.Errorf("参数错误:provider_id") } siteName, ok := cfg["siteName"].(string) if !ok { return fmt.Errorf("参数错误:siteName") } data := url.Values{} data.Set("key", keyPem) data.Set("csr", certPem) data.Set("siteName", siteName) _, err := RequestBt(&data, "POST", providerID, "mod/docker/com/set_ssl") if err != nil { return fmt.Errorf("证书部署失败: %v", err) } return nil } func BtPanelAPITest(providerID string) error { data := url.Values{} _, err := RequestBt(&data, "POST", providerID, "system?action=GetNetWork") if err != nil { return fmt.Errorf("测试请求失败: %v", err) } return nil } func BtPanelSiteList(providerID string) ([]response.AccessSiteList, error) { data := url.Values{} data.Set("cert_list", "") siteList, err := RequestBt(&data, "POST", providerID, "ssl?action=GetSiteDomain") if err != nil { fmt.Println("获取网站列表失败:", err) return nil, err } var result []response.AccessSiteList sites, ok := siteList["all"].([]any) if !ok { return nil, fmt.Errorf("获取网站列表失败: 数据格式错误") } for _, site := range sites { result = append(result, response.AccessSiteList{Id: "", SiteName: site.(string), Domain: []string{}}) } //fmt.Printf("siteList:%#v\n", result) return result, nil } func DeployBtSingleSite(cfg map[string]any) error { cert, ok := cfg["certificate"].(map[string]any) if !ok { return fmt.Errorf("证书不存在") } // 设置证书 keyPem, ok := cert["key"].(string) if !ok { return fmt.Errorf("证书错误:key") } certPem, ok := cert["cert"].(string) if !ok { return fmt.Errorf("证书错误:cert") } var providerID string switch v := cfg["provider_id"].(type) { case float64: providerID = strconv.Itoa(int(v)) case string: providerID = v default: return fmt.Errorf("参数错误:provider_id") } siteName, ok := cfg["siteName"].(string) if !ok { return fmt.Errorf("参数错误:siteName") } data := url.Values{} data.Set("key", keyPem) data.Set("csr", certPem) data.Set("siteName", siteName) _, err := RequestBt(&data, "POST", providerID, "/site?action=SetSSL") if err != nil { return fmt.Errorf("证书部署失败: %v", err) } return nil }