From 17ffe5704f8744a0d34853a4fd814fbb5c11814d Mon Sep 17 00:00:00 2001 From: net909 Date: Sat, 8 Nov 2025 16:05:56 +0800 Subject: [PATCH] =?UTF-8?q?1panel=E6=94=AF=E6=8C=81=E5=AD=90=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E9=83=A8=E7=BD=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/lib/DeployHelper.php | 29 +++++++++++++++++++-- app/lib/deploy/opanel.php | 52 ++++++++++++++++++++++++++++++++++++-- app/lib/dns/cloudflare.php | 8 +++++- 3 files changed, 84 insertions(+), 5 deletions(-) diff --git a/app/lib/DeployHelper.php b/app/lib/DeployHelper.php index 4e072e0..7a6fad1 100644 --- a/app/lib/DeployHelper.php +++ b/app/lib/DeployHelper.php @@ -559,7 +559,7 @@ class DeployHelper 'icon' => 'opanel.png', 'desc' => '更新面板证书管理内的SSL证书', 'note' => null, - 'tasknote' => '系统会根据关联SSL证书的域名,自动更新对应证书', + 'tasknote' => '', 'inputs' => [ 'url' => [ 'name' => '面板地址', @@ -594,7 +594,32 @@ class DeployHelper 'value' => '0' ], ], - 'taskinputs' => [], + 'taskinputs' => [ + 'type' => [ + 'name' => '部署类型', + 'type' => 'radio', + 'options' => [ + '0' => '更新已有证书', + '3' => '面板本身的证书', + ], + 'value' => '0', + 'required' => true, + ], + 'id' => [ + 'name' => '证书ID', + 'type' => 'input', + 'placeholder' => '在证书列表查看ID', + 'note' => '留空为根据关联SSL证书的域名,自动更新对应证书', + 'show' => 'type==0', + ], + 'node_name' => [ + 'name' => '子节点名称', + 'type' => 'input', + 'placeholder' => '', + 'note' => '不填写时,将替换主控节点证书;否则,将替换被控节点证书', + 'show' => 'type==0', + ], + ], ], 'mwpanel' => [ 'name' => 'MW面板', diff --git a/app/lib/deploy/opanel.php b/app/lib/deploy/opanel.php index 487daab..5e2872b 100644 --- a/app/lib/deploy/opanel.php +++ b/app/lib/deploy/opanel.php @@ -11,6 +11,7 @@ class opanel implements DeployInterface private $url; private $key; private $proxy; + private $nodeName; public function __construct($config) { @@ -27,6 +28,42 @@ class opanel implements DeployInterface public function deploy($fullchain, $privatekey, $config, &$info) { + if (isset($config['type']) && $config['type'] == '3') { + $params = [ + 'cert' => $fullchain, + 'key' => $privatekey, + 'ssl' => 'Enable', + 'sslID' => null, + 'sslType' => 'import-paste', + ]; + try { + $this->request('/core/settings/ssl/update', $params); + $this->log("面板证书更新成功!"); + return; + } catch (Exception $e) { + throw new Exception("面板证书更新失败:" . $e->getMessage()); + } + } + + if (isset($config['node_name'])) $this->nodeName = $config['node_name']; + + if (!empty($config['id'])) { + $params = [ + 'sslID' => intval($config['id']), + 'type' => 'paste', + 'certificate' => $fullchain, + 'privateKey' => $privatekey, + 'description' => '', + ]; + try { + $this->request('/websites/ssl/upload', $params); + $this->log("证书ID:{$config['id']}更新成功!"); + return; + } catch (Exception $e) { + throw new Exception("证书ID:{$config['id']}更新失败:" . $e->getMessage()); + } + } + $domains = $config['domainList']; if (empty($domains)) throw new Exception('没有设置要部署的域名'); @@ -73,7 +110,15 @@ class opanel implements DeployInterface } } if ($success == 0) { - throw new Exception($errmsg ? $errmsg : '没有要更新的证书'); + $params = [ + 'sslID' => 0, + 'type' => 'paste', + 'certificate' => $fullchain, + 'privateKey' => $privatekey, + 'description' => '', + ]; + $this->request('/websites/ssl/upload', $params); + $this->log("证书上传成功!"); } } @@ -97,8 +142,11 @@ class opanel implements DeployInterface $token = md5('1panel' . $this->key . $timestamp); $headers = [ '1Panel-Token' => $token, - '1Panel-Timestamp' => $timestamp + '1Panel-Timestamp' => $timestamp, ]; + if (!empty($this->nodeName)) { + $headers['CurrentNode'] = $this->nodeName; + } $body = $params ? json_encode($params) : '{}'; if ($body) $headers['Content-Type'] = 'application/json'; $response = http_request($url, $body, null, null, $headers, $this->proxy); diff --git a/app/lib/dns/cloudflare.php b/app/lib/dns/cloudflare.php index 63681ba..be2ca48 100644 --- a/app/lib/dns/cloudflare.php +++ b/app/lib/dns/cloudflare.php @@ -78,6 +78,9 @@ class cloudflare implements DnsInterface $name = $this->domain == $row['name'] ? '@' : str_replace('.'.$this->domain, '', $row['name']); $status = str_ends_with($name, '_pause') ? '0' : '1'; $name = $status == '0' ? substr($name, 0, -6) : $name; + if ($row['type'] == 'SRV' && isset($row['priority'])) { + $row['content'] = $row['priority'] . ' ' . $row['content']; + } $list[] = [ 'RecordId' => $row['id'], 'Domain' => $this->domain, @@ -112,6 +115,9 @@ class cloudflare implements DnsInterface $name = $this->domain == $data['result']['name'] ? '@' : str_replace('.' . $this->domain, '', $data['result']['name']); $status = str_ends_with($name, '_pause') ? '0' : '1'; $name = $status == '0' ? substr($name, 0, -6) : $name; + if ($data['result']['type'] == 'SRV' && isset($data['result']['priority'])) { + $data['result']['content'] = $data['result']['priority'] . ' ' . $data['result']['content']; + } return [ 'RecordId' => $data['result']['id'], 'Domain' => $this->domain, @@ -257,7 +263,7 @@ class cloudflare implements DnsInterface { $url = $this->baseUrl . $path; - if (preg_match('/^[0-9a-z]+$/i', $this->ApiKey)) { + if (preg_match('/^[0-9a-f]+$/i', $this->ApiKey)) { $headers = [ 'X-Auth-Email: ' . $this->Email, 'X-Auth-Key: ' . $this->ApiKey,