allinssl/plugins/kuocai/action.go

166 lines
4.3 KiB
Go

package main
import (
"encoding/json"
"errors"
"fmt"
"io"
"math/rand"
"net/http"
"net/url"
"strings"
"time"
)
type LoginInfo struct {
account string
password string
}
type LoginResponse struct {
Code string
Message string
Data string
Success bool
}
type HTTPSConfig struct {
HTTPSStatus string `json:"https_status"`
CertificateSource string `json:"certificate_source"`
CertificateName string `json:"certificate_name"`
CertificateValue string `json:"certificate_value"`
PrivateKey string `json:"private_key"`
}
type DeployConfig struct {
DomainID string `json:"doMainId"`
HTTPS HTTPSConfig `json:"https"`
}
func randomString(n int) string {
rand.Seed(time.Now().UnixNano())
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b := make([]byte, n)
for i := range b {
b[i] = charset[rand.Intn(len(charset))]
}
return string(b)
}
const baseUrl = "https://www.kuocaiyun.com/"
func login(loginInfo LoginInfo) (string, error) {
loginUrl := baseUrl + "login/loginUser"
formData := url.Values{}
formData.Set("userAccount", loginInfo.account)
formData.Set("userPwd", loginInfo.password)
formData.Set("remember", "true")
resp, err := http.Post(loginUrl, "application/x-www-form-urlencoded", strings.NewReader(formData.Encode()))
const emptyString = ""
if err != nil {
outputError("请求失败", err)
return emptyString, err
}
if resp.StatusCode != 200 {
return emptyString, errors.New("请求失败:" + string(rune(resp.StatusCode)))
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
outputError("关闭响应流失败", err)
}
}(resp.Body)
// 读取响应体
var loginResp LoginResponse
if err := json.NewDecoder(resp.Body).Decode(&loginResp); err != nil {
outputError("解析登录请求结果失败", err)
return emptyString, err
}
if !loginResp.Success || loginResp.Data == "" {
return emptyString, errors.New("登录请求失败:" + loginResp.Message)
}
return loginResp.Data, nil
}
func deployCert(token string, domainId string, certKey string, certValue string) (map[string]interface{}, error) {
deployUrl := baseUrl + "CdnDomainHttps/httpsConfiguration"
params := DeployConfig{
DomainID: domainId,
HTTPS: HTTPSConfig{
HTTPSStatus: "on",
CertificateSource: "0",
CertificateName: "cert_" + randomString(13),
CertificateValue: certValue,
PrivateKey: certKey,
},
}
// 序列化参数
jsonData, err := json.Marshal(params)
if err != nil {
return nil, fmt.Errorf("JSON序列化失败: %v", err)
}
req, err := http.NewRequest("POST", deployUrl, strings.NewReader(string(jsonData)))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Cookie", "kuocai_cdn_token="+token)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("HTTP请求失败: %v", err)
}
defer resp.Body.Close()
// 解析响应
var result map[string]interface{}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("响应解析失败: %v", err)
}
if !result["success"].(bool) {
return result, fmt.Errorf("更新证书失败")
}
return result, nil
}
func Upload(cfg map[string]any) (*Response, error) {
if cfg == nil {
return nil, fmt.Errorf("config cannot be nil")
}
certStr, ok := cfg["cert"].(string)
if !ok || certStr == "" {
return nil, fmt.Errorf("cert is required and must be a string")
}
keyStr, ok := cfg["key"].(string)
if !ok || keyStr == "" {
return nil, fmt.Errorf("key is required and must be a string")
}
username, ok := cfg["username"].(string)
if !ok || username == "" {
return nil, fmt.Errorf("username is required and must be a string")
}
password, ok := cfg["password"].(string)
if !ok || password == "" {
return nil, fmt.Errorf("password is required and must be a string")
}
domainId, ok := cfg["domainId"].(string)
if !ok || domainId == "" {
return nil, fmt.Errorf("domainId is required and must be a string")
}
token, err := login(LoginInfo{account: username, password: password})
if err != nil || token == "" {
return nil, fmt.Errorf("fetch token failed, err %v", err)
}
res, err := deployCert(token, domainId, keyStr, certStr)
if err != nil {
return nil, err
}
return &Response{
Status: "success",
Message: "success",
Result: res,
}, nil
}