From db418c7a117840dc7353deee43a5c20071a9cd12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E7=8E=96?= <2792045980@qq.com> Date: Wed, 22 Apr 2026 22:49:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=90=8C=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E6=8F=92=E4=BB=B6=20(#445)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 域名账户新增页可选择同系统对接,需传入对方系统网址;用户ID;API密钥 Co-authored-by: 小玖 <232709122+xiaojiu-code@users.noreply.github.com> --- app/lib/DnsHelper.php | 42 ++++++ app/lib/dns/cccyun.php | 327 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 369 insertions(+) create mode 100644 app/lib/dns/cccyun.php diff --git a/app/lib/DnsHelper.php b/app/lib/DnsHelper.php index 6866aba..f04e2dc 100644 --- a/app/lib/DnsHelper.php +++ b/app/lib/DnsHelper.php @@ -608,6 +608,47 @@ class DnsHelper 'page' => false, 'add' => false, ], + 'cccyun' => [ + 'name' => '同系统对接', + 'icon' => 'logo.png', + 'note' => '通过聚合DNS管理系统接口实现域名解析管理', + 'config' => [ + 'base_url' => [ + 'name' => 'API 地址', + 'type' => 'input', + 'placeholder' => '例如:https://dns.example.com', + 'required' => true, + ], + 'uid' => [ + 'name' => '用户 ID', + 'type' => 'input', + 'placeholder' => '', + 'required' => true, + ], + 'key' => [ + 'name' => 'API 密钥', + 'type' => 'input', + 'placeholder' => '', + 'required' => true, + ], + 'proxy' => [ + 'name' => '使用代理服务器', + 'type' => 'radio', + 'options' => [ + '0' => '否', + '1' => '是', + ], + 'value' => '0' + ], + ], + 'remark' => 2, + 'status' => true, + 'redirect' => false, + 'log' => false, + 'weight' => true, + 'page' => false, + 'add' => false, + ], ]; public static $line_name = [ @@ -627,6 +668,7 @@ class DnsHelper 'spaceship' => ['DEF' => 'default'], 'aliyunesa' => ['DEF' => '0'], 'tencenteo' => ['DEF' => 'Default'], + 'cccyun' => ['DEF' => 'default'], ]; public static function getList() diff --git a/app/lib/dns/cccyun.php b/app/lib/dns/cccyun.php new file mode 100644 index 0000000..ba2efe6 --- /dev/null +++ b/app/lib/dns/cccyun.php @@ -0,0 +1,327 @@ +uid = $config['uid']; + $this->key = $config['key']; + $this->baseUrl = rtrim($config['base_url'], '/'); + $proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false; + $this->proxy = $proxy; + $this->domain = $config['domain']; + $this->domainid = $config['domainid']; + } + + public function getError() + { + return $this->error; + } + + public function check() + { + if ($this->getDomainList() != false) { + return true; + } + return false; + } + + public function getDomainList($KeyWord = null, $PageNumber = 1, $PageSize = 20) + { + $offset = ($PageNumber - 1) * $PageSize; + $param = [ + 'offset' => $offset, + 'limit' => $PageSize, + ]; + if (!isNullOrEmpty($KeyWord)) { + $param['kw'] = $KeyWord; + } + + $data = $this->send_request('/api/domain', $param); + if ($data && isset($data['rows'])) { + $list = []; + foreach ($data['rows'] as $row) { + $list[] = [ + 'DomainId' => $row['id'], + 'Domain' => $row['name'], + 'RecordCount' => $row['recordcount'], + ]; + } + return ['total' => $data['total'], 'list' => $list]; + } + return false; + } + + public function getDomainRecords($PageNumber = 1, $PageSize = 20, $KeyWord = null, $SubDomain = null, $Value = null, $Type = null, $Line = null, $Status = null) + { + $offset = ($PageNumber - 1) * $PageSize; + $param = [ + 'offset' => $offset, + 'limit' => $PageSize, + ]; + if (!isNullOrEmpty($KeyWord)) $param['keyword'] = $KeyWord; + if (!isNullOrEmpty($SubDomain)) $param['subdomain'] = $SubDomain; + if (!isNullOrEmpty($Value)) $param['value'] = $Value; + if (!isNullOrEmpty($Type)) $param['type'] = $Type; + if (!isNullOrEmpty($Line)) $param['line'] = $Line; + if (!isNullOrEmpty($Status)) $param['status'] = $Status; + + $data = $this->send_request('/api/record/data/' . $this->domainid, $param); + if ($data && isset($data['rows'])) { + $list = []; + foreach ($data['rows'] as $row) { + $list[] = [ + 'RecordId' => $row['RecordId'], + 'Domain' => $row['Domain'], + 'Name' => $row['Name'], + 'Type' => $row['Type'], + 'Value' => $row['Value'], + 'Line' => $row['Line'], + 'LineName' => $row['LineName'], + 'TTL' => $row['TTL'], + 'MX' => $row['MX'], + 'Status' => $row['Status'], + 'Weight' => $row['Weight'], + 'Remark' => $row['Remark'], + 'UpdateTime' => $row['UpdateTime'], + ]; + } + return ['total' => $data['total'], 'list' => $list]; + } elseif ($this->error == '记录列表为空。') { + return ['total' => 0, 'list' => []]; + } + return false; + } + + public function getSubDomainRecords($SubDomain, $PageNumber = 1, $PageSize = 20, $Type = null, $Line = null) + { + if ($SubDomain == '') $SubDomain = '@'; + return $this->getDomainRecords($PageNumber, $PageSize, null, $SubDomain, null, $Type, $Line); + } + + public function getDomainRecordInfo($RecordId) + { + $param = [ + 'recordid' => $RecordId, + ]; + $data = $this->send_request('/api/record/data/' . $this->domainid, $param); + if ($data && isset($data['rows'][0])) { + $row = $data['rows'][0]; + return [ + 'RecordId' => $row['RecordId'], + 'Domain' => $row['Domain'], + 'Name' => $row['Name'], + 'Type' => $row['Type'], + 'Value' => $row['Value'], + 'Line' => $row['Line'], + 'TTL' => $row['TTL'], + 'MX' => $row['MX'], + 'Status' => $row['Status'], + 'Weight' => $row['Weight'], + 'Remark' => $row['Remark'], + 'UpdateTime' => $row['UpdateTime'], + ]; + } + return false; + } + + public function addDomainRecord($Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = 1, $Weight = null, $Remark = null) + { + $param = [ + 'name' => $Name, + 'type' => $Type, + 'value' => $Value, + 'line' => $Line, + 'ttl' => intval($TTL), + ]; + if ($Type == 'MX' && !isNullOrEmpty($MX)) { + $param['mx'] = intval($MX); + } + if (!isNullOrEmpty($Weight)) { + $param['weight'] = intval($Weight); + } + if (!isNullOrEmpty($Remark)) { + $param['remark'] = $Remark; + } + + $data = $this->send_request('/api/record/add/' . $this->domainid, $param); + return is_array($data) && isset($data['code']) && $data['code'] == 0; + } + + public function updateDomainRecord($RecordId, $Name, $Type, $Value, $Line = 'default', $TTL = 600, $MX = 1, $Weight = null, $Remark = null) + { + $param = [ + 'recordid' => $RecordId, + 'name' => $Name, + 'type' => $Type, + 'value' => $Value, + 'line' => $Line, + 'ttl' => intval($TTL), + ]; + if ($Type == 'MX' && !isNullOrEmpty($MX)) { + $param['mx'] = intval($MX); + } + if (!isNullOrEmpty($Weight)) { + $param['weight'] = intval($Weight); + } + if (!isNullOrEmpty($Remark)) { + $param['remark'] = $Remark; + } + + $data = $this->send_request('/api/record/update/' . $this->domainid, $param); + return is_array($data) && isset($data['code']) && $data['code'] == 0; + } + + public function updateDomainRecordRemark($RecordId, $Remark) + { + $param = [ + 'recordid' => $RecordId, + 'remark' => $Remark, + ]; + + $data = $this->send_request('/api/record/remark/' . $this->domainid, $param); + return is_array($data) && isset($data['code']) && $data['code'] == 0; + } + + public function deleteDomainRecord($RecordId) + { + $param = [ + 'recordid' => $RecordId, + ]; + + $data = $this->send_request('/api/record/delete/' . $this->domainid, $param); + return is_array($data) && isset($data['code']) && $data['code'] == 0; + } + + public function setDomainRecordStatus($RecordId, $Status) + { + $param = [ + 'recordid' => $RecordId, + 'status' => $Status, + ]; + + $data = $this->send_request('/api/record/status/' . $this->domainid, $param); + return is_array($data) && isset($data['code']) && $data['code'] == 0; + } + + public function getDomainRecordLog($PageNumber = 1, $PageSize = 20, $KeyWord = null, $StartDate = null, $endDate = null) + { + $this->setError('该DNS服务商不支持查看日志'); + return false; + } + + public function getRecordLine() + { + $data = $this->send_request('/api/domain/' . $this->domainid, ['loginurl' => 0]); + if ($data && isset($data['recordLine'])) { + $list = []; + foreach ($data['recordLine'] as $row) { + $list[$row['id']] = [ + 'name' => $row['name'], + 'parent' => isset($row['parent']) ? $row['parent'] : null, + ]; + } + return $list; + } + return false; + } + + public function getMinTTL() + { + $data = $this->send_request('/api/domain/' . $this->domainid, ['loginurl' => 0]); + if ($data && isset($data['minTTL'])) { + return $data['minTTL']; + } + return false; + } + + public function addDomain($Domain) + { + $this->setError('该DNS服务商不支持添加域名'); + return false; + } + + private function send_request($path, $param = []) + { + try { + $timestamp = time(); + $signStr = $this->uid . $timestamp . $this->key; + $sign = md5($signStr); + + $url = $this->baseUrl . $path; + + $param['uid'] = $this->uid; + $param['timestamp'] = $timestamp; + $param['sign'] = $sign; + $postData = http_build_query($param); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/x-www-form-urlencoded' + ]); + + if ($this->proxy) { + $proxy_config = Db::name('config')->where('key', 'proxy')->value('value'); + if ($proxy_config) { + $proxy_info = json_decode($proxy_config, true); + if ($proxy_info && $proxy_info['open'] == 1) { + curl_setopt($ch, CURLOPT_PROXY, $proxy_info['ip'] . ':' . $proxy_info['port']); + if (!empty($proxy_info['username']) && !empty($proxy_info['password'])) { + curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_info['username'] . ':' . $proxy_info['password']); + } + } + } + } + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $curlError = curl_error($ch); + curl_close($ch); + + if ($curlError) { + throw new Exception('CURL Error: ' . $curlError); + } + + if ($httpCode != 200) { + throw new Exception('HTTP Error: ' . $httpCode); + } + + $result = json_decode($response, true); + if (!$result) { + throw new Exception('JSON Decode Error: ' . $response); + } + + if (isset($result['code']) && $result['code'] != 0 && isset($result['msg'])) { + throw new Exception($result['msg']); + } + + return isset($result['data']) ? $result['data'] : $result; + + } catch (Exception $e) { + $this->setError($e->getMessage()); + return false; + } + } + + private function setError($message) + { + $this->error = $message; + } +} \ No newline at end of file