From 9f529e25288aad8acde9554672a6e6dbeb6d1d34 Mon Sep 17 00:00:00 2001 From: net909 Date: Thu, 21 Aug 2025 19:47:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EuniCloud=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=EF=BC=8Ccdnfly=E9=83=A8=E7=BD=B2=E6=94=AF=E6=8C=81=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E5=AF=86=E7=A0=81=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/DeployHelper.php | 85 +++++++++++- app/lib/deploy/cdnfly.php | 55 +++++++- app/lib/deploy/unicloud.php | 211 ++++++++++++++++++++++++++++++ app/view/domain/domain.html | 1 - app/view/domain/record.html | 1 - composer.lock | 44 +++++-- public/static/images/unicloud.png | Bin 0 -> 22521 bytes 7 files changed, 378 insertions(+), 19 deletions(-) create mode 100644 app/lib/deploy/unicloud.php create mode 100644 public/static/images/unicloud.png diff --git a/app/lib/DeployHelper.php b/app/lib/DeployHelper.php index d559f88..a6fff72 100644 --- a/app/lib/DeployHelper.php +++ b/app/lib/DeployHelper.php @@ -139,12 +139,12 @@ class DeployHelper 'class' => 1, 'icon' => 'host.png', 'desc' => '支持虚拟主机与CDN站点', - 'note' => '以上登录地址需填写Easypanel管理员面板地址,非用户面板。', + 'note' => '以上登录信息为Easypanel管理员面板的,非用户面板。', 'inputs' => [ 'url' => [ 'name' => '面板地址', 'type' => 'input', - 'placeholder' => 'Easypanel管理员面板地址', + 'placeholder' => 'Easypanel面板地址', 'note' => '填写规则如:http://192.168.1.100:3312 ,不要带其他后缀', 'required' => true, ], @@ -288,17 +288,43 @@ class DeployHelper 'note' => '填写示例:http://demo.cdnfly.cn', 'required' => true, ], + 'auth' => [ + 'name' => '认证方式', + 'type' => 'radio', + 'options' => [ + '0' => '接口密钥', + '1' => '模拟登录', + ], + 'value' => '0', + 'required' => true, + ], 'api_key' => [ 'name' => 'api_key', 'type' => 'input', 'placeholder' => '', 'required' => true, + 'show' => 'auth==0', ], 'api_secret' => [ 'name' => 'api_secret', 'type' => 'input', 'placeholder' => '', 'required' => true, + 'show' => 'auth==0', + ], + 'username' => [ + 'name' => '登录账号', + 'type' => 'input', + 'placeholder' => '', + 'required' => true, + 'show' => 'auth==1', + ], + 'password' => [ + 'name' => '登录密码', + 'type' => 'input', + 'placeholder' => '', + 'required' => true, + 'show' => 'auth==1', ], 'proxy' => [ 'name' => '使用代理服务器', @@ -1636,6 +1662,61 @@ class DeployHelper ], ], ], + 'unicloud' => [ + 'name' => 'uniCloud', + 'class' => 2, + 'icon' => 'unicloud.png', + 'desc' => '部署到uniCloud服务空间', + 'note' => null, + 'inputs' => [ + 'username' => [ + 'name' => '账号', + 'type' => 'input', + 'placeholder' => '', + 'required' => true, + ], + 'password' => [ + 'name' => '密码', + 'type' => 'input', + 'placeholder' => '', + 'required' => true, + ], + 'proxy' => [ + 'name' => '使用代理服务器', + 'type' => 'radio', + 'options' => [ + '0' => '否', + '1' => '是', + ], + 'value' => '0' + ], + ], + 'taskinputs' => [ + 'spaceId' => [ + 'name' => '服务空间ID', + 'type' => 'input', + 'placeholder' => 'spaceId', + 'required' => true, + ], + 'provider' => [ + 'name' => '空间提供商', + 'type' => 'select', + 'options' => [ + ['value'=>'aliyun', 'label'=>'阿里云'], + ['value'=>'tencent', 'label'=>'腾讯云'], + ['value'=>'alipay', 'label'=>'支付宝云'], + ], + 'value' => 'aliyun', + 'required' => true, + ], + 'domains' => [ + 'name' => '空间域名', + 'type' => 'input', + 'placeholder' => '多个域名可使用,分隔', + 'required' => true, + ], + ], + ], 'aws' => [ 'name' => 'AWS', 'class' => 2, diff --git a/app/lib/deploy/cdnfly.php b/app/lib/deploy/cdnfly.php index 80e59e5..06b43ed 100644 --- a/app/lib/deploy/cdnfly.php +++ b/app/lib/deploy/cdnfly.php @@ -11,6 +11,9 @@ class cdnfly implements DeployInterface private $url; private $api_key; private $api_secret; + private $auth = 0; + private $username; + private $password; private $proxy; public function __construct($config) @@ -18,13 +21,23 @@ class cdnfly implements DeployInterface $this->url = rtrim($config['url'], '/'); $this->api_key = $config['api_key']; $this->api_secret = $config['api_secret']; + $this->auth = isset($config['auth']) ? $config['auth'] : 0; + if ($this->auth == 1) { + $this->username = $config['username']; + $this->password = $config['password']; + } $this->proxy = $config['proxy'] == 1; } public function check() { - if (empty($this->url) || empty($this->api_key) || empty($this->api_secret)) throw new Exception('必填参数不能为空'); - $this->request('/v1/user'); + if ($this->auth == 1) { + if (empty($this->url) || empty($this->username) || empty($this->password)) throw new Exception('必填参数不能为空'); + $this->login(); + } else { + if (empty($this->url) || empty($this->api_key) || empty($this->api_secret)) throw new Exception('必填参数不能为空'); + $this->request('/v1/user'); + } } public function deploy($fullchain, $privatekey, $config, &$info) @@ -37,10 +50,46 @@ class cdnfly implements DeployInterface 'cert' => $fullchain, 'key' => $privatekey, ]; - $this->request('/v1/certs/' . $id, $params, 'PUT'); + if ($this->auth == 1) { + $access_token = $this->login(); + $url = $this->url . '/v1/certs/' . $id; + $body = json_encode($params); + $headers = [ + 'Access-Token' => $access_token, + ]; + $response = http_request($url, $body, null, null, $headers, $this->proxy, 'PUT'); + $result = json_decode($response['body'], true); + if (isset($result['code']) && $result['code'] == 0) { + } elseif (isset($result['msg'])) { + throw new Exception('证书ID:' . $id . '更新失败,' . $result['msg']); + } else { + throw new Exception('证书ID:' . $id . '更新失败,返回数据解析失败'); + } + } else { + $this->request('/v1/certs/' . $id, $params, 'PUT'); + } $this->log("证书ID:{$id}更新成功!"); } + public function login() + { + $url = $this->url . '/v1/login'; + $params = [ + 'account' => $this->username, + 'password' => $this->password, + ]; + $body = json_encode($params); + $response = http_request($url, $body, null, null, null, $this->proxy); + $result = json_decode($response['body'], true); + if (isset($result['code']) && $result['code'] == 0) { + return $result['data']['access_token']; + } elseif (isset($result['msg'])) { + throw new Exception($result['msg']); + } else { + throw new Exception('登录失败,返回数据解析失败'); + } + } + private function request($path, $params = null, $method = null) { $url = $this->url . $path; diff --git a/app/lib/deploy/unicloud.php b/app/lib/deploy/unicloud.php new file mode 100644 index 0000000..cd663e1 --- /dev/null +++ b/app/lib/deploy/unicloud.php @@ -0,0 +1,211 @@ +username = $config['username']; + $this->password = $config['password']; + $this->proxy = $config['proxy'] == 1; + $this->deviceId = getMillisecond() . random(7, 1); + } + + public function check() + { + if (empty($this->username) || empty($this->password)) throw new Exception('账号或密码不能为空'); + $this->login(); + } + + public function deploy($fullchain, $privatekey, $config, &$info) + { + if (empty($config['domains'])) throw new Exception('绑定的域名不能为空'); + $this->getToken(); + + $url = 'https://unicloud-api.dcloud.net.cn/unicloud/api/host/create-domain-with-cert'; + foreach (explode(',', $config['domains']) as $domain) { + $params = [ + 'appid' => '', + 'provider' => $config['provider'], + 'spaceId' => $config['spaceId'], + 'domain' => $domain, + 'cert' => rawurlencode($fullchain), + 'key' => rawurlencode($privatekey), + ]; + $post = json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + $headers = [ + 'Token' => $this->token, + ]; + $response = http_request($url, $post, null, null, $headers, $this->proxy); + $result = json_decode($response['body'], true); + if (isset($result['ret']) && $result['ret'] == 0) { + $this->log('域名:' . $domain . ' 证书更新成功!'); + } elseif(isset($result['desc'])) { + throw new Exception('域名:' . $domain . ' 证书更新失败:' . $result['desc']); + } else { + throw new Exception('域名:' . $domain . ' 证书更新失败:' . $response['body']); + } + } + } + + private function login() + { + $url = 'https://account.dcloud.net.cn/client'; + $clientInfo = $this->getClientInfo('__UNI__unicloud_console', '账号中心'); + $bizParams = [ + 'functionTarget' => 'uni-id-co', + 'functionArgs' => [ + 'method' => 'login', + 'params' => [[ + 'password' => $this->password, + 'captcha' => '', + 'resetAppId' => '__UNI__unicloud_console', + 'resetUniPlatform' => 'web', + 'isReturnToken' => false, + 'email' => $this->username, + ]], + 'clientInfo' => $clientInfo, + ], + ]; + $params = [ + 'method' => 'serverless.function.runtime.invoke', + 'params' => json_encode($bizParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), + 'spaceId' => 'uni-id-server', + 'timestamp' => getMillisecond(), + ]; + $sign = $this->sign($params, 'ba461799-fde8-429f-8cc4-4b6d306e2339'); + $post = json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + $headers = [ + 'Origin' => 'https://account.dcloud.net.cn', + 'Referer' => 'https://account.dcloud.net.cn/', + 'X-Client-Info' => json_encode($clientInfo, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), + 'X-Serverless-Sign' => $sign, + ]; + $response = http_request($url, $post, null, null, $headers, $this->proxy); + $result = json_decode($response['body'], true); + if (isset($result['success']) && $result['success'] == true) { + if (isset($result['data']['errCode']) && $result['data']['errCode'] == 0) { + return $result['data']['newToken']['token']; + } else { + throw new Exception('登录失败:' . $result['data']['errMsg']); + } + } else { + throw new Exception('登录失败:' . $response['body']); + } + } + + private function getToken() + { + $uniIdToken = $this->login(); + $url = 'https://unicloud.dcloud.net.cn/client'; + $clientInfo = $this->getClientInfo('__UNI__unicloud_console', 'uniCloud控制台'); + $bizParams = [ + 'functionTarget' => 'uni-cloud-kernel', + 'functionArgs' => [ + 'action' => 'user/getUserToken', + 'data' => [ + 'isLogin' => true + ], + 'clientInfo' => $clientInfo, + 'uniIdToken' => $uniIdToken, + ], + ]; + $params = [ + 'method' => 'serverless.function.runtime.invoke', + 'params' => json_encode($bizParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), + 'spaceId' => 'dc-6nfabcn6ada8d3dd', + 'timestamp' => getMillisecond(), + ]; + $sign = $this->sign($params, '4c1f7fbf-c732-42b0-ab10-4634a8bbe834'); + $post = json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + $headers = [ + 'Origin' => 'https://account.dcloud.net.cn', + 'Referer' => 'https://account.dcloud.net.cn/', + 'X-Client-Info' => json_encode($clientInfo, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), + 'X-Client-Token' => $uniIdToken, + 'X-Serverless-Sign' => $sign, + ]; + $response = http_request($url, $post, null, null, $headers, $this->proxy); + $result = json_decode($response['body'], true); + if (isset($result['success']) && $result['success'] == true) { + if (isset($result['data']['code']) && $result['data']['code'] == 0) { + if (isset($result['data']['data']['ret']) && $result['data']['data']['ret'] == 0) { + $this->token = $result['data']['data']['data']['token']; + return $result['data']['data']['data']['token']; + } else { + throw new Exception('获取token失败:' . $result['data']['data']['desc']); + } + } else { + throw new Exception('获取token失败:' . $response['body']); + } + } else { + throw new Exception('获取token失败:' . $response['body']); + } + } + + private function getClientInfo($appId, $appName, $appVersion = '1.0.0', $appVersionCode = '100') + { + $clientInfo = [ + 'PLATFORM' => 'web', + 'OS' => 'windows', + 'APPID' => $appId, + 'DEVICEID' => $this->deviceId, + 'scene' => 1001, + 'appId' => $appId, + 'appLanguage' => 'zh-Hans', + 'appName' => $appName, + 'appVersion' => $appVersion, + 'appVersionCode' => $appVersionCode, + 'browserName' => 'chrome', + 'browserVersion' => '122.0.6261.95', + 'deviceId' => $this->deviceId, + 'deviceModel' => 'PC', + 'deviceType' => 'pc', + 'hostName' => 'chrome', + 'hostVersion' => '122.0.6261.95', + 'osName' => 'windows', + 'osVersion' => '10 x64', + 'ua' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36', + 'uniCompilerVersion' => '4.45', + 'uniPlatform' => 'web', + 'uniRuntimeVersion' => '4.45', + 'locale' => 'zh-Hans', + 'LOCALE' => 'zh-Hans', + ]; + return $clientInfo; + } + + private function sign($data, $key) + { + ksort($data); + $signstr = ''; + foreach ($data as $k => $v) { + $signstr .= $k . '=' . $v . '&'; + } + $signstr = rtrim($signstr, '&'); + return hash_hmac('md5', $signstr, $key); + } + + public function setLogger($func) + { + $this->logger = $func; + } + + private function log($txt) + { + if ($this->logger) { + call_user_func($this->logger, $txt); + } + } +} diff --git a/app/view/domain/domain.html b/app/view/domain/domain.html index af2994f..a0beb10 100644 --- a/app/view/domain/domain.html +++ b/app/view/domain/domain.html @@ -301,7 +301,6 @@ $(document).ready(function(){ }, onPageChange: function(number, size){ if(size != defaultPageSize){ - defaultPageSize = size; setCookie('domain_pagesize', size); } }, diff --git a/app/view/domain/record.html b/app/view/domain/record.html index 763de3e..4f42403 100644 --- a/app/view/domain/record.html +++ b/app/view/domain/record.html @@ -359,7 +359,6 @@ $(document).ready(function(){ ], onPageChange: function(number, size){ if(size != defaultPageSize){ - defaultPageSize = size; setCookie('record_pagesize', size); } }, diff --git a/composer.lock b/composer.lock index a902d42..41c91bb 100644 --- a/composer.lock +++ b/composer.lock @@ -951,7 +951,7 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -1014,7 +1014,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" }, "funding": [ { @@ -1025,6 +1025,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -1034,7 +1038,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -1095,7 +1099,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" }, "funding": [ { @@ -1106,6 +1110,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -1115,7 +1123,7 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -1176,7 +1184,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -1187,6 +1195,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -1196,7 +1208,7 @@ }, { "name": "symfony/polyfill-php81", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -1252,7 +1264,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" }, "funding": [ { @@ -1263,6 +1275,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -1272,7 +1288,7 @@ }, { "name": "symfony/polyfill-php82", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php82.git", @@ -1328,7 +1344,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php82/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php82/tree/v1.33.0" }, "funding": [ { @@ -1339,6 +1355,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -1866,7 +1886,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { @@ -1880,6 +1900,6 @@ "ext-sockets": "*", "ext-ssh2": "*" }, - "platform-dev": {}, + "platform-dev": [], "plugin-api-version": "2.6.0" } diff --git a/public/static/images/unicloud.png b/public/static/images/unicloud.png new file mode 100644 index 0000000000000000000000000000000000000000..710f9246e7f27c03d72858b39e9ab57d1fa36b5c GIT binary patch literal 22521 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 literal 0 HcmV?d00001