mirror of
https://github.com/netcccyun/dnsmgr.git
synced 2026-05-09 23:16:27 +02:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1eb6267a2 | ||
|
|
2c81b36249 | ||
|
|
8d5a9bc083 | ||
|
|
31300d8a7b | ||
|
|
300f2a9b92 | ||
|
|
865275c065 | ||
|
|
cae9887e05 | ||
|
|
6de361171e | ||
|
|
e59ff8997e | ||
|
|
6ce2e006b5 | ||
|
|
197d816bbb | ||
|
|
dfded1122b | ||
|
|
8201318bd7 | ||
|
|
b31aee7166 | ||
|
|
06b43fa33f | ||
|
|
fa9235562a | ||
|
|
92ba34833b | ||
|
|
83c1afc186 |
11
README.md
11
README.md
@@ -1,19 +1,12 @@
|
||||
## 聚合DNS管理系统
|
||||
|
||||
聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析,目前已支持的域名平台有:
|
||||
|
||||
- 阿里云
|
||||
- 腾讯云
|
||||
- 华为云
|
||||
- 西部数码
|
||||
- DNSLA
|
||||
- CloudFlare
|
||||
聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析,目前已支持的域名平台有:阿里云、腾讯云、华为云、百度云、西部数码、火山引擎、DNSLA、CloudFlare、Namesilo
|
||||
|
||||
### 功能特性
|
||||
|
||||
- 多用户管理,可为每个用户可分配不同的域名解析权限
|
||||
- 提供API接口,可获取域名单独的登录链接,方便各种IDC系统对接
|
||||
- 容灾切换功能,支持ping、tcp、http(s)检测协议并自动暂停/修改域名解析,并支持邮件、微信公众号通知
|
||||
- 容灾切换功能,支持ping、tcp、http(s)检测协议并自动暂停/修改域名解析,并支持邮件、微信公众号、TG群机器人通知
|
||||
- CF优选IP功能,支持获取最新的Cloudflare优选IP,并自动更新到解析记录
|
||||
- SSL证书申请与自动部署功能,支持从Let's Encrypt等渠道申请SSL证书,并自动部署到各种面板、云服务商、服务器等
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ function get_curl($url, $post = 0, $referer = 0, $cookie = 0, $header = 0, $ua =
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
$httpheader[] = "Accept: */*";
|
||||
@@ -165,6 +166,11 @@ function getSubstr($str, $leftStr, $rightStr)
|
||||
}
|
||||
}
|
||||
|
||||
function arrays_are_equal($array1, $array2)
|
||||
{
|
||||
return empty(array_diff($array1, $array2)) && empty(array_diff($array2, $array1));
|
||||
}
|
||||
|
||||
function checkRefererHost()
|
||||
{
|
||||
if (!Request::header('referer')) {
|
||||
@@ -407,26 +413,7 @@ function curl_client($url, $data = null, $referer = null, $cookie = null, $heade
|
||||
}
|
||||
|
||||
if ($proxy) {
|
||||
$proxy_server = config_get('proxy_server');
|
||||
$proxy_port = intval(config_get('proxy_port'));
|
||||
$proxy_userpwd = config_get('proxy_user') . ':' . config_get('proxy_pwd');
|
||||
$proxy_type = config_get('proxy_type');
|
||||
if ($proxy_type == 'https') {
|
||||
$proxy_type = CURLPROXY_HTTPS;
|
||||
} elseif ($proxy_type == 'sock4') {
|
||||
$proxy_type = CURLPROXY_SOCKS4;
|
||||
} elseif ($proxy_type == 'sock5') {
|
||||
$proxy_type = CURLPROXY_SOCKS5;
|
||||
} else {
|
||||
$proxy_type = CURLPROXY_HTTP;
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
|
||||
curl_setopt($ch, CURLOPT_PROXY, $proxy_server);
|
||||
curl_setopt($ch, CURLOPT_PROXYPORT, $proxy_port);
|
||||
if ($proxy_userpwd != ':') {
|
||||
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type);
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
|
||||
$ret = curl_exec($ch);
|
||||
@@ -442,4 +429,31 @@ function curl_client($url, $data = null, $referer = null, $cookie = null, $heade
|
||||
$header = substr($ret, 0, $headerSize);
|
||||
$body = substr($ret, $headerSize);
|
||||
return ['code' => $httpCode, 'redirect_url' => $redirect_url, 'header' => $header, 'body' => $body];
|
||||
}
|
||||
|
||||
function curl_set_proxy(&$ch)
|
||||
{
|
||||
$proxy_server = config_get('proxy_server');
|
||||
$proxy_port = intval(config_get('proxy_port'));
|
||||
$proxy_userpwd = config_get('proxy_user') . ':' . config_get('proxy_pwd');
|
||||
$proxy_type = config_get('proxy_type');
|
||||
if (empty($proxy_server) || empty($proxy_port)) {
|
||||
return;
|
||||
}
|
||||
if ($proxy_type == 'https') {
|
||||
$proxy_type = CURLPROXY_HTTPS;
|
||||
} elseif ($proxy_type == 'sock4') {
|
||||
$proxy_type = CURLPROXY_SOCKS4;
|
||||
} elseif ($proxy_type == 'sock5') {
|
||||
$proxy_type = CURLPROXY_SOCKS5;
|
||||
} else {
|
||||
$proxy_type = CURLPROXY_HTTP;
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
|
||||
curl_setopt($ch, CURLOPT_PROXY, $proxy_server);
|
||||
curl_setopt($ch, CURLOPT_PROXYPORT, $proxy_port);
|
||||
if ($proxy_userpwd != ':') {
|
||||
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type);
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class Auth extends BaseController
|
||||
$user = Db::name('user')->where('username', $username)->find();
|
||||
if ($user && password_verify($password, $user['password'])) {
|
||||
if ($user['status'] == 0) return json(['code' => -1, 'msg' => '此用户已被封禁', 'vcode' => 1]);
|
||||
if ($user['totp_open'] == 1 && !empty($user['totp_secret'])) {
|
||||
if (isset($user['totp_open']) && $user['totp_open'] == 1 && !empty($user['totp_secret'])) {
|
||||
session('pre_login_user', $user['id']);
|
||||
if (file_exists($login_limit_file)) {
|
||||
unlink($login_limit_file);
|
||||
@@ -53,7 +53,9 @@ class Auth extends BaseController
|
||||
} else {
|
||||
if ($user) {
|
||||
Db::name('log')->insert(['uid' => $user['id'], 'action' => '登录失败', 'data' => 'IP:' . $this->clientip, 'addtime' => date("Y-m-d H:i:s")]);
|
||||
if ($user['totp_open'] == 1 && !empty($user['totp_secret'])) $login_limit_count = 10;
|
||||
if (isset($user['totp_open']) && $user['totp_open'] == 1 && !empty($user['totp_secret'])) {
|
||||
return json(['code' => -1, 'msg' => '用户名或密码错误', 'vcode' => 1]);
|
||||
}
|
||||
}
|
||||
if (!file_exists($login_limit_file)) {
|
||||
$login_limit = ['count' => 0, 'time' => 0];
|
||||
|
||||
@@ -317,6 +317,72 @@ class Cert extends BaseController
|
||||
Db::name('cert_domain')->insertAll($domainList);
|
||||
Db::commit();
|
||||
return json(['code' => 0, 'msg' => '修改证书订单成功!']);
|
||||
} elseif ($action == 'import') {
|
||||
$fullchain = input('post.fullchain', null, 'trim');
|
||||
$privatekey = input('post.privatekey', null, 'trim');
|
||||
if (!openssl_x509_read($fullchain)) return json(['code' => -1, 'msg' => '证书内容填写错误']);
|
||||
if (!openssl_get_privatekey($privatekey)) return json(['code' => -1, 'msg' => '私钥内容填写错误']);
|
||||
if (!openssl_x509_check_private_key($fullchain, $privatekey)) return json(['code' => -1, 'msg' => 'SSL证书与私钥不匹配']);
|
||||
$certInfo = openssl_x509_parse($fullchain, true);
|
||||
if (!$certInfo || !isset($certInfo['extensions']['subjectAltName'])) return json(['code' => -1, 'msg' => '证书内容解析失败']);
|
||||
|
||||
$domains = [];
|
||||
$subjectAltName = explode(',', $certInfo['extensions']['subjectAltName']);
|
||||
foreach ($subjectAltName as $domain) {
|
||||
$domain = trim($domain);
|
||||
if (strpos($domain, 'DNS:') === 0) $domain = substr($domain, 4);
|
||||
if (!empty($domain)) {
|
||||
$domains[] = $domain;
|
||||
}
|
||||
}
|
||||
$domains = array_unique($domains);
|
||||
if (empty($domains)) return json(['code' => -1, 'msg' => '证书绑定域名不能为空']);
|
||||
$issuetime = date('Y-m-d H:i:s', $certInfo['validFrom_time_t']);
|
||||
$expiretime = date('Y-m-d H:i:s', $certInfo['validTo_time_t']);
|
||||
$issuer = $certInfo['issuer']['CN'];
|
||||
|
||||
$order_ids = Db::name('cert_order')->where('issuetime', $issuetime)->column('id');
|
||||
if (!empty($order_ids)) {
|
||||
foreach ($order_ids as $order_id) {
|
||||
$domains2 = Db::name('cert_domain')->where('oid', $order_id)->column('domain');
|
||||
if (arrays_are_equal($domains2, $domains)) {
|
||||
return json(['code' => -1, 'msg' => '该证书已存在,无需重复添加']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$order = [
|
||||
'aid' => input('post.aid/d'),
|
||||
'keytype' => input('post.keytype'),
|
||||
'keysize' => input('post.keysize'),
|
||||
'addtime' => date('Y-m-d H:i:s'),
|
||||
'updatetime' => date('Y-m-d H:i:s'),
|
||||
'issuetime' => $issuetime,
|
||||
'expiretime' => $expiretime,
|
||||
'issuer' => $issuer,
|
||||
'status' => 3,
|
||||
'fullchain' => $fullchain,
|
||||
'privatekey' => $privatekey,
|
||||
];
|
||||
if (empty($order['aid']) || empty($order['keytype']) || empty($order['keysize'])) return json(['code' => -1, 'msg' => '必填参数不能为空']);
|
||||
|
||||
$res = $this->check_order($order, $domains);
|
||||
if (is_array($res)) return json($res);
|
||||
|
||||
Db::startTrans();
|
||||
$id = Db::name('cert_order')->insertGetId($order);
|
||||
$domainList = [];
|
||||
$i = 1;
|
||||
foreach ($domains as $domain) {
|
||||
$domainList[] = [
|
||||
'oid' => $id,
|
||||
'domain' => $domain,
|
||||
'sort' => $i++,
|
||||
];
|
||||
}
|
||||
Db::name('cert_domain')->insertAll($domainList);
|
||||
Db::commit();
|
||||
return json(['code' => 0, 'msg' => '导入证书成功!']);
|
||||
} elseif ($action == 'del') {
|
||||
$id = input('post.id/d');
|
||||
$dcount = DB::name('cert_deploy')->where('oid', $id)->count();
|
||||
@@ -368,13 +434,18 @@ class Cert extends BaseController
|
||||
$max_domains = CertHelper::$cert_config[$account['type']]['max_domains'];
|
||||
$wildcard = CertHelper::$cert_config[$account['type']]['wildcard'];
|
||||
$cname = CertHelper::$cert_config[$account['type']]['cname'];
|
||||
if (count($domains) > $max_domains) return ['code' => -1, 'msg' => '域名数量不能超过'.$max_domains.'个'];
|
||||
if (count($domains) > $max_domains) {
|
||||
if (!(count($domains) == 2 && $max_domains == 1 && ltrim($domains[0], 'www.') == ltrim($domains[1], 'www.'))) {
|
||||
return ['code' => -1, 'msg' => '域名数量不能超过'.$max_domains.'个'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach($domains as $domain){
|
||||
if(!$wildcard && strpos($domain, '*') !== false) return ['code' => -1, 'msg' => '该证书账户类型不支持泛域名'];
|
||||
$mainDomain = getMainDomain($domain);
|
||||
$drow = Db::name('domain')->where('name', $mainDomain)->find();
|
||||
if (!$drow) {
|
||||
if (substr($domain, 0, 2) == '*.') $domain = substr($domain, 2);
|
||||
if (!$cname || !Db::name('cert_cname')->where('domain', $domain)->where('status', 1)->find()) {
|
||||
return ['code' => -1, 'msg' => '域名'.$domain.'未在本系统添加'];
|
||||
}
|
||||
@@ -437,6 +508,20 @@ class Cert extends BaseController
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
public function order_import()
|
||||
{
|
||||
if (!checkPermission(2)) return $this->alert('error', '无权限');
|
||||
$accounts = [];
|
||||
foreach (Db::name('cert_account')->where('deploy', 0)->select() as $row) {
|
||||
$accounts[$row['id']] = ['name'=>$row['id'].'_'.CertHelper::$cert_config[$row['type']]['name'], 'type'=>$row['type']];
|
||||
if (!empty($row['remark'])) {
|
||||
$accounts[$row['id']]['name'] .= '(' . $row['remark'] . ')';
|
||||
}
|
||||
}
|
||||
View::assign('accounts', $accounts);
|
||||
return View::fetch();
|
||||
}
|
||||
|
||||
|
||||
public function deploytask()
|
||||
{
|
||||
|
||||
@@ -57,6 +57,7 @@ class Domain extends BaseController
|
||||
$sk = input('post.sk', null, 'trim');
|
||||
$ext = input('post.ext', null, 'trim');
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
$proxy = input('post.proxy/d', 0);
|
||||
if (empty($ak) || empty($sk)) return json(['code' => -1, 'msg' => 'AccessKey和SecretKey不能为空']);
|
||||
if (Db::name('account')->where('type', $type)->where('ak', $ak)->find()) {
|
||||
return json(['code' => -1, 'msg' => '域名账户已存在']);
|
||||
@@ -67,6 +68,7 @@ class Domain extends BaseController
|
||||
'ak' => $ak,
|
||||
'sk' => $sk,
|
||||
'ext' => $ext,
|
||||
'proxy' => $proxy,
|
||||
'remark' => $remark,
|
||||
'addtime' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
@@ -92,6 +94,7 @@ class Domain extends BaseController
|
||||
$sk = input('post.sk', null, 'trim');
|
||||
$ext = input('post.ext', null, 'trim');
|
||||
$remark = input('post.remark', null, 'trim');
|
||||
$proxy = input('post.proxy/d', 0);
|
||||
if (empty($ak) || empty($sk)) return json(['code' => -1, 'msg' => 'AccessKey和SecretKey不能为空']);
|
||||
if (Db::name('account')->where('type', $type)->where('ak', $ak)->where('id', '<>', $id)->find()) {
|
||||
return json(['code' => -1, 'msg' => '域名账户已存在']);
|
||||
@@ -102,6 +105,7 @@ class Domain extends BaseController
|
||||
'ak' => $ak,
|
||||
'sk' => $sk,
|
||||
'ext' => $ext,
|
||||
'proxy' => $proxy,
|
||||
'remark' => $remark,
|
||||
]);
|
||||
$dns = DnsHelper::getModel($id);
|
||||
@@ -150,6 +154,26 @@ class Domain extends BaseController
|
||||
return view();
|
||||
}
|
||||
|
||||
public function domain_add()
|
||||
{
|
||||
if (!checkPermission(2)) return $this->alert('error', '无权限');
|
||||
$list = Db::name('account')->select();
|
||||
$accounts = [];
|
||||
$types = [];
|
||||
foreach ($list as $row) {
|
||||
$accounts[$row['id']] = $row['id'] . '_' . DnsHelper::$dns_config[$row['type']]['name'];
|
||||
if (!array_key_exists($row['type'], $types)) {
|
||||
$types[$row['type']] = DnsHelper::$dns_config[$row['type']]['name'];
|
||||
}
|
||||
if (!empty($row['remark'])) {
|
||||
$accounts[$row['id']] .= '(' . $row['remark'] . ')';
|
||||
}
|
||||
}
|
||||
View::assign('accounts', $accounts);
|
||||
View::assign('types', $types);
|
||||
return view();
|
||||
}
|
||||
|
||||
public function domain_data()
|
||||
{
|
||||
if (!checkPermission(1)) return json(['total' => 0, 'rows' => []]);
|
||||
@@ -230,6 +254,25 @@ class Domain extends BaseController
|
||||
Db::name('dmtask')->where('did', $id)->delete();
|
||||
Db::name('optimizeip')->where('did', $id)->delete();
|
||||
return json(['code' => 0]);
|
||||
} elseif ($act == 'batchadd') {
|
||||
if (!checkPermission(2)) return $this->alert('error', '无权限');
|
||||
$aid = input('post.aid/d');
|
||||
$domains = input('post.domains');
|
||||
if (empty($domains)) return json(['code' => -1, 'msg' => '参数不能为空']);
|
||||
$data = [];
|
||||
foreach ($domains as $row) {
|
||||
$data[] = [
|
||||
'aid' => $aid,
|
||||
'name' => $row['name'],
|
||||
'thirdid' => $row['id'],
|
||||
'addtime' => date('Y-m-d H:i:s'),
|
||||
'is_hide' => 0,
|
||||
'is_sso' => 1,
|
||||
'recordcount' => $row['recordcount'],
|
||||
];
|
||||
}
|
||||
Db::name('domain')->insertAll($data);
|
||||
return json(['code' => 0, 'msg' => '成功添加' . count($data) . '个域名!']);
|
||||
}
|
||||
return json(['code' => -3]);
|
||||
}
|
||||
@@ -245,13 +288,10 @@ class Domain extends BaseController
|
||||
$result = $dns->getDomainList($kw, $page, $pagesize);
|
||||
if (!$result) return json(['code' => -1, 'msg' => '获取域名列表失败,' . $dns->getError()]);
|
||||
|
||||
$newlist = [];
|
||||
foreach ($result['list'] as $row) {
|
||||
if (!Db::name('domain')->where('aid', $aid)->where('name', $row['Domain'])->find()) {
|
||||
$newlist[] = $row;
|
||||
}
|
||||
foreach ($result['list'] as &$row) {
|
||||
$row['disabled'] = Db::name('domain')->where('aid', $aid)->where('name', $row['Domain'])->find() != null;
|
||||
}
|
||||
return json(['code' => 0, 'data' => ['total' => $result['total'], 'list' => $newlist]]);
|
||||
return json(['code' => 0, 'data' => ['total' => $result['total'], 'list' => $result['list']]]);
|
||||
}
|
||||
|
||||
//获取解析线路和最小TTL
|
||||
|
||||
@@ -76,6 +76,20 @@ class System extends BaseController
|
||||
}
|
||||
}
|
||||
|
||||
public function webhooktest()
|
||||
{
|
||||
if (!checkPermission(2)) return $this->alert('error', '无权限');
|
||||
$webhook_url = config_get('webhook_url');
|
||||
if (empty($webhook_url)) return json(['code' => -1, 'msg' => '请先保存设置']);
|
||||
$content = "这是一封测试消息!\n来自:" . $this->request->root(true);
|
||||
$result = \app\utils\MsgNotice::send_webhook('消息发送测试', $content);
|
||||
if ($result === true) {
|
||||
return json(['code' => 0, 'msg' => '消息发送成功!']);
|
||||
} else {
|
||||
return json(['code' => -1, 'msg' => '消息发送失败!' . $result]);
|
||||
}
|
||||
}
|
||||
|
||||
public function proxytest()
|
||||
{
|
||||
if (!checkPermission(2)) return $this->alert('error', '无权限');
|
||||
|
||||
@@ -1922,4 +1922,7 @@ com.za
|
||||
com.zw
|
||||
mil.cn
|
||||
edu.kg
|
||||
edu.cn
|
||||
edu.cn
|
||||
eu.org
|
||||
us.kg
|
||||
ggff.net
|
||||
@@ -154,6 +154,15 @@ class CertHelper
|
||||
'placeholder' => '申请证书时填写的邮箱',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
]
|
||||
],
|
||||
'aliyun' => [
|
||||
@@ -195,6 +204,15 @@ class CertHelper
|
||||
'placeholder' => '申请联系人的邮箱地址',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
]
|
||||
],
|
||||
'ucloud' => [
|
||||
|
||||
@@ -259,16 +259,6 @@ class DeployHelper
|
||||
'note' => '需要先<a href="https://goedge.cloud/docs/API/Settings.md" target="_blank" rel="noreferrer">开启HTTP API端口</a>',
|
||||
'tasknote' => '系统会根据关联SSL证书的域名,自动更新对应证书',
|
||||
'inputs' => [
|
||||
'systype' => [
|
||||
'name' => '系统类型',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => 'GoEdge',
|
||||
'1' => 'FlexCDN',
|
||||
],
|
||||
'value' => '0',
|
||||
'required' => true,
|
||||
],
|
||||
'url' => [
|
||||
'name' => 'HTTP API地址',
|
||||
'type' => 'input',
|
||||
@@ -298,6 +288,16 @@ class DeployHelper
|
||||
'value' => 'user',
|
||||
'required' => true,
|
||||
],
|
||||
'systype' => [
|
||||
'name' => '系统类型',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => 'GoEdge',
|
||||
'1' => 'FlexCDN',
|
||||
],
|
||||
'value' => '0',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
@@ -342,6 +342,63 @@ class DeployHelper
|
||||
],
|
||||
'taskinputs' => [],
|
||||
],
|
||||
'mwpanel' => [
|
||||
'name' => 'MW面板',
|
||||
'class' => 1,
|
||||
'icon' => 'mwpanel.ico',
|
||||
'note' => null,
|
||||
'tasknote' => '',
|
||||
'inputs' => [
|
||||
'url' => [
|
||||
'name' => '面板地址',
|
||||
'type' => 'input',
|
||||
'placeholder' => 'MW面板地址',
|
||||
'note' => '填写规则如:http://192.168.1.100:8888 ,不要带其他后缀',
|
||||
'required' => true,
|
||||
],
|
||||
'appid' => [
|
||||
'name' => '应用ID',
|
||||
'type' => 'input',
|
||||
'placeholder' => 'MW面板设置->API接口',
|
||||
'required' => true,
|
||||
],
|
||||
'appsecret' => [
|
||||
'name' => '应用密钥',
|
||||
'type' => 'input',
|
||||
'placeholder' => '面板设置->API接口',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'type' => [
|
||||
'name' => '部署类型',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => 'MW面板站点的证书',
|
||||
'1' => 'MW面板本身的证书',
|
||||
],
|
||||
'value' => '0',
|
||||
'required' => true,
|
||||
],
|
||||
'sites' => [
|
||||
'name' => '网站名称列表',
|
||||
'type' => 'textarea',
|
||||
'placeholder' => '填写要部署证书的网站名称,每行一个',
|
||||
'note' => '网站名称,即为网站创建时绑定的第一个域名',
|
||||
'show' => 'type==0',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'aliyun' => [
|
||||
'name' => '阿里云',
|
||||
'class' => 2,
|
||||
@@ -361,6 +418,15 @@ class DeployHelper
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'product' => [
|
||||
@@ -499,6 +565,15 @@ class DeployHelper
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'product' => [
|
||||
@@ -592,7 +667,7 @@ class DeployHelper
|
||||
'name' => '实例ID',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'show' => 'product==\'lighthouse\'',
|
||||
'show' => 'product==\'lighthouse\'||product==\'ddos\'',
|
||||
'required' => true,
|
||||
],
|
||||
'domain' => [
|
||||
@@ -600,6 +675,7 @@ class DeployHelper
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'show' => 'product!=\'clb\'&&product!=\'tke\'',
|
||||
'note' => 'CDN、EO、WAF多个域名可用,隔开,其他只能填写1个域名',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
@@ -622,6 +698,15 @@ class DeployHelper
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'product' => [
|
||||
@@ -714,6 +799,15 @@ class DeployHelper
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'product' => [
|
||||
@@ -722,10 +816,18 @@ class DeployHelper
|
||||
'options' => [
|
||||
['value'=>'cdn', 'label'=>'CDN'],
|
||||
['value'=>'oss', 'label'=>'OSS'],
|
||||
['value'=>'pili', 'label'=>'视频直播'],
|
||||
],
|
||||
'value' => 'cdn',
|
||||
'required' => true,
|
||||
],
|
||||
'pili_hub' => [
|
||||
'name' => '直播空间名称',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'show' => 'product==\'pili\'',
|
||||
'required' => true,
|
||||
],
|
||||
'domain' => [
|
||||
'name' => '绑定的域名',
|
||||
'type' => 'input',
|
||||
@@ -752,6 +854,15 @@ class DeployHelper
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'domain' => [
|
||||
@@ -780,6 +891,15 @@ class DeployHelper
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'domain' => [
|
||||
@@ -808,12 +928,87 @@ class DeployHelper
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'product' => [
|
||||
'name' => '要部署的产品',
|
||||
'type' => 'select',
|
||||
'options' => [
|
||||
['value'=>'cdn', 'label'=>'内容分发网络CDN'],
|
||||
['value'=>'dcdn', 'label'=>'全站加速DCDN'],
|
||||
['value'=>'clb', 'label'=>'负载均衡CLB'],
|
||||
['value'=>'tos', 'label'=>'对象存储TOS'],
|
||||
['value'=>'live', 'label'=>'视频直播'],
|
||||
['value'=>'imagex', 'label'=>'veImageX'],
|
||||
],
|
||||
'value' => 'cdn',
|
||||
'required' => true,
|
||||
],
|
||||
'bucket_domain' => [
|
||||
'name' => 'Bucket域名',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'show' => 'product==\'tos\'',
|
||||
'required' => true,
|
||||
],
|
||||
'domain' => [
|
||||
'name' => '绑定的域名',
|
||||
'type' => 'input',
|
||||
'placeholder' => '多个域名可使用英文逗号分隔',
|
||||
'placeholder' => '多个域名可使用,分隔',
|
||||
'show' => 'product!=\'clb\'',
|
||||
'required' => true,
|
||||
],
|
||||
'listener_id' => [
|
||||
'name' => '监听器ID',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'show' => 'product==\'clb\'',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'west' => [
|
||||
'name' => '西部数码',
|
||||
'class' => 2,
|
||||
'icon' => 'west.ico',
|
||||
'note' => '支持部署到西部数码虚拟主机',
|
||||
'inputs' => [
|
||||
'username' => [
|
||||
'name' => '用户名',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'api_password' => [
|
||||
'name' => 'API密码',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'sitename' => [
|
||||
'name' => 'FTP账号',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
@@ -857,6 +1052,48 @@ class DeployHelper
|
||||
],
|
||||
],
|
||||
],
|
||||
'ctyun' => [
|
||||
'name' => '天翼云',
|
||||
'class' => 2,
|
||||
'icon' => 'ctyun.ico',
|
||||
'note' => '支持部署到天翼云CDN',
|
||||
'inputs' => [
|
||||
'AccessKeyId' => [
|
||||
'name' => 'AccessKeyId',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'SecretAccessKey' => [
|
||||
'name' => 'SecretAccessKey',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'product' => [
|
||||
'name' => '产品',
|
||||
'type' => 'hidden',
|
||||
'value' => 'cdn',
|
||||
],
|
||||
'domain' => [
|
||||
'name' => 'CDN域名',
|
||||
'type' => 'input',
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
'allwaf' => [
|
||||
'name' => 'AllWAF',
|
||||
'class' => 2,
|
||||
@@ -906,6 +1143,15 @@ class DeployHelper
|
||||
'placeholder' => '',
|
||||
'required' => true,
|
||||
],
|
||||
'proxy' => [
|
||||
'name' => '使用代理服务器',
|
||||
'type' => 'radio',
|
||||
'options' => [
|
||||
'0' => '否',
|
||||
'1' => '是',
|
||||
],
|
||||
'value' => '0'
|
||||
],
|
||||
],
|
||||
'taskinputs' => [
|
||||
'product' => [
|
||||
@@ -1266,7 +1512,7 @@ class DeployHelper
|
||||
];
|
||||
|
||||
public static $class_config = [
|
||||
1 => '自建面板',
|
||||
1 => '自建系统',
|
||||
2 => '云服务商',
|
||||
3 => '服务器',
|
||||
];
|
||||
|
||||
@@ -227,7 +227,7 @@ class ACMECert extends ACMEv2
|
||||
|
||||
public function authOrder($order)
|
||||
{
|
||||
if ($order['status'] != 'ready' && empty($order['challenges'])) {
|
||||
if ($order['status'] != 'pending' && $order['status'] != 'ready' && empty($order['challenges'])) {
|
||||
throw new Exception('No challenges available');
|
||||
}
|
||||
|
||||
|
||||
@@ -308,26 +308,7 @@ class ACMEv2
|
||||
));
|
||||
|
||||
if ($this->proxy) {
|
||||
$proxy_server = config_get('proxy_server');
|
||||
$proxy_port = intval(config_get('proxy_port'));
|
||||
$proxy_userpwd = config_get('proxy_user').':'.config_get('proxy_pwd');
|
||||
$proxy_type = config_get('proxy_type');
|
||||
if ($proxy_type == 'https') {
|
||||
$proxy_type = CURLPROXY_HTTPS;
|
||||
} elseif ($proxy_type == 'sock4') {
|
||||
$proxy_type = CURLPROXY_SOCKS4;
|
||||
} elseif ($proxy_type == 'sock5') {
|
||||
$proxy_type = CURLPROXY_SOCKS5;
|
||||
} else {
|
||||
$proxy_type = CURLPROXY_HTTP;
|
||||
}
|
||||
curl_setopt($this->ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
|
||||
curl_setopt($this->ch, CURLOPT_PROXY, $proxy_server);
|
||||
curl_setopt($this->ch, CURLOPT_PROXYPORT, $proxy_port);
|
||||
if ($proxy_userpwd != ':') {
|
||||
curl_setopt($this->ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
|
||||
}
|
||||
curl_setopt($this->ch, CURLOPT_PROXYTYPE, $proxy_type);
|
||||
curl_set_proxy($this->ch);
|
||||
}
|
||||
|
||||
$took = microtime(true);
|
||||
|
||||
@@ -20,7 +20,8 @@ class aliyun implements CertInterface
|
||||
{
|
||||
$this->AccessKeyId = $config['AccessKeyId'];
|
||||
$this->AccessKeySecret = $config['AccessKeySecret'];
|
||||
$this->client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $this->Endpoint, $this->Version);
|
||||
$proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $this->Endpoint, $this->Version, $proxy);
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@ class huoshan implements CertInterface
|
||||
{
|
||||
$this->AccessKeyId = $config['AccessKeyId'];
|
||||
$this->SecretAccessKey = $config['SecretAccessKey'];
|
||||
$this->client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, $this->endpoint, $this->service, $this->version, $this->region);
|
||||
$proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, $this->endpoint, $this->service, $this->version, $this->region, $proxy);
|
||||
}
|
||||
|
||||
public function register()
|
||||
|
||||
@@ -21,7 +21,8 @@ class tencent implements CertInterface
|
||||
{
|
||||
$this->SecretId = $config['SecretId'];
|
||||
$this->SecretKey = $config['SecretKey'];
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, $this->endpoint, $this->service, $this->version);
|
||||
$proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, $this->endpoint, $this->service, $this->version, null, $proxy);
|
||||
$this->email = $config['email'];
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@ class AWS
|
||||
private $version;
|
||||
private $region;
|
||||
private $etag;
|
||||
private $proxy = false;
|
||||
|
||||
public function __construct($AccessKeyId, $SecretAccessKey, $endpoint, $service, $version, $region)
|
||||
public function __construct($AccessKeyId, $SecretAccessKey, $endpoint, $service, $version, $region, $proxy = false)
|
||||
{
|
||||
$this->AccessKeyId = $AccessKeyId;
|
||||
$this->SecretAccessKey = $SecretAccessKey;
|
||||
@@ -25,6 +26,7 @@ class AWS
|
||||
$this->service = $service;
|
||||
$this->version = $version;
|
||||
$this->region = $region;
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,6 +144,7 @@ class AWS
|
||||
}
|
||||
|
||||
$path = '/' . $this->version . $path;
|
||||
$body = '';
|
||||
if ($method == 'GET' || $method == 'DELETE') {
|
||||
$query = $params;
|
||||
} else {
|
||||
@@ -179,7 +182,7 @@ class AWS
|
||||
|
||||
// step 1: build canonical request string
|
||||
$httpRequestMethod = $method;
|
||||
$canonicalUri = $path;
|
||||
$canonicalUri = $this->getCanonicalURI($path);
|
||||
$canonicalQueryString = $this->getCanonicalQueryString($query);
|
||||
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
|
||||
$hashedRequestPayload = hash("sha256", $body);
|
||||
@@ -219,6 +222,17 @@ class AWS
|
||||
$replace = ['%20', '%2A', '~'];
|
||||
return str_replace($search, $replace, urlencode($str));
|
||||
}
|
||||
|
||||
private function getCanonicalURI($path)
|
||||
{
|
||||
if (empty($path)) return '/';
|
||||
$pattens = explode('/', $path);
|
||||
$pattens = array_map(function ($item) {
|
||||
return $this->escape($item);
|
||||
}, $pattens);
|
||||
$canonicalURI = implode('/', $pattens);
|
||||
return $canonicalURI;
|
||||
}
|
||||
|
||||
private function getCanonicalQueryString($parameters)
|
||||
{
|
||||
@@ -252,6 +266,9 @@ class AWS
|
||||
private function curl($method, $url, $body, $header, $xml = false, $etag = false)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
@@ -13,13 +13,15 @@ class Aliyun
|
||||
private $AccessKeySecret;
|
||||
private $Endpoint;
|
||||
private $Version;
|
||||
private $proxy = false;
|
||||
|
||||
public function __construct($AccessKeyId, $AccessKeySecret, $Endpoint, $Version)
|
||||
public function __construct($AccessKeyId, $AccessKeySecret, $Endpoint, $Version, $proxy = false)
|
||||
{
|
||||
$this->AccessKeyId = $AccessKeyId;
|
||||
$this->AccessKeySecret = $AccessKeySecret;
|
||||
$this->Endpoint = $Endpoint;
|
||||
$this->Version = $Version;
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,6 +47,9 @@ class Aliyun
|
||||
$url .= '?' . http_build_query($data);
|
||||
}
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
@@ -13,13 +13,15 @@ class AliyunNew
|
||||
private $AccessKeySecret;
|
||||
private $Endpoint;
|
||||
private $Version;
|
||||
private $proxy = false;
|
||||
|
||||
public function __construct($AccessKeyId, $AccessKeySecret, $Endpoint, $Version)
|
||||
public function __construct($AccessKeyId, $AccessKeySecret, $Endpoint, $Version, $proxy = false)
|
||||
{
|
||||
$this->AccessKeyId = $AccessKeyId;
|
||||
$this->AccessKeySecret = $AccessKeySecret;
|
||||
$this->Endpoint = $Endpoint;
|
||||
$this->Version = $Version;
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +76,7 @@ class AliyunNew
|
||||
|
||||
// step 1: build canonical request string
|
||||
$httpRequestMethod = $method;
|
||||
$canonicalUri = $path;
|
||||
$canonicalUri = $this->getCanonicalURI($path);
|
||||
$canonicalQueryString = $this->getCanonicalQueryString($query);
|
||||
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
|
||||
$hashedRequestPayload = hash("sha256", $body);
|
||||
@@ -106,6 +108,17 @@ class AliyunNew
|
||||
return str_replace($search, $replace, urlencode($str));
|
||||
}
|
||||
|
||||
private function getCanonicalURI($path)
|
||||
{
|
||||
if (empty($path)) return '/';
|
||||
$pattens = explode('/', $path);
|
||||
$pattens = array_map(function ($item) {
|
||||
return $this->escape($item);
|
||||
}, $pattens);
|
||||
$canonicalURI = implode('/', $pattens);
|
||||
return $canonicalURI;
|
||||
}
|
||||
|
||||
private function getCanonicalQueryString($parameters)
|
||||
{
|
||||
if (empty($parameters)) return '';
|
||||
@@ -138,6 +151,9 @@ class AliyunNew
|
||||
private function curl($method, $url, $body, $header)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
@@ -9,12 +9,14 @@ class AliyunOSS
|
||||
private $AccessKeyId;
|
||||
private $AccessKeySecret;
|
||||
private $Endpoint;
|
||||
private $proxy = false;
|
||||
|
||||
public function __construct($AccessKeyId, $AccessKeySecret, $Endpoint)
|
||||
public function __construct($AccessKeyId, $AccessKeySecret, $Endpoint, $proxy = false)
|
||||
{
|
||||
$this->AccessKeyId = $AccessKeyId;
|
||||
$this->AccessKeySecret = $AccessKeySecret;
|
||||
$this->Endpoint = $Endpoint;
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
public function addBucketCnameCert($bucket, $domain, $cert_id)
|
||||
@@ -101,6 +103,9 @@ class AliyunOSS
|
||||
private function curl($method, $url, $body, $header)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
@@ -12,12 +12,14 @@ class BaiduCloud
|
||||
private $AccessKeyId;
|
||||
private $SecretAccessKey;
|
||||
private $endpoint;
|
||||
private $proxy = false;
|
||||
|
||||
public function __construct($AccessKeyId, $SecretAccessKey, $endpoint)
|
||||
public function __construct($AccessKeyId, $SecretAccessKey, $endpoint, $proxy = false)
|
||||
{
|
||||
$this->AccessKeyId = $AccessKeyId;
|
||||
$this->SecretAccessKey = $SecretAccessKey;
|
||||
$this->endpoint = $endpoint;
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,6 +142,9 @@ class BaiduCloud
|
||||
private function curl($method, $url, $body, $header)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
163
app/lib/client/Ctyun.php
Normal file
163
app/lib/client/Ctyun.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
|
||||
namespace app\lib\client;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* 天翼云
|
||||
*/
|
||||
class Ctyun
|
||||
{
|
||||
private $AccessKeyId;
|
||||
private $SecretAccessKey;
|
||||
private $endpoint;
|
||||
private $proxy = false;
|
||||
|
||||
public function __construct($AccessKeyId, $SecretAccessKey, $endpoint, $proxy = false)
|
||||
{
|
||||
$this->AccessKeyId = $AccessKeyId;
|
||||
$this->SecretAccessKey = $SecretAccessKey;
|
||||
$this->endpoint = $endpoint;
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method 请求方法
|
||||
* @param string $path 请求路径
|
||||
* @param array|null $query 请求参数
|
||||
* @param array|null $params 请求体
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function request($method, $path, $query = null, $params = null)
|
||||
{
|
||||
if (!empty($query)) {
|
||||
$query = array_filter($query, function ($a) { return $a !== null;});
|
||||
}
|
||||
if (!empty($params)) {
|
||||
$params = array_filter($params, function ($a) { return $a !== null;});
|
||||
}
|
||||
|
||||
$time = time();
|
||||
$date = date("Ymd\THis\Z", $time);
|
||||
$body = !empty($params) ? json_encode($params) : '';
|
||||
$headers = [
|
||||
'Host' => $this->endpoint,
|
||||
'Eop-date' => $date,
|
||||
'ctyun-eop-request-id' => getSid(),
|
||||
];
|
||||
if ($body) {
|
||||
$headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
$authorization = $this->generateSign($query, $headers, $body, $date);
|
||||
$headers['Eop-Authorization'] = $authorization;
|
||||
|
||||
$url = 'https://' . $this->endpoint . $path;
|
||||
if (!empty($query)) {
|
||||
$url .= '?' . http_build_query($query);
|
||||
}
|
||||
$header = [];
|
||||
foreach ($headers as $key => $value) {
|
||||
$header[] = $key . ': ' . $value;
|
||||
}
|
||||
return $this->curl($method, $url, $body, $header);
|
||||
}
|
||||
|
||||
private function generateSign($query, $headers, $body, $date)
|
||||
{
|
||||
// step 1: build canonical request string
|
||||
$canonicalQueryString = $this->getCanonicalQueryString($query);
|
||||
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
|
||||
$hashedRequestPayload = hash("sha256", $body);
|
||||
|
||||
// step 2: build string to sign
|
||||
$stringToSign = $canonicalHeaders . "\n"
|
||||
. $canonicalQueryString . "\n"
|
||||
. $hashedRequestPayload;
|
||||
|
||||
// step 3: sign string
|
||||
$ktime = hash_hmac("sha256", $date, $this->SecretAccessKey, true);
|
||||
$kAk = hash_hmac("sha256", $this->AccessKeyId, $ktime, true);
|
||||
$kdate = hash_hmac("sha256", substr($date, 0, 8), $kAk, true);
|
||||
$signature = hash_hmac("sha256", $stringToSign, $kdate, true);
|
||||
$signature = base64_encode($signature);
|
||||
|
||||
// step 4: build authorization
|
||||
$authorization = $this->AccessKeyId . " Headers=" . $signedHeaders . " Signature=" . $signature;
|
||||
|
||||
return $authorization;
|
||||
}
|
||||
|
||||
private function escape($str)
|
||||
{
|
||||
$search = ['+', '*', '%7E'];
|
||||
$replace = ['%20', '%2A', '~'];
|
||||
return str_replace($search, $replace, urlencode($str));
|
||||
}
|
||||
|
||||
private function getCanonicalQueryString($parameters)
|
||||
{
|
||||
if (empty($parameters)) return '';
|
||||
ksort($parameters);
|
||||
$canonicalQueryString = '';
|
||||
foreach ($parameters as $key => $value) {
|
||||
$canonicalQueryString .= '&' . $this->escape($key) . '=' . $this->escape($value);
|
||||
}
|
||||
return substr($canonicalQueryString, 1);
|
||||
}
|
||||
|
||||
private function getCanonicalHeaders($oldheaders)
|
||||
{
|
||||
$headers = array();
|
||||
foreach ($oldheaders as $key => $value) {
|
||||
$headers[strtolower($key)] = trim($value);
|
||||
}
|
||||
ksort($headers);
|
||||
|
||||
$canonicalHeaders = '';
|
||||
$signedHeaders = '';
|
||||
foreach ($headers as $key => $value) {
|
||||
$canonicalHeaders .= $key . ':' . $value . "\n";
|
||||
$signedHeaders .= $key . ';';
|
||||
}
|
||||
$signedHeaders = substr($signedHeaders, 0, -1);
|
||||
return [$canonicalHeaders, $signedHeaders];
|
||||
}
|
||||
|
||||
private function curl($method, $url, $body, $header)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
if (!empty($body)) {
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
||||
}
|
||||
$response = curl_exec($ch);
|
||||
$errno = curl_errno($ch);
|
||||
if ($errno) {
|
||||
curl_close($ch);
|
||||
throw new Exception('Curl error: ' . curl_error($ch));
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$arr = json_decode($response, true);
|
||||
if (isset($arr['statusCode']) && $arr['statusCode'] == 100000) {
|
||||
return isset($arr['returnObj']) ? $arr['returnObj'] : true;
|
||||
} elseif (isset($arr['errorMessage'])) {
|
||||
throw new Exception($arr['errorMessage']);
|
||||
} elseif (isset($arr['message'])) {
|
||||
throw new Exception($arr['message']);
|
||||
} else {
|
||||
throw new Exception('返回数据解析失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,12 +12,14 @@ class HuaweiCloud
|
||||
private $AccessKeyId;
|
||||
private $SecretAccessKey;
|
||||
private $endpoint;
|
||||
private $proxy = false;
|
||||
|
||||
public function __construct($AccessKeyId, $SecretAccessKey, $endpoint)
|
||||
public function __construct($AccessKeyId, $SecretAccessKey, $endpoint, $proxy = false)
|
||||
{
|
||||
$this->AccessKeyId = $AccessKeyId;
|
||||
$this->SecretAccessKey = $SecretAccessKey;
|
||||
$this->endpoint = $endpoint;
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,8 +70,7 @@ class HuaweiCloud
|
||||
|
||||
// step 1: build canonical request string
|
||||
$httpRequestMethod = $method;
|
||||
$canonicalUri = $path;
|
||||
if (substr($canonicalUri, -1) != "/") $canonicalUri .= "/";
|
||||
$canonicalUri = $this->getCanonicalURI($path);
|
||||
$canonicalQueryString = $this->getCanonicalQueryString($query);
|
||||
[$canonicalHeaders, $signedHeaders] = $this->getCanonicalHeaders($headers);
|
||||
$hashedRequestPayload = hash("sha256", $body);
|
||||
@@ -103,6 +104,18 @@ class HuaweiCloud
|
||||
return str_replace($search, $replace, urlencode($str));
|
||||
}
|
||||
|
||||
private function getCanonicalURI($path)
|
||||
{
|
||||
if (empty($path)) return '/';
|
||||
$pattens = explode('/', $path);
|
||||
$pattens = array_map(function ($item) {
|
||||
return $this->escape($item);
|
||||
}, $pattens);
|
||||
$canonicalURI = implode('/', $pattens);
|
||||
if (substr($canonicalURI, -1) != '/') $canonicalURI .= '/';
|
||||
return $canonicalURI;
|
||||
}
|
||||
|
||||
private function getCanonicalQueryString($parameters)
|
||||
{
|
||||
if (empty($parameters)) return '';
|
||||
@@ -135,6 +148,9 @@ class HuaweiCloud
|
||||
private function curl($method, $url, $body, $header)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
@@ -150,6 +166,7 @@ class HuaweiCloud
|
||||
curl_close($ch);
|
||||
throw new Exception('Curl error: ' . curl_error($ch));
|
||||
}
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
$arr = json_decode($response, true);
|
||||
@@ -164,7 +181,6 @@ class HuaweiCloud
|
||||
return $arr;
|
||||
}
|
||||
} else {
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
if ($httpCode >= 200 && $httpCode < 300) {
|
||||
return null;
|
||||
} else {
|
||||
|
||||
@@ -12,11 +12,13 @@ class Qiniu
|
||||
private $ApiUrl = 'https://api.qiniu.com';
|
||||
private $AccessKey;
|
||||
private $SecretKey;
|
||||
private $proxy = false;
|
||||
|
||||
public function __construct($AccessKey, $SecretKey)
|
||||
public function __construct($AccessKey, $SecretKey, $proxy = false)
|
||||
{
|
||||
$this->AccessKey = $AccessKey;
|
||||
$this->SecretKey = $SecretKey;
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,6 +61,39 @@ class Qiniu
|
||||
return $this->curl($method, $url, $body, $header);
|
||||
}
|
||||
|
||||
public function pili_request($method, $path, $query = null, $params = null)
|
||||
{
|
||||
$this->ApiUrl = 'https://pili.qiniuapi.com';
|
||||
$url = $this->ApiUrl . $path;
|
||||
$query_str = null;
|
||||
$body = null;
|
||||
if (!empty($query)) {
|
||||
$query = array_filter($query, function ($a) {
|
||||
return $a !== null;
|
||||
});
|
||||
$query_str = http_build_query($query);
|
||||
$url .= '?' . $query_str;
|
||||
}
|
||||
if (!empty($params)) {
|
||||
$params = array_filter($params, function ($a) {
|
||||
return $a !== null;
|
||||
});
|
||||
$body = json_encode($params);
|
||||
}
|
||||
|
||||
$sign_str = $method . ' ' . $path . ($query_str ? '?' . $query_str : '') . "\nHost: pili.qiniuapi.com" . ($body ? "\nContent-Type: application/json" : '') . "\n\n" . $body;
|
||||
$hmac = hash_hmac('sha1', $sign_str, $this->SecretKey, true);
|
||||
$sign = $this->AccessKey . ':' . $this->base64_urlSafeEncode($hmac);
|
||||
|
||||
$header = [
|
||||
'Authorization: Qiniu ' . $sign,
|
||||
];
|
||||
if ($body) {
|
||||
$header[] = 'Content-Type: application/json';
|
||||
}
|
||||
return $this->curl($method, $url, $body, $header);
|
||||
}
|
||||
|
||||
private function base64_urlSafeEncode($data)
|
||||
{
|
||||
$find = array('+', '/');
|
||||
@@ -69,6 +104,9 @@ class Qiniu
|
||||
private function curl($method, $url, $body, $header)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
@@ -90,7 +128,7 @@ class Qiniu
|
||||
|
||||
if ($httpCode == 200) {
|
||||
$arr = json_decode($response, true);
|
||||
if($arr) return $arr;
|
||||
if ($arr) return $arr;
|
||||
return true;
|
||||
} else {
|
||||
$arr = json_decode($response, true);
|
||||
|
||||
@@ -15,8 +15,9 @@ class TencentCloud
|
||||
private $service;
|
||||
private $version;
|
||||
private $region;
|
||||
private $proxy = false;
|
||||
|
||||
public function __construct($SecretId, $SecretKey, $endpoint, $service, $version, $region = null)
|
||||
public function __construct($SecretId, $SecretKey, $endpoint, $service, $version, $region = null, $proxy = false)
|
||||
{
|
||||
$this->SecretId = $SecretId;
|
||||
$this->SecretKey = $SecretKey;
|
||||
@@ -24,6 +25,7 @@ class TencentCloud
|
||||
$this->service = $service;
|
||||
$this->version = $version;
|
||||
$this->region = $region;
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,6 +100,9 @@ class TencentCloud
|
||||
{
|
||||
$url = 'https://'.$this->endpoint.'/';
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
@@ -15,8 +15,9 @@ class Volcengine
|
||||
private $service;
|
||||
private $version;
|
||||
private $region;
|
||||
private $proxy = false;
|
||||
|
||||
public function __construct($AccessKeyId, $SecretAccessKey, $endpoint, $service, $version, $region)
|
||||
public function __construct($AccessKeyId, $SecretAccessKey, $endpoint, $service, $version, $region, $proxy = false)
|
||||
{
|
||||
$this->AccessKeyId = $AccessKeyId;
|
||||
$this->SecretAccessKey = $SecretAccessKey;
|
||||
@@ -24,6 +25,7 @@ class Volcengine
|
||||
$this->service = $service;
|
||||
$this->version = $version;
|
||||
$this->region = $region;
|
||||
$this->proxy = $proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +38,9 @@ class Volcengine
|
||||
public function request($method, $action, $params = [], $querys = [])
|
||||
{
|
||||
if (!empty($params)) {
|
||||
$params = array_filter($params, function ($a) { return $a !== null;});
|
||||
$params = array_filter($params, function ($a) {
|
||||
return $a !== null;
|
||||
});
|
||||
}
|
||||
|
||||
$query = [
|
||||
@@ -76,9 +80,51 @@ class Volcengine
|
||||
return $this->curl($method, $url, $body, $header);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method 请求方法
|
||||
* @param string $action 方法名称
|
||||
* @param array $params 请求参数
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function tos_request($method, $params = [], $query = [])
|
||||
{
|
||||
if (!empty($params)) {
|
||||
$params = array_filter($params, function ($a) {
|
||||
return $a !== null;
|
||||
});
|
||||
}
|
||||
|
||||
$body = '';
|
||||
if ($method != 'GET') {
|
||||
$body = !empty($params) ? json_encode($params) : '';
|
||||
}
|
||||
|
||||
$time = time();
|
||||
$headers = [
|
||||
'Host' => $this->endpoint,
|
||||
'X-Tos-Date' => gmdate("Ymd\THis\Z", $time),
|
||||
'X-Tos-Content-Sha256' => hash("sha256", $body),
|
||||
];
|
||||
if ($body) {
|
||||
$headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
$path = '/';
|
||||
|
||||
$authorization = $this->generateSign($method, $path, $query, $headers, $body, $time);
|
||||
$headers['Authorization'] = $authorization;
|
||||
|
||||
$url = 'https://' . $this->endpoint . $path . '?' . http_build_query($query);
|
||||
$header = [];
|
||||
foreach ($headers as $key => $value) {
|
||||
$header[] = $key . ': ' . $value;
|
||||
}
|
||||
return $this->curl($method, $url, $body, $header);
|
||||
}
|
||||
|
||||
private function generateSign($method, $path, $query, $headers, $body, $time)
|
||||
{
|
||||
$algorithm = "HMAC-SHA256";
|
||||
$algorithm = $this->service == 'tos' ? "TOS4-HMAC-SHA256" : "HMAC-SHA256";
|
||||
|
||||
// step 1: build canonical request string
|
||||
$httpRequestMethod = $method;
|
||||
@@ -157,6 +203,9 @@ class Volcengine
|
||||
private function curl($method, $url, $body, $header)
|
||||
{
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
@@ -172,21 +221,27 @@ class Volcengine
|
||||
curl_close($ch);
|
||||
throw new Exception('Curl error: ' . curl_error($ch));
|
||||
}
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
$arr = json_decode($response, true);
|
||||
if ($arr) {
|
||||
if ($httpCode == 200) {
|
||||
if (isset($arr['Result'])) {
|
||||
return $arr['Result'];
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (isset($arr['ResponseMetadata']['Error']['MessageCN'])) {
|
||||
throw new Exception($arr['ResponseMetadata']['Error']['MessageCN']);
|
||||
} elseif (isset($arr['ResponseMetadata']['Error']['Message'])) {
|
||||
throw new Exception($arr['ResponseMetadata']['Error']['Message']);
|
||||
} elseif (isset($arr['Result'])) {
|
||||
return $arr['Result'];
|
||||
} elseif (isset($arr['Message'])) {
|
||||
throw new Exception($arr['Message']);
|
||||
} elseif (isset($arr['message'])) {
|
||||
throw new Exception($arr['message']);
|
||||
} else {
|
||||
return true;
|
||||
throw new Exception('返回数据解析失败(http_code=' . $httpCode . ')');
|
||||
}
|
||||
} else {
|
||||
throw new Exception('返回数据解析失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,19 @@ class aliyun implements DeployInterface
|
||||
private $logger;
|
||||
private $AccessKeyId;
|
||||
private $AccessKeySecret;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->AccessKeyId = $config['AccessKeyId'];
|
||||
$this->AccessKeySecret = $config['AccessKeySecret'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->AccessKeyId) || empty($this->AccessKeySecret)) throw new Exception('必填参数不能为空');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'cas.aliyuncs.com', '2020-04-07');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'cas.aliyuncs.com', '2020-04-07', $this->proxy);
|
||||
$param = ['Action' => 'ListUserCertificateOrder'];
|
||||
$client->request($param);
|
||||
return true;
|
||||
@@ -79,7 +81,7 @@ class aliyun implements DeployInterface
|
||||
$cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
$serial_no = strtolower($certInfo['serialNumberHex']);
|
||||
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'cas.aliyuncs.com', '2020-04-07');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'cas.aliyuncs.com', '2020-04-07', $this->proxy);
|
||||
$param = [
|
||||
'Action' => 'ListUserCertificateOrder',
|
||||
'Keyword' => $certInfo['subject']['CN'],
|
||||
@@ -125,7 +127,7 @@ class aliyun implements DeployInterface
|
||||
{
|
||||
$domain = $config['domain'];
|
||||
if (empty($domain)) throw new Exception('CDN绑定域名不能为空');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'cdn.aliyuncs.com', '2018-05-10');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'cdn.aliyuncs.com', '2018-05-10', $this->proxy);
|
||||
$param = [
|
||||
'Action' => 'SetCdnDomainSSLCertificate',
|
||||
'DomainName' => $domain,
|
||||
@@ -142,7 +144,7 @@ class aliyun implements DeployInterface
|
||||
{
|
||||
$domain = $config['domain'];
|
||||
if (empty($domain)) throw new Exception('DCDN绑定域名不能为空');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'dcdn.aliyuncs.com', '2018-01-15');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'dcdn.aliyuncs.com', '2018-01-15', $this->proxy);
|
||||
$param = [
|
||||
'Action' => 'SetDcdnDomainSSLCertificate',
|
||||
'DomainName' => $domain,
|
||||
@@ -239,7 +241,7 @@ class aliyun implements DeployInterface
|
||||
|
||||
$endpoint = 'wafopenapi.' . $config['region'] . '.aliyuncs.com';
|
||||
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2021-10-01');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2021-10-01', $this->proxy);
|
||||
|
||||
$param = [
|
||||
'Action' => 'DescribeInstance',
|
||||
@@ -298,7 +300,7 @@ class aliyun implements DeployInterface
|
||||
|
||||
$endpoint = 'wafopenapi.' . $config['region'] . '.aliyuncs.com';
|
||||
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2019-09-10');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2019-09-10', $this->proxy);
|
||||
|
||||
$param = [
|
||||
'Action' => 'DescribeInstanceInfo',
|
||||
@@ -337,7 +339,7 @@ class aliyun implements DeployInterface
|
||||
|
||||
$endpoint = 'apigateway.' . $config['regionid'] . '.aliyuncs.com';
|
||||
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2016-07-14');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2016-07-14', $this->proxy);
|
||||
|
||||
$param = [
|
||||
'Action' => 'SetDomainCertificate',
|
||||
@@ -359,7 +361,7 @@ class aliyun implements DeployInterface
|
||||
|
||||
$endpoint = 'ddoscoo.' . $config['region'] . '.aliyuncs.com';
|
||||
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2020-01-01');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2020-01-01', $this->proxy);
|
||||
|
||||
$param = [
|
||||
'Action' => 'AssociateWebCert',
|
||||
@@ -375,7 +377,7 @@ class aliyun implements DeployInterface
|
||||
{
|
||||
$domain = $config['domain'];
|
||||
if (empty($domain)) throw new Exception('视频直播绑定域名不能为空');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'live.aliyuncs.com', '2016-11-01');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'live.aliyuncs.com', '2016-11-01', $this->proxy);
|
||||
$param = [
|
||||
'Action' => 'SetLiveDomainCertificate',
|
||||
'DomainName' => $domain,
|
||||
@@ -392,7 +394,7 @@ class aliyun implements DeployInterface
|
||||
{
|
||||
$domain = $config['domain'];
|
||||
if (empty($domain)) throw new Exception('视频点播绑定域名不能为空');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'vod.cn-shanghai.aliyuncs.com', '2017-03-21');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, 'vod.cn-shanghai.aliyuncs.com', '2017-03-21', $this->proxy);
|
||||
$param = [
|
||||
'Action' => 'SetVodDomainCertificate',
|
||||
'DomainName' => $domain,
|
||||
@@ -415,7 +417,7 @@ class aliyun implements DeployInterface
|
||||
if (!$certInfo) throw new Exception('证书解析失败');
|
||||
$cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
|
||||
$client = new AliyunNewClient($this->AccessKeyId, $this->AccessKeySecret, $fc_cname, '2023-03-30');
|
||||
$client = new AliyunNewClient($this->AccessKeyId, $this->AccessKeySecret, $fc_cname, '2023-03-30', $this->proxy);
|
||||
|
||||
try {
|
||||
$data = $client->request('GET', 'GetCustomDomain', '/2023-03-30/custom-domains/' . $domain);
|
||||
@@ -458,7 +460,7 @@ class aliyun implements DeployInterface
|
||||
if (!$certInfo) throw new Exception('证书解析失败');
|
||||
$cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
|
||||
$client = new AliyunNewClient($this->AccessKeyId, $this->AccessKeySecret, $fc_cname, '2021-04-06');
|
||||
$client = new AliyunNewClient($this->AccessKeyId, $this->AccessKeySecret, $fc_cname, '2021-04-06', $this->proxy);
|
||||
|
||||
try {
|
||||
$data = $client->request('GET', 'GetCustomDomain', '/2021-04-06/custom-domains/' . $domain);
|
||||
@@ -495,7 +497,7 @@ class aliyun implements DeployInterface
|
||||
if (empty($config['clb_port'])) throw new Exception('HTTPS监听端口不能为空');
|
||||
|
||||
$endpoint = 'slb.' . $config['regionid'] . '.aliyuncs.com';
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2014-05-15');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2014-05-15', $this->proxy);
|
||||
|
||||
$param = [
|
||||
'Action' => 'DescribeServerCertificates',
|
||||
@@ -570,7 +572,7 @@ class aliyun implements DeployInterface
|
||||
if (empty($config['alb_listener_id'])) throw new Exception('负载均衡监听ID不能为空');
|
||||
|
||||
$endpoint = 'alb.' . $config['regionid'] . '.aliyuncs.com';
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2020-06-16');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2020-06-16', $this->proxy);
|
||||
|
||||
$param = [
|
||||
'Action' => 'ListListenerCertificates',
|
||||
@@ -605,7 +607,7 @@ class aliyun implements DeployInterface
|
||||
if (empty($config['nlb_listener_id'])) throw new Exception('负载均衡监听ID不能为空');
|
||||
|
||||
$endpoint = 'nlb.' . $config['regionid'] . '.aliyuncs.com';
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2022-04-30');
|
||||
$client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $endpoint, '2022-04-30', $this->proxy);
|
||||
|
||||
$param = [
|
||||
'Action' => 'ListListenerCertificates',
|
||||
|
||||
@@ -52,14 +52,33 @@ class allwaf implements DeployInterface
|
||||
$this->log('获取证书列表成功(total=' . count($list) . ')');
|
||||
|
||||
$certInfo = openssl_x509_parse($fullchain, true);
|
||||
$cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
|
||||
foreach ($list as $row) {
|
||||
if (!empty($list)) {
|
||||
foreach ($list as $row) {
|
||||
$params = [
|
||||
'sslCertId' => $row['id'],
|
||||
'isOn' => true,
|
||||
'name' => $row['name'],
|
||||
'description' => $row['description'],
|
||||
'serverName' => $row['serverName'],
|
||||
'isCA' => false,
|
||||
'certData' => base64_encode($fullchain),
|
||||
'keyData' => base64_encode($privatekey),
|
||||
'timeBeginAt' => $certInfo['validFrom_time_t'],
|
||||
'timeEndAt' => $certInfo['validTo_time_t'],
|
||||
'dnsNames' => $domains,
|
||||
'commonNames' => [$certInfo['issuer']['CN']],
|
||||
];
|
||||
$this->request('/SSLCertService/updateSSLCert', $params);
|
||||
$this->log('证书ID:' . $row['id'] . '更新成功!');
|
||||
}
|
||||
} else {
|
||||
$params = [
|
||||
'sslCertId' => $row['id'],
|
||||
'isOn' => true,
|
||||
'name' => $row['name'],
|
||||
'description' => $row['description'],
|
||||
'serverName' => $row['serverName'],
|
||||
'name' => $cert_name,
|
||||
'description' => $cert_name,
|
||||
'serverName' => $certInfo['subject']['CN'],
|
||||
'isCA' => false,
|
||||
'certData' => base64_encode($fullchain),
|
||||
'keyData' => base64_encode($privatekey),
|
||||
@@ -68,8 +87,8 @@ class allwaf implements DeployInterface
|
||||
'dnsNames' => $domains,
|
||||
'commonNames' => [$certInfo['issuer']['CN']],
|
||||
];
|
||||
$this->request('/SSLCertService/updateSSLCert', $params);
|
||||
$this->log('证书ID:' . $row['id'] . '更新成功!');
|
||||
$result = $this->request('/SSLCertService/createSSLCert', $params);
|
||||
$this->log('证书ID:' . $result['sslCertId'] . '添加成功!');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,17 +11,19 @@ class aws implements DeployInterface
|
||||
private $logger;
|
||||
private $AccessKeyId;
|
||||
private $SecretAccessKey;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->AccessKeyId = $config['AccessKeyId'];
|
||||
$this->SecretAccessKey = $config['SecretAccessKey'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->AccessKeyId) || empty($this->SecretAccessKey)) throw new Exception('必填参数不能为空');
|
||||
$client = new AWSClient($this->AccessKeyId, $this->SecretAccessKey, 'iam.amazonaws.com', 'iam', '2010-05-08', 'us-east-1');
|
||||
$client = new AWSClient($this->AccessKeyId, $this->SecretAccessKey, 'iam.amazonaws.com', 'iam', '2010-05-08', 'us-east-1', $this->proxy);
|
||||
$client->requestXml('GET', 'GetUser');
|
||||
return true;
|
||||
}
|
||||
@@ -44,7 +46,7 @@ class aws implements DeployInterface
|
||||
usleep(500000);
|
||||
}
|
||||
|
||||
$client = new \app\lib\client\AWS($this->AccessKeyId, $this->SecretAccessKey, 'cloudfront.amazonaws.com', 'cloudfront', '2020-05-31', 'us-east-1');
|
||||
$client = new AWSClient($this->AccessKeyId, $this->SecretAccessKey, 'cloudfront.amazonaws.com', 'cloudfront', '2020-05-31', 'us-east-1', $this->proxy);
|
||||
try {
|
||||
$data = $client->requestXmlN('GET', '/distribution/' . $config['distribution_id'] . '/config', [], null, true);
|
||||
} catch (Exception $e) {
|
||||
@@ -66,7 +68,7 @@ class aws implements DeployInterface
|
||||
'PrivateKey' => base64_encode($privatekey),
|
||||
];
|
||||
|
||||
$client = new \app\lib\client\AWS($this->AccessKeyId, $this->SecretAccessKey, 'acm.us-east-1.amazonaws.com', 'acm', '', 'us-east-1');
|
||||
$client = new AWSClient($this->AccessKeyId, $this->SecretAccessKey, 'acm.us-east-1.amazonaws.com', 'acm', '', 'us-east-1', $this->proxy);
|
||||
try {
|
||||
$data = $client->request('POST', 'CertificateManager.ImportCertificate', $param);
|
||||
$cert_id = $data['CertificateArn'];
|
||||
|
||||
@@ -11,17 +11,19 @@ class baidu implements DeployInterface
|
||||
private $logger;
|
||||
private $AccessKeyId;
|
||||
private $SecretAccessKey;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->AccessKeyId = $config['AccessKeyId'];
|
||||
$this->SecretAccessKey = $config['SecretAccessKey'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->AccessKeyId) || empty($this->SecretAccessKey)) throw new Exception('必填参数不能为空');
|
||||
$client = new BaiduCloud($this->AccessKeyId, $this->SecretAccessKey, 'cdn.baidubce.com');
|
||||
$client = new BaiduCloud($this->AccessKeyId, $this->SecretAccessKey, 'cdn.baidubce.com', $this->proxy);
|
||||
$client->request('GET', '/v2/domain');
|
||||
return true;
|
||||
}
|
||||
@@ -33,7 +35,7 @@ class baidu implements DeployInterface
|
||||
if (!$certInfo) throw new Exception('证书解析失败');
|
||||
$config['cert_name'] = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
|
||||
$client = new BaiduCloud($this->AccessKeyId, $this->SecretAccessKey, 'cdn.baidubce.com');
|
||||
$client = new BaiduCloud($this->AccessKeyId, $this->SecretAccessKey, 'cdn.baidubce.com', $this->proxy);
|
||||
try {
|
||||
$data = $client->request('GET', '/v2/' . $config['domain'] . '/certificates');
|
||||
if (isset($data['certName']) && $data['certName'] == $config['cert_name']) {
|
||||
|
||||
81
app/lib/deploy/ctyun.php
Normal file
81
app/lib/deploy/ctyun.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace app\lib\deploy;
|
||||
|
||||
use app\lib\DeployInterface;
|
||||
use app\lib\client\Ctyun as CtyunClient;
|
||||
use Exception;
|
||||
|
||||
class ctyun implements DeployInterface
|
||||
{
|
||||
private $logger;
|
||||
private $AccessKeyId;
|
||||
private $SecretAccessKey;
|
||||
private $proxy;
|
||||
private $client;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->AccessKeyId = $config['AccessKeyId'];
|
||||
$this->SecretAccessKey = $config['SecretAccessKey'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new CtyunClient($this->AccessKeyId, $this->SecretAccessKey, 'ctcdn-global.ctapi.ctyun.cn', $this->proxy);
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->AccessKeyId) || empty($this->SecretAccessKey)) throw new Exception('必填参数不能为空');
|
||||
$this->client->request('GET', '/v1/cert/query-cert-list');
|
||||
return true;
|
||||
}
|
||||
|
||||
public function deploy($fullchain, $privatekey, $config, &$info)
|
||||
{
|
||||
$certInfo = openssl_x509_parse($fullchain, true);
|
||||
if (!$certInfo) throw new Exception('证书解析失败');
|
||||
$cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
|
||||
$param = [
|
||||
'name' => $cert_name,
|
||||
'key' => $privatekey,
|
||||
'certs' => $fullchain,
|
||||
];
|
||||
try {
|
||||
$this->client->request('POST', '/v1/cert/creat-cert', null, $param);
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), '已存在重名的证书') !== false) {
|
||||
$this->log('已存在重名的证书 cert_name=' . $cert_name);
|
||||
} else {
|
||||
throw new Exception('上传证书失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
$this->log('上传证书成功 cert_name=' . $cert_name);
|
||||
|
||||
$param = [
|
||||
'domain' => $config['domain'],
|
||||
'https_status' => 'on',
|
||||
'cert_name' => $cert_name,
|
||||
];
|
||||
try {
|
||||
$this->client->request('POST', '/v1/domain/update-domain', null, $param);
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), '请求已提交,请勿重复操作!') === false) {
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$this->log('CDN域名 ' . $config['domain'] . ' 部署证书成功!');
|
||||
}
|
||||
|
||||
public function setLogger($func)
|
||||
{
|
||||
$this->logger = $func;
|
||||
}
|
||||
|
||||
private function log($txt)
|
||||
{
|
||||
if ($this->logger) {
|
||||
call_user_func($this->logger, $txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,11 +10,13 @@ class doge implements DeployInterface
|
||||
private $logger;
|
||||
private $AccessKey;
|
||||
private $SecretKey;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->AccessKey = $config['AccessKey'];
|
||||
$this->SecretKey = $config['SecretKey'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
}
|
||||
|
||||
public function check()
|
||||
@@ -95,7 +97,7 @@ class doge implements DeployInterface
|
||||
$headers = ['Authorization: ' . $authorization];
|
||||
if($body && $json) $headers[] = 'Content-Type: application/json';
|
||||
$url = 'https://api.dogecloud.com'.$path;
|
||||
$response = curl_client($url, $body, null, null, $headers);
|
||||
$response = curl_client($url, $body, null, null, $headers, $this->proxy);
|
||||
$result = json_decode($response['body'], true);
|
||||
if(isset($result['code']) && $result['code'] == 200){
|
||||
return isset($result['data']) ? $result['data'] : true;
|
||||
|
||||
@@ -50,20 +50,39 @@ class goedge implements DeployInterface
|
||||
throw new Exception('获取证书列表失败:' . $e->getMessage());
|
||||
}
|
||||
$list = json_decode(base64_decode($data['sslCertsJSON']), true);
|
||||
if (!$list || empty($list)) {
|
||||
if ($list === false) {
|
||||
throw new Exception('证书列表为空');
|
||||
}
|
||||
$this->log('获取证书列表成功(total=' . count($list) . ')');
|
||||
|
||||
$certInfo = openssl_x509_parse($fullchain, true);
|
||||
$cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
|
||||
foreach ($list as $row) {
|
||||
if (!empty($list)) {
|
||||
foreach ($list as $row) {
|
||||
$params = [
|
||||
'sslCertId' => $row['id'],
|
||||
'isOn' => true,
|
||||
'name' => $row['name'],
|
||||
'description' => $row['description'],
|
||||
'serverName' => $row['serverName'],
|
||||
'isCA' => false,
|
||||
'certData' => base64_encode($fullchain),
|
||||
'keyData' => base64_encode($privatekey),
|
||||
'timeBeginAt' => $certInfo['validFrom_time_t'],
|
||||
'timeEndAt' => $certInfo['validTo_time_t'],
|
||||
'dnsNames' => $domains,
|
||||
'commonNames' => [$certInfo['issuer']['CN']],
|
||||
];
|
||||
$this->request('/SSLCertService/updateSSLCert', $params);
|
||||
$this->log('证书ID:' . $row['id'] . '更新成功!');
|
||||
}
|
||||
} else {
|
||||
$params = [
|
||||
'sslCertId' => $row['id'],
|
||||
'isOn' => true,
|
||||
'name' => $row['name'],
|
||||
'description' => $row['description'],
|
||||
'serverName' => $row['serverName'],
|
||||
'name' => $cert_name,
|
||||
'description' => $cert_name,
|
||||
'serverName' => $certInfo['subject']['CN'],
|
||||
'isCA' => false,
|
||||
'certData' => base64_encode($fullchain),
|
||||
'keyData' => base64_encode($privatekey),
|
||||
@@ -72,8 +91,8 @@ class goedge implements DeployInterface
|
||||
'dnsNames' => $domains,
|
||||
'commonNames' => [$certInfo['issuer']['CN']],
|
||||
];
|
||||
$this->request('/SSLCertService/updateSSLCert', $params);
|
||||
$this->log('证书ID:' . $row['id'] . '更新成功!');
|
||||
$result = $this->request('/SSLCertService/createSSLCert', $params);
|
||||
$this->log('证书ID:' . $result['sslCertId'] . '添加成功!');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,17 +11,19 @@ class huawei implements DeployInterface
|
||||
private $logger;
|
||||
private $AccessKeyId;
|
||||
private $SecretAccessKey;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->AccessKeyId = $config['AccessKeyId'];
|
||||
$this->SecretAccessKey = $config['SecretAccessKey'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->AccessKeyId) || empty($this->SecretAccessKey)) throw new Exception('必填参数不能为空');
|
||||
$client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, 'scm.cn-north-4.myhuaweicloud.com');
|
||||
$client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, 'scm.cn-north-4.myhuaweicloud.com', $this->proxy);
|
||||
$client->request('GET', '/v3/scm/certificates');
|
||||
return true;
|
||||
}
|
||||
@@ -43,7 +45,7 @@ class huawei implements DeployInterface
|
||||
private function deploy_cdn($fullchain, $privatekey, $config)
|
||||
{
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
$client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, 'cdn.myhuaweicloud.com');
|
||||
$client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, 'cdn.myhuaweicloud.com', $this->proxy);
|
||||
$param = [
|
||||
'configs' => [
|
||||
'https' => [
|
||||
@@ -66,7 +68,7 @@ class huawei implements DeployInterface
|
||||
if (empty($config['region_id'])) throw new Exception('区域ID不能为空');
|
||||
if (empty($config['cert_id'])) throw new Exception('证书ID不能为空');
|
||||
$endpoint = 'elb.' . $config['region_id'] . '.myhuaweicloud.com';
|
||||
$client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, $endpoint);
|
||||
$client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, $endpoint, $this->proxy);
|
||||
try {
|
||||
$data = $client->request('GET', '/v3/' . $config['project_id'] . '/elb/certificates/' . $config['cert_id']);
|
||||
} catch (Exception $e) {
|
||||
@@ -93,7 +95,7 @@ class huawei implements DeployInterface
|
||||
if (empty($config['region_id'])) throw new Exception('区域ID不能为空');
|
||||
if (empty($config['cert_id'])) throw new Exception('证书ID不能为空');
|
||||
$endpoint = 'waf.' . $config['region_id'] . '.myhuaweicloud.com';
|
||||
$client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, $endpoint);
|
||||
$client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, $endpoint, $this->proxy);
|
||||
try {
|
||||
$data = $client->request('GET', '/v1/' . $config['project_id'] . '/waf/certificates/' . $config['cert_id']);
|
||||
} catch (Exception $e) {
|
||||
@@ -118,7 +120,7 @@ class huawei implements DeployInterface
|
||||
if (!$certInfo) throw new Exception('证书解析失败');
|
||||
$cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
|
||||
$client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, 'scm.cn-north-4.myhuaweicloud.com');
|
||||
$client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, 'scm.cn-north-4.myhuaweicloud.com', $this->proxy);
|
||||
$param = [
|
||||
'name' => $cert_name,
|
||||
'certificate' => $fullchain,
|
||||
|
||||
@@ -11,34 +11,49 @@ class huoshan implements DeployInterface
|
||||
private $logger;
|
||||
private $AccessKeyId;
|
||||
private $SecretAccessKey;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->AccessKeyId = $config['AccessKeyId'];
|
||||
$this->SecretAccessKey = $config['SecretAccessKey'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->AccessKeyId) || empty($this->SecretAccessKey)) throw new Exception('必填参数不能为空');
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'cdn.volcengineapi.com', 'cdn', '2021-03-01', 'cn-north-1');
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'open.volcengineapi.com', 'cdn', '2021-03-01', 'cn-north-1', $this->proxy);
|
||||
$client->request('POST', 'ListCertInfo', ['Source' => 'volc_cert_center']);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function deploy($fullchain, $privatekey, $config, &$info)
|
||||
{
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
$cert_id = $this->get_cert_id($fullchain, $privatekey);
|
||||
if (!$cert_id) throw new Exception('获取证书ID失败');
|
||||
$info['cert_id'] = $cert_id;
|
||||
$this->deploy_cdn($cert_id, $config);
|
||||
if ($config['product'] == 'live') {
|
||||
$this->deploy_live($fullchain, $privatekey, $config);
|
||||
} else {
|
||||
$cert_id = $this->get_cert_id($fullchain, $privatekey);
|
||||
if (!$cert_id) throw new Exception('获取证书ID失败');
|
||||
$info['cert_id'] = $cert_id;
|
||||
if (!isset($config['product']) || $config['product'] == 'cdn') {
|
||||
$this->deploy_cdn($cert_id, $config);
|
||||
} elseif ($config['product'] == 'dcdn') {
|
||||
$this->deploy_dcdn($cert_id, $config);
|
||||
} elseif ($config['product'] == 'tos') {
|
||||
$this->deploy_tos($cert_id, $config);
|
||||
} elseif ($config['product'] == 'imagex') {
|
||||
$this->deploy_imagex($cert_id, $config);
|
||||
} elseif ($config['product'] == 'clb') {
|
||||
$this->deploy_clb($cert_id, $config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function deploy_cdn($cert_id, $config)
|
||||
{
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'cdn.volcengineapi.com', 'cdn', '2021-03-01', 'cn-north-1');
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'cdn.volcengineapi.com', 'cdn', '2021-03-01', 'cn-north-1', $this->proxy);
|
||||
$param = [
|
||||
'CertId' => $cert_id,
|
||||
'Domain' => $config['domain'],
|
||||
@@ -49,37 +64,137 @@ class huoshan implements DeployInterface
|
||||
if ($row['Status'] == 'success') {
|
||||
$this->log('CDN域名 ' . $row['Domain'] . ' 部署证书成功!');
|
||||
} else {
|
||||
$this->log('CDN域名 ' . $row['Domain'] . ' 部署证书失败:' . isset($row['ErrorMsg']) ? $row['ErrorMsg'] : '');
|
||||
$this->log('CDN域名 ' . $row['Domain'] . ' 部署证书失败:' . (isset($row['ErrorMsg']) ? $row['ErrorMsg'] : ''));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function deploy_dcdn($cert_id, $config)
|
||||
{
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'open.volcengineapi.com', 'dcdn', '2021-04-01', 'cn-north-1', $this->proxy);
|
||||
$param = [
|
||||
'CertId' => $cert_id,
|
||||
'DomainNames' => explode(',', $config['domain']),
|
||||
];
|
||||
$client->request('POST', 'CreateCertBind', $param);
|
||||
$this->log('DCDN域名 ' . $config['domain'] . ' 部署证书成功!');
|
||||
}
|
||||
|
||||
private function deploy_tos($cert_id, $config)
|
||||
{
|
||||
if (empty($config['bucket_domain'])) throw new Exception('Bucket域名不能为空');
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, $config['bucket_domain'], 'tos', '2021-04-01', 'cn-beijing', $this->proxy);
|
||||
foreach (explode(',', $config['domain']) as $domain) {
|
||||
$param = [
|
||||
'CustomDomainRule' => [
|
||||
'Domain' => $domain,
|
||||
'CertId' => $cert_id,
|
||||
]
|
||||
];
|
||||
$query = ['customdomain' => ''];
|
||||
$client->tos_request('PUT', $param, $query);
|
||||
$this->log('对象存储域名 ' . $config['domain'] . ' 部署证书成功!');
|
||||
}
|
||||
}
|
||||
|
||||
private function deploy_live($fullchain, $privatekey, $config)
|
||||
{
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
|
||||
$certInfo = openssl_x509_parse($fullchain, true);
|
||||
if (!$certInfo) throw new Exception('证书解析失败');
|
||||
$cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'live.volcengineapi.com', 'live', '2023-01-01', 'cn-north-1', $this->proxy);
|
||||
$param = [
|
||||
'CertName' => $cert_name,
|
||||
'Rsa' => [
|
||||
'Pubkey' => $fullchain,
|
||||
'Prikey' => $privatekey,
|
||||
],
|
||||
'UseWay' => 'https',
|
||||
];
|
||||
$result = $client->request('POST', 'CreateCert', $param);
|
||||
$this->log('上传证书成功 ChainID=' . $result['ChainID']);
|
||||
|
||||
foreach (explode(',', $config['domain']) as $domain) {
|
||||
$param = [
|
||||
'ChainID' => $result['ChainID'],
|
||||
'Domain' => $domain,
|
||||
'HTTPS' => true,
|
||||
'HTTP2' => true,
|
||||
];
|
||||
$client->request('POST', 'BindCert', $param);
|
||||
$this->log('视频直播域名 ' . $domain . ' 部署证书成功!');
|
||||
}
|
||||
}
|
||||
|
||||
private function deploy_imagex($cert_id, $config)
|
||||
{
|
||||
if (empty($config['bucket_domain'])) throw new Exception('Bucket域名不能为空');
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'imagex.volcengineapi.com', 'imagex', '2018-08-01', 'cn-north-1', $this->proxy);
|
||||
foreach (explode(',', $config['domain']) as $domain) {
|
||||
$param = [
|
||||
[
|
||||
'domain' => $domain,
|
||||
'cert_id' => $cert_id,
|
||||
]
|
||||
];
|
||||
$result = $client->request('POST', 'UpdateImageBatchDomainCert', $param);
|
||||
if (isset($result['SuccessDomains']) && count($result['SuccessDomains']) > 0) {
|
||||
$this->log('veImageX域名 ' . $domain . ' 部署证书成功!');
|
||||
} elseif (isset($result['FailedDomains']) && count($result['FailedDomains']) > 0) {
|
||||
$errmsg = $result['FailedDomains'][0]['ErrMsg'];
|
||||
$this->log('veImageX域名 ' . $domain . ' 部署证书失败:' . $errmsg);
|
||||
} else {
|
||||
$this->log('veImageX域名 ' . $domain . ' 部署证书失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function deploy_clb($cert_id, $config)
|
||||
{
|
||||
if (empty($config['listener_id'])) throw new Exception('监听器ID不能为空');
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'open.volcengineapi.com', 'clb', '2020-04-01', 'cn-beijing', $this->proxy);
|
||||
$param = [
|
||||
'ListenerId' => $config['listener_id'],
|
||||
'CertificateSource' => 'cert_center',
|
||||
'CertCenterCertificateId' => $cert_id,
|
||||
];
|
||||
$client->request('GET', 'ModifyListenerAttributes', $param);
|
||||
$this->log('CLB监听器 ' . $config['listener_id'] . ' 部署证书成功!');
|
||||
}
|
||||
|
||||
private function get_cert_id($fullchain, $privatekey)
|
||||
{
|
||||
$certInfo = openssl_x509_parse($fullchain, true);
|
||||
if (!$certInfo) throw new Exception('证书解析失败');
|
||||
$cert_name = str_replace('*.', '', $certInfo['subject']['CN']) . '-' . $certInfo['validFrom_time_t'];
|
||||
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'cdn.volcengineapi.com', 'cdn', '2021-03-01', 'cn-north-1');
|
||||
$client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, 'open.volcengineapi.com', 'certificate_service', '2024-10-01', 'cn-beijing', $this->proxy);
|
||||
$param = [
|
||||
'Source' => 'volc_cert_center',
|
||||
'Certificate' => $fullchain,
|
||||
'PrivateKey' => $privatekey,
|
||||
'Desc' => $cert_name,
|
||||
'Tag' => $cert_name,
|
||||
'Repeatable' => false,
|
||||
'CertificateInfo' => [
|
||||
'CertificateChain' => $fullchain,
|
||||
'PrivateKey' => $privatekey,
|
||||
],
|
||||
];
|
||||
try {
|
||||
$data = $client->request('POST', 'AddCertificate', $param);
|
||||
$data = $client->request('POST', 'ImportCertificate', $param);
|
||||
} catch (Exception $e) {
|
||||
if (strpos($e->getMessage(), '证书已存在,ID为') !== false) {
|
||||
$cert_id = trim(getSubstr($e->getMessage(), '证书已存在,ID为', '。'));
|
||||
$this->log('证书已存在 CertId=' . $cert_id);
|
||||
return $cert_id;
|
||||
}
|
||||
throw new Exception('上传证书失败:' . $e->getMessage());
|
||||
}
|
||||
$this->log('上传证书成功 CertId=' . $data['CertId']);
|
||||
return $data['CertId'];
|
||||
if (!empty($data['InstanceId'])) {
|
||||
$cert_id = $data['InstanceId'];
|
||||
} else {
|
||||
$cert_id = $data['RepeatId'];
|
||||
}
|
||||
$this->log('上传证书成功 CertId=' . $cert_id);
|
||||
return $cert_id;
|
||||
}
|
||||
|
||||
public function setLogger($func)
|
||||
|
||||
@@ -62,8 +62,8 @@ class lecdn implements DeployInterface
|
||||
'password' => $this->password,
|
||||
];
|
||||
$result = $this->request($path, $params);
|
||||
if (isset($result['access_token'])) {
|
||||
$this->accessToken = $result['access_token'];
|
||||
if (isset($result['token'])) {
|
||||
$this->accessToken = $result['token'];
|
||||
} else {
|
||||
throw new Exception('登录成功,获取access_token失败');
|
||||
}
|
||||
@@ -83,7 +83,7 @@ class lecdn implements DeployInterface
|
||||
}
|
||||
$response = curl_client($url, $body, null, null, $headers, $this->proxy, $method);
|
||||
$result = json_decode($response['body'], true);
|
||||
if (isset($result['code']) && $result['code'] == 0) {
|
||||
if (isset($result['code']) && $result['code'] == 200) {
|
||||
return isset($result['data']) ? $result['data'] : null;
|
||||
} elseif (isset($result['message'])) {
|
||||
throw new Exception($result['message']);
|
||||
|
||||
127
app/lib/deploy/mwpanel.php
Normal file
127
app/lib/deploy/mwpanel.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace app\lib\deploy;
|
||||
|
||||
use app\lib\DeployInterface;
|
||||
use Exception;
|
||||
|
||||
class mwpanel implements DeployInterface
|
||||
{
|
||||
private $logger;
|
||||
private $url;
|
||||
private $appid;
|
||||
private $appsecret;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->url = rtrim($config['url'], '/');
|
||||
$this->appid = $config['appid'];
|
||||
$this->appsecret = $config['appsecret'];
|
||||
$this->proxy = $config['proxy'] == 1;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->url) || empty($this->appid) || empty($this->appsecret)) throw new Exception('请填写面板地址和接口密钥');
|
||||
|
||||
$path = '/task/count';
|
||||
$response = $this->request($path);
|
||||
$result = json_decode($response, true);
|
||||
if (isset($result['status']) && $result['status'] == true) {
|
||||
return true;
|
||||
} else {
|
||||
throw new Exception(isset($result['msg']) ? $result['msg'] : '面板地址无法连接');
|
||||
}
|
||||
}
|
||||
|
||||
public function deploy($fullchain, $privatekey, $config, &$info)
|
||||
{
|
||||
if ($config['type'] == '1') {
|
||||
$this->deployPanel($fullchain, $privatekey);
|
||||
$this->log("面板证书部署成功");
|
||||
return;
|
||||
}
|
||||
$sites = explode("\n", $config['sites']);
|
||||
$success = 0;
|
||||
$errmsg = null;
|
||||
foreach ($sites as $site) {
|
||||
$siteName = trim($site);
|
||||
if (empty($siteName)) continue;
|
||||
try {
|
||||
$this->deploySite($siteName, $fullchain, $privatekey);
|
||||
$this->log("网站 {$siteName} 证书部署成功");
|
||||
$success++;
|
||||
} catch (Exception $e) {
|
||||
$errmsg = $e->getMessage();
|
||||
$this->log("网站 {$siteName} 证书部署失败:" . $errmsg);
|
||||
}
|
||||
}
|
||||
if ($success == 0) {
|
||||
throw new Exception($errmsg ? $errmsg : '要部署的网站不存在');
|
||||
}
|
||||
}
|
||||
|
||||
private function deployPanel($fullchain, $privatekey)
|
||||
{
|
||||
$path = '/setting/save_panel_ssl';
|
||||
$data = [
|
||||
'privateKey' => $privatekey,
|
||||
'certPem' => $fullchain,
|
||||
'choose' => 'local',
|
||||
];
|
||||
$response = $this->request($path, $data);
|
||||
$result = json_decode($response, true);
|
||||
if (isset($result['status']) && $result['status']) {
|
||||
return true;
|
||||
} elseif (isset($result['msg'])) {
|
||||
throw new Exception($result['msg']);
|
||||
} else {
|
||||
throw new Exception($response ? $response : '返回数据解析失败');
|
||||
}
|
||||
}
|
||||
|
||||
private function deploySite($siteName, $fullchain, $privatekey)
|
||||
{
|
||||
$path = '/site/set_ssl';
|
||||
$data = [
|
||||
'type' => '1',
|
||||
'siteName' => $siteName,
|
||||
'key' => $privatekey,
|
||||
'csr' => $fullchain,
|
||||
];
|
||||
$response = $this->request($path, $data);
|
||||
$result = json_decode($response, true);
|
||||
if (isset($result['status']) && $result['status']) {
|
||||
return true;
|
||||
} elseif (isset($result['msg'])) {
|
||||
throw new Exception($result['msg']);
|
||||
} else {
|
||||
throw new Exception($response ? $response : '返回数据解析失败');
|
||||
}
|
||||
}
|
||||
|
||||
public function setLogger($func)
|
||||
{
|
||||
$this->logger = $func;
|
||||
}
|
||||
|
||||
private function log($txt)
|
||||
{
|
||||
if ($this->logger) {
|
||||
call_user_func($this->logger, $txt);
|
||||
}
|
||||
}
|
||||
|
||||
private function request($path, $params = null)
|
||||
{
|
||||
$url = $this->url . $path;
|
||||
|
||||
$headers = [
|
||||
'app-id: '.$this->appid,
|
||||
'app-secret: '.$this->appsecret,
|
||||
];
|
||||
$response = curl_client($url, $params ? http_build_query($params) : null, null, null, $headers, $this->proxy);
|
||||
return $response['body'];
|
||||
}
|
||||
}
|
||||
@@ -40,32 +40,35 @@ class opanel implements DeployInterface
|
||||
|
||||
$success = 0;
|
||||
$errmsg = null;
|
||||
foreach ($data['items'] as $row) {
|
||||
if (empty($row['primaryDomain'])) continue;
|
||||
$cert_domains[] = $row['primaryDomain'];
|
||||
if(!empty($row['domains'])) $cert_domains += explode(',', $row['domains']);
|
||||
$flag = false;
|
||||
foreach ($cert_domains as $domain) {
|
||||
if (in_array($domain, $domains)) {
|
||||
$flag = true;
|
||||
break;
|
||||
if (!empty($data['items'])) {
|
||||
foreach ($data['items'] as $row) {
|
||||
if (empty($row['primaryDomain'])) continue;
|
||||
$cert_domains = [];
|
||||
$cert_domains[] = $row['primaryDomain'];
|
||||
if(!empty($row['domains'])) $cert_domains += explode(',', $row['domains']);
|
||||
$flag = false;
|
||||
foreach ($cert_domains as $domain) {
|
||||
if (in_array($domain, $domains)) {
|
||||
$flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($flag) {
|
||||
$params = [
|
||||
'sslID' => $row['id'],
|
||||
'type' => 'paste',
|
||||
'certificate' => $fullchain,
|
||||
'privateKey' => $privatekey,
|
||||
'description' => '',
|
||||
];
|
||||
try {
|
||||
$this->request('/api/v1/websites/ssl/upload', $params);
|
||||
$this->log("证书ID:{$row['id']}更新成功!");
|
||||
$success++;
|
||||
} catch (Exception $e) {
|
||||
$errmsg = $e->getMessage();
|
||||
$this->log("证书ID:{$row['id']}更新失败:" . $errmsg);
|
||||
if ($flag) {
|
||||
$params = [
|
||||
'sslID' => $row['id'],
|
||||
'type' => 'paste',
|
||||
'certificate' => $fullchain,
|
||||
'privateKey' => $privatekey,
|
||||
'description' => '',
|
||||
];
|
||||
try {
|
||||
$this->request('/api/v1/websites/ssl/upload', $params);
|
||||
$this->log("证书ID:{$row['id']}更新成功!");
|
||||
$success++;
|
||||
} catch (Exception $e) {
|
||||
$errmsg = $e->getMessage();
|
||||
$this->log("证书ID:{$row['id']}更新失败:" . $errmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,7 +99,7 @@ class opanel implements DeployInterface
|
||||
'1Panel-Token: '.$token,
|
||||
'1Panel-Timestamp: '.$timestamp
|
||||
];
|
||||
$body = $params ? json_encode($params) : null;
|
||||
$body = $params ? json_encode($params) : '{}';
|
||||
if($body) $headers[] = 'Content-Type: application/json';
|
||||
$response = curl_client($url, $body, null, null, $headers, $this->proxy);
|
||||
$result = json_decode($response['body'], true);
|
||||
|
||||
@@ -17,7 +17,7 @@ class qiniu implements DeployInterface
|
||||
{
|
||||
$this->AccessKey = $config['AccessKey'];
|
||||
$this->SecretKey = $config['SecretKey'];
|
||||
$this->client = new QiniuClient($this->AccessKey, $this->SecretKey);
|
||||
$this->client = new QiniuClient($this->AccessKey, $this->SecretKey, isset($config['proxy']) ? $config['proxy'] == 1 : false);
|
||||
}
|
||||
|
||||
public function check()
|
||||
@@ -42,6 +42,8 @@ class qiniu implements DeployInterface
|
||||
$this->deploy_cdn($domain, $cert_id);
|
||||
} elseif ($config['product'] == 'oss') {
|
||||
$this->deploy_oss($domain, $cert_id);
|
||||
} elseif ($config['product'] == 'pili') {
|
||||
$this->deploy_pili($config['pili_hub'], $domain, $cert_name);
|
||||
} else {
|
||||
throw new Exception('未知的产品类型');
|
||||
}
|
||||
@@ -87,6 +89,15 @@ class qiniu implements DeployInterface
|
||||
$this->log('OSS域名 ' . $domain . ' 证书部署成功!');
|
||||
}
|
||||
|
||||
private function deploy_pili($hub, $domain, $cert_name)
|
||||
{
|
||||
$param = [
|
||||
'CertName' => $cert_name,
|
||||
];
|
||||
$this->client->pili_request('POST', '/v2/hubs/'.$hub.'/domains/'.$domain.'/cert', null, $param);
|
||||
$this->log('视频直播域名 ' . $domain . ' 证书部署成功!');
|
||||
}
|
||||
|
||||
private function get_cert_id($fullchain, $privatekey, $common_name, $cert_name)
|
||||
{
|
||||
$cert_id = null;
|
||||
|
||||
@@ -68,7 +68,15 @@ class safeline implements DeployInterface
|
||||
}
|
||||
}
|
||||
if ($success == 0) {
|
||||
throw new Exception($errmsg ? $errmsg : '没有要更新的证书');
|
||||
$params = [
|
||||
'manual' => [
|
||||
'crt' => $fullchain,
|
||||
'key' => $privatekey,
|
||||
],
|
||||
'type' => 2,
|
||||
];
|
||||
$this->request('/api/open/cert', $params);
|
||||
$this->log("证书上传成功!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,14 @@ class tencent implements DeployInterface
|
||||
private $SecretId;
|
||||
private $SecretKey;
|
||||
private TencentCloud $client;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->SecretId = $config['SecretId'];
|
||||
$this->SecretKey = $config['SecretKey'];
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05');
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', null, $this->proxy);
|
||||
}
|
||||
|
||||
public function check()
|
||||
@@ -35,21 +37,25 @@ class tencent implements DeployInterface
|
||||
if (empty($config['regionid'])) throw new Exception('所属地域ID不能为空');
|
||||
if (empty($config['cos_bucket'])) throw new Exception('存储桶名称不能为空');
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
$instance_id = $config['regionid'] . '#' . $config['cos_bucket'] . '#' . $config['domain'];
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', $config['regionid']);
|
||||
$instance_id = $config['regionid'] . '|' . $config['cos_bucket'] . '|' . $config['domain'];
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', $config['regionid'], $this->proxy);
|
||||
} elseif ($config['product'] == 'tke') {
|
||||
if (empty($config['regionid'])) throw new Exception('所属地域ID不能为空');
|
||||
if (empty($config['tke_cluster_id'])) throw new Exception('集群ID不能为空');
|
||||
if (empty($config['tke_namespace'])) throw new Exception('命名空间不能为空');
|
||||
if (empty($config['tke_secret'])) throw new Exception('secret名称不能为空');
|
||||
$instance_id = $config['tke_cluster_id'] . '|' . $config['tke_namespace'] . '|' . $config['tke_secret'];
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', $config['regionid']);
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', $config['regionid'], $this->proxy);
|
||||
} elseif ($config['product'] == 'lighthouse') {
|
||||
if (empty($config['regionid'])) throw new Exception('所属地域ID不能为空');
|
||||
if (empty($config['lighthouse_id'])) throw new Exception('实例ID不能为空');
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
$instance_id = $config['regionid'] . '|' . $config['lighthouse_id'] . '|' . $config['domain'];
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', $config['regionid']);
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', $config['regionid'], $this->proxy);
|
||||
} elseif ($config['product'] == 'ddos') {
|
||||
if (empty($config['lighthouse_id'])) throw new Exception('实例ID不能为空');
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
$instance_id = $config['lighthouse_id'] . '|' . $config['domain'] . '|443';
|
||||
} elseif ($config['product'] == 'clb') {
|
||||
return $this->deploy_clb($cert_id, $config);
|
||||
} elseif ($config['product'] == 'scf') {
|
||||
@@ -57,10 +63,10 @@ class tencent implements DeployInterface
|
||||
} else {
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
if ($config['product'] == 'waf') {
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', $config['region']);
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', $config['region'], $this->proxy);
|
||||
} elseif (in_array($config['product'], ['tse', 'scf'])) {
|
||||
if (empty($config['regionid'])) throw new Exception('所属地域ID不能为空');
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', $config['regionid']);
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, 'ssl.tencentcloudapi.com', 'ssl', '2019-12-05', $config['regionid'], $this->proxy);
|
||||
}
|
||||
$instance_id = $config['domain'];
|
||||
}
|
||||
@@ -104,9 +110,14 @@ class tencent implements DeployInterface
|
||||
|
||||
private function deploy_common($product, $cert_id, $instance_id)
|
||||
{
|
||||
if (in_array($product, ['cdn', 'waf', 'teo', 'ddos', 'live', 'vod']) && strpos($instance_id, ',') !== false) {
|
||||
$instance_ids = explode(',', $instance_id);
|
||||
} else {
|
||||
$instance_ids = [$instance_id];
|
||||
}
|
||||
$param = [
|
||||
'CertificateId' => $cert_id,
|
||||
'InstanceIdList' => [$instance_id],
|
||||
'InstanceIdList' => $instance_ids,
|
||||
'ResourceType' => $product,
|
||||
];
|
||||
$data = $this->client->request('DeployCertificateInstance', $param);
|
||||
@@ -144,7 +155,7 @@ class tencent implements DeployInterface
|
||||
if (empty($config['clb_id'])) throw new Exception('负载均衡ID不能为空');
|
||||
$sni_switch = !empty($config['clb_domain']) ? 1 : 0;
|
||||
|
||||
$client = new TencentCloud($this->SecretId, $this->SecretKey, 'clb.tencentcloudapi.com', 'clb', '2018-03-17', $config['regionid']);
|
||||
$client = new TencentCloud($this->SecretId, $this->SecretKey, 'clb.tencentcloudapi.com', 'clb', '2018-03-17', $config['regionid'], $this->proxy);
|
||||
$param = [
|
||||
'LoadBalancerId' => $config['clb_id'],
|
||||
'Protocol' => 'HTTPS',
|
||||
@@ -209,7 +220,7 @@ class tencent implements DeployInterface
|
||||
if (empty($config['regionid'])) throw new Exception('所属地域ID不能为空');
|
||||
if (empty($config['domain'])) throw new Exception('绑定的域名不能为空');
|
||||
|
||||
$client = new TencentCloud($this->SecretId, $this->SecretKey, 'scf.tencentcloudapi.com', 'scf', '2018-04-16', $config['regionid']);
|
||||
$client = new TencentCloud($this->SecretId, $this->SecretKey, 'scf.tencentcloudapi.com', 'scf', '2018-04-16', $config['regionid'], $this->proxy);
|
||||
$param = [
|
||||
'Domain' => $config['domain'],
|
||||
];
|
||||
|
||||
131
app/lib/deploy/west.php
Normal file
131
app/lib/deploy/west.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace app\lib\deploy;
|
||||
|
||||
use app\lib\DeployInterface;
|
||||
use Exception;
|
||||
|
||||
class west implements DeployInterface
|
||||
{
|
||||
private $logger;
|
||||
private $username;
|
||||
private $api_password;
|
||||
private $baseUrl = 'https://api.west.cn/api/v2';
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->username = $config['username'];
|
||||
$this->api_password = $config['api_password'];
|
||||
$this->proxy = $config['proxy'] == 1;
|
||||
}
|
||||
|
||||
public function check()
|
||||
{
|
||||
if (empty($this->username) || empty($this->api_password)) throw new Exception('用户名或API密码不能为空');
|
||||
$this->execute('/vhost/', ['act' => 'products']);
|
||||
}
|
||||
|
||||
public function deploy($fullchain, $privatekey, $config, &$info)
|
||||
{
|
||||
if (empty($config['sitename'])) throw new Exception('FTP账号不能为空');
|
||||
$params = [
|
||||
'act' => 'vhostssl',
|
||||
'sitename' => $config['sitename'],
|
||||
'cmd' => 'info'
|
||||
];
|
||||
try {
|
||||
$data = $this->execute('/vhost/', $params);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('获取虚拟主机SSL配置失败:' . $e->getMessage());
|
||||
}
|
||||
|
||||
$params = [
|
||||
'act' => 'vhostssl',
|
||||
'sitename' => $config['sitename'],
|
||||
'cmd' => 'import',
|
||||
'keycontent' => $privatekey,
|
||||
'certcontent' => $fullchain,
|
||||
];
|
||||
try {
|
||||
$this->execute('/vhost/', $params);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('上传SSL证书失败:' . $e->getMessage());
|
||||
}
|
||||
$this->log('SSL证书上传成功');
|
||||
|
||||
if (!isset($data['SSLEnabled']) || $data['SSLEnabled'] == 0) {
|
||||
$params = [
|
||||
'act' => 'vhostssl',
|
||||
'sitename' => $config['sitename'],
|
||||
'cmd' => 'openssl',
|
||||
];
|
||||
try {
|
||||
$this->execute('/vhost/', $params);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('虚拟主机部署SSL失败:' . $e->getMessage());
|
||||
}
|
||||
} else {
|
||||
$params = [
|
||||
'act' => 'vhostssl',
|
||||
'sitename' => $config['sitename'],
|
||||
'cmd' => 'info'
|
||||
];
|
||||
try {
|
||||
$data = $this->execute('/vhost/', $params);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception('获取虚拟主机SSL配置失败:' . $e->getMessage());
|
||||
}
|
||||
if (!empty($data['sslcert']['ssl'])) {
|
||||
foreach ($data['sslcert']['ssl'] as $domain => $row) {
|
||||
if (!in_array($domain, $config['domainList'])) continue;
|
||||
$params = [
|
||||
'act' => 'vhostssl',
|
||||
'sitename' => $config['sitename'],
|
||||
'cmd' => 'clearsslcache',
|
||||
'sslid' => $row['sysid'],
|
||||
'dm' => $domain,
|
||||
];
|
||||
try {
|
||||
$this->execute('/vhost/', $params);
|
||||
$this->log('更新' . $domain . '证书缓存成功');
|
||||
} catch (Exception $e) {
|
||||
$this->log('更新' . $domain . '证书缓存失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->log('虚拟主机' . $config['sitename'] . '部署SSL成功');
|
||||
}
|
||||
|
||||
private function execute($path, $params)
|
||||
{
|
||||
$params['username'] = $this->username;
|
||||
$params['time'] = getMillisecond();
|
||||
$params['token'] = md5($this->username . $this->api_password . $params['time']);
|
||||
$response = curl_client($this->baseUrl . $path, str_replace('+', '%20', http_build_query($params)), null, null, null, $this->proxy);
|
||||
$response = mb_convert_encoding($response['body'], 'UTF-8', 'GBK');
|
||||
$arr = json_decode($response, true);
|
||||
if ($arr) {
|
||||
if ($arr['result'] == 200) {
|
||||
return isset($arr['data']) ? $arr['data'] : [];
|
||||
} else {
|
||||
throw new Exception($arr['msg']);
|
||||
}
|
||||
} else {
|
||||
throw new Exception('请求失败(httpCode=' . $response['code'] . ')');
|
||||
}
|
||||
}
|
||||
|
||||
public function setLogger($func)
|
||||
{
|
||||
$this->logger = $func;
|
||||
}
|
||||
|
||||
private function log($txt)
|
||||
{
|
||||
if ($this->logger) {
|
||||
call_user_func($this->logger, $txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,8 @@ class aliyun implements DnsInterface
|
||||
{
|
||||
$this->AccessKeyId = $config['ak'];
|
||||
$this->AccessKeySecret = $config['sk'];
|
||||
$this->client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $this->Endpoint, $this->Version);
|
||||
$proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new AliyunClient($this->AccessKeyId, $this->AccessKeySecret, $this->Endpoint, $this->Version, $proxy);
|
||||
$this->domain = $config['domain'];
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ class baidu implements DnsInterface
|
||||
{
|
||||
$this->AccessKeyId = $config['ak'];
|
||||
$this->SecretAccessKey = $config['sk'];
|
||||
$this->client = new BaiduCloud($this->AccessKeyId, $this->SecretAccessKey, $this->endpoint);
|
||||
$proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new BaiduCloud($this->AccessKeyId, $this->SecretAccessKey, $this->endpoint, $proxy);
|
||||
$this->domain = $config['domain'];
|
||||
$this->domainid = $config['domainid'];
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ class cloudflare implements DnsInterface
|
||||
private $error;
|
||||
private $domain;
|
||||
private $domainid;
|
||||
private $proxy;
|
||||
|
||||
function __construct($config)
|
||||
{
|
||||
@@ -19,6 +20,7 @@ class cloudflare implements DnsInterface
|
||||
$this->ApiKey = $config['sk'];
|
||||
$this->domain = $config['domain'];
|
||||
$this->domainid = $config['domainid'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
}
|
||||
|
||||
public function getError()
|
||||
@@ -261,6 +263,9 @@ class cloudflare implements DnsInterface
|
||||
}
|
||||
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
@@ -13,6 +13,7 @@ class dnsla implements DnsInterface
|
||||
private $error;
|
||||
private $domain;
|
||||
private $domainid;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
@@ -20,6 +21,7 @@ class dnsla implements DnsInterface
|
||||
$this->apisecret = $config['sk'];
|
||||
$this->domain = $config['domain'];
|
||||
$this->domainid = $config['domainid'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
}
|
||||
|
||||
public function getError()
|
||||
@@ -249,10 +251,13 @@ class dnsla implements DnsInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function curl($method, $path, $header, $body = null, $isPut = false)
|
||||
private function curl($method, $path, $header, $body = null)
|
||||
{
|
||||
$url = $this->baseUrl . $path;
|
||||
$ch = curl_init($url);
|
||||
if ($this->proxy) {
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
|
||||
|
||||
@@ -23,7 +23,8 @@ class dnspod implements DnsInterface
|
||||
{
|
||||
$this->SecretId = $config['ak'];
|
||||
$this->SecretKey = $config['sk'];
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, $this->endpoint, $this->service, $this->version);
|
||||
$proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new TencentCloud($this->SecretId, $this->SecretKey, $this->endpoint, $this->service, $this->version, null, $proxy);
|
||||
$this->domain = $config['domain'];
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ class huawei implements DnsInterface
|
||||
{
|
||||
$this->AccessKeyId = $config['ak'];
|
||||
$this->SecretAccessKey = $config['sk'];
|
||||
$this->client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, $this->endpoint);
|
||||
$proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new HuaweiCloud($this->AccessKeyId, $this->SecretAccessKey, $this->endpoint, $proxy);
|
||||
$this->domain = $config['domain'];
|
||||
$this->domainid = $config['domainid'];
|
||||
}
|
||||
@@ -134,7 +135,7 @@ class huawei implements DnsInterface
|
||||
{
|
||||
$Name = $this->getHost($Name);
|
||||
if ($Type == 'TXT' && substr($Value, 0, 1) != '"') $Value = '"' . $Value . '"';
|
||||
$records = explode(',', $Value);
|
||||
$records = array_reverse(explode(',', $Value));
|
||||
$params = ['name' => $Name, 'type' => $this->convertType($Type), 'records' => $records, 'line' => $Line, 'ttl' => intval($TTL), 'description' => $Remark];
|
||||
if ($Type == 'MX') $params['records'][0] = intval($MX) . ' ' . $Value;
|
||||
if ($Weight > 0) $params['weight'] = intval($Weight);
|
||||
@@ -147,7 +148,7 @@ class huawei implements DnsInterface
|
||||
{
|
||||
$Name = $this->getHost($Name);
|
||||
if ($Type == 'TXT' && substr($Value, 0, 1) != '"') $Value = '"' . $Value . '"';
|
||||
$records = explode(',', $Value);
|
||||
$records = array_reverse(explode(',', $Value));
|
||||
$params = ['name' => $Name, 'type' => $this->convertType($Type), 'records' => $records, 'line' => $Line, 'ttl' => intval($TTL), 'description' => $Remark];
|
||||
if ($Type == 'MX') $params['records'][0] = intval($MX) . ' ' . $Value;
|
||||
if ($Weight > 0) $params['weight'] = intval($Weight);
|
||||
|
||||
@@ -32,7 +32,8 @@ class huoshan implements DnsInterface
|
||||
{
|
||||
$this->AccessKeyId = $config['ak'];
|
||||
$this->SecretAccessKey = $config['sk'];
|
||||
$this->client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, $this->endpoint, $this->service, $this->version, $this->region);
|
||||
$proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
$this->client = new Volcengine($this->AccessKeyId, $this->SecretAccessKey, $this->endpoint, $this->service, $this->version, $this->region, $proxy);
|
||||
$this->domain = $config['domain'];
|
||||
$this->domainid = $config['domainid'];
|
||||
}
|
||||
|
||||
@@ -12,11 +12,13 @@ class namesilo implements DnsInterface
|
||||
private $version = '1';
|
||||
private $error;
|
||||
private $domain;
|
||||
private $proxy;
|
||||
|
||||
function __construct($config)
|
||||
{
|
||||
$this->apikey = $config['sk'];
|
||||
$this->domain = $config['domain'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
}
|
||||
|
||||
public function getError()
|
||||
@@ -193,7 +195,7 @@ class namesilo implements DnsInterface
|
||||
$url .= '?' . http_build_query($params);
|
||||
|
||||
try{
|
||||
$response = curl_client($url);
|
||||
$response = curl_client($url, null, null, null, null, $this->proxy);
|
||||
}catch(Exception $e){
|
||||
$this->setError($e->getMessage());
|
||||
return false;
|
||||
|
||||
@@ -15,12 +15,14 @@ class west implements DnsInterface
|
||||
private $error;
|
||||
private $domain;
|
||||
private $domainid;
|
||||
private $proxy;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->username = $config['ak'];
|
||||
$this->api_password = $config['sk'];
|
||||
$this->domain = $config['domain'];
|
||||
$this->proxy = isset($config['proxy']) ? $config['proxy'] == 1 : false;
|
||||
}
|
||||
|
||||
public function getError()
|
||||
@@ -177,10 +179,15 @@ class west implements DnsInterface
|
||||
private function execute($path, $params)
|
||||
{
|
||||
$params['username'] = $this->username;
|
||||
$params['time'] = $this->getMillisecond();
|
||||
$params['time'] = getMillisecond();
|
||||
$params['token'] = md5($this->username.$this->api_password.$params['time']);
|
||||
$response = $this->curl($path, $params);
|
||||
$response = mb_convert_encoding($response, 'UTF-8', 'GBK');
|
||||
try{
|
||||
$response = curl_client($this->baseUrl . $path, http_build_query($params), null, null, null, $this->proxy);
|
||||
}catch(\Exception $e){
|
||||
$this->setError($e->getMessage());
|
||||
return false;
|
||||
}
|
||||
$response = mb_convert_encoding($response['body'], 'UTF-8', 'GBK');
|
||||
$arr = json_decode($response, true);
|
||||
if ($arr) {
|
||||
if ($arr['result'] == 200) {
|
||||
@@ -195,34 +202,6 @@ class west implements DnsInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function curl($path, $params = null)
|
||||
{
|
||||
$url = $this->baseUrl . $path;
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
if ($params) {
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
|
||||
}
|
||||
$response = curl_exec($ch);
|
||||
$errno = curl_errno($ch);
|
||||
if ($errno) {
|
||||
$this->setError('Curl error: ' . curl_error($ch));
|
||||
}
|
||||
curl_close($ch);
|
||||
if ($errno) return false;
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function getMillisecond()
|
||||
{
|
||||
list($s1, $s2) = explode(' ', microtime());
|
||||
return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
|
||||
}
|
||||
|
||||
private function setError($message)
|
||||
{
|
||||
$this->error = $message;
|
||||
|
||||
@@ -131,8 +131,13 @@ class CertDeployService
|
||||
private function saveLog($txt)
|
||||
{
|
||||
if (empty($this->task['processid'])) return;
|
||||
if (!is_dir(app()->getRuntimePath() . 'log')) mkdir(app()->getRuntimePath() . 'log');
|
||||
$file_name = app()->getRuntimePath().'log/'.$this->task['processid'].'.log';
|
||||
$file_exists = file_exists($file_name);
|
||||
file_put_contents($file_name, $txt . PHP_EOL, FILE_APPEND);
|
||||
if (!$file_exists) {
|
||||
@chmod($file_name, 0777);
|
||||
}
|
||||
if(php_sapi_name() == 'cli'){
|
||||
echo $txt . PHP_EOL;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ class CertOrderService
|
||||
foreach($this->domainList as $domain){
|
||||
$mainDomain = getMainDomain($domain);
|
||||
if (!Db::name('domain')->where('name', $mainDomain)->find()) {
|
||||
if (substr($domain, 0, 2) == '*.') $domain = substr($domain, 2);
|
||||
$cname_row = Db::name('cert_cname')->where('domain', $domain)->where('status', 1)->find();
|
||||
if (!$cname || !$cname_row) {
|
||||
$errmsg = '域名'.$domain.'未在本系统添加';
|
||||
@@ -116,7 +117,9 @@ class CertOrderService
|
||||
$this->saveLog(date('Y-m-d H:i:s').' - 开始添加DNS记录');
|
||||
$this->addDns();
|
||||
$this->saveLog('添加DNS记录成功,请等待生效后进行验证...');
|
||||
Db::name('cert_order')->where('id', $this->order['id'])->update(['retrytime' => date('Y-m-d H:i:s', time() + 300)]);
|
||||
if (CertHelper::$cert_config[$this->atype]['cname']) {
|
||||
Db::name('cert_order')->where('id', $this->order['id'])->update(['retrytime' => date('Y-m-d H:i:s', time() + 180)]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
// step4: 查询DNS
|
||||
@@ -417,8 +420,13 @@ class CertOrderService
|
||||
private function saveLog($txt)
|
||||
{
|
||||
if (empty($this->order['processid'])) return;
|
||||
if (!is_dir(app()->getRuntimePath() . 'log')) mkdir(app()->getRuntimePath() . 'log');
|
||||
$file_name = app()->getRuntimePath().'log/'.$this->order['processid'].'.log';
|
||||
$file_exists = file_exists($file_name);
|
||||
file_put_contents($file_name, $txt . PHP_EOL, FILE_APPEND);
|
||||
if (!$file_exists) {
|
||||
@chmod($file_name, 0777);
|
||||
}
|
||||
if(php_sapi_name() == 'cli'){
|
||||
echo $txt . PHP_EOL;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class CertTaskService
|
||||
$retcode = $service->process();
|
||||
if ($retcode == 3) {
|
||||
echo 'ID:'.$row['id'].' 证书已签发成功!'.PHP_EOL;
|
||||
if($row['issend'] == 0) MsgNotice::cert_send($row['id'], true);
|
||||
if($row['issend'] == 0) MsgNotice::cert_order_send($row['id'], true);
|
||||
} elseif ($retcode == 1) {
|
||||
echo 'ID:'.$row['id'].' 添加DNS记录成功!'.PHP_EOL;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class CertTaskService
|
||||
if ($e->getCode() == 102) {
|
||||
break;
|
||||
} elseif ($e->getCode() == 103) {
|
||||
if($row['issend'] == 0) MsgNotice::cert_send($row['id'], false);
|
||||
if($row['issend'] == 0) MsgNotice::cert_order_send($row['id'], false);
|
||||
} else {
|
||||
$failcount++;
|
||||
}
|
||||
@@ -74,14 +74,14 @@ class CertTaskService
|
||||
$service = new CertDeployService($row['id']);
|
||||
$service->process();
|
||||
echo 'ID:'.$row['id'].' 部署任务执行成功!'.PHP_EOL;
|
||||
if($row['issend'] == 0) MsgNotice::deploy_send($row['id'], true);
|
||||
if($row['issend'] == 0) MsgNotice::cert_deploy_send($row['id'], true);
|
||||
$count++;
|
||||
} catch (Exception $e) {
|
||||
echo 'ID:'.$row['id'].' '.$e->getMessage().PHP_EOL;
|
||||
if ($e->getCode() == 102) {
|
||||
break;
|
||||
} elseif ($e->getCode() == 103) {
|
||||
if($row['issend'] == 0) MsgNotice::deploy_send($row['id'], false);
|
||||
if($row['issend'] == 0) MsgNotice::cert_deploy_send($row['id'], false);
|
||||
} else {
|
||||
$count++;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ CREATE TABLE `dnsmgr_account` (
|
||||
`ak` varchar(256) DEFAULT NULL,
|
||||
`sk` varchar(256) DEFAULT NULL,
|
||||
`ext` varchar(256) DEFAULT NULL,
|
||||
`proxy` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`remark` varchar(100) DEFAULT NULL,
|
||||
`addtime` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
|
||||
@@ -149,4 +149,7 @@ CREATE TABLE IF NOT EXISTS `dnsmgr_cert_cname` (
|
||||
`addtime` datetime DEFAULT NULL,
|
||||
`status` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
ALTER TABLE `dnsmgr_account`
|
||||
ADD COLUMN `proxy` tinyint(1) NOT NULL DEFAULT '0';
|
||||
@@ -39,6 +39,9 @@ class CertDnsUtils
|
||||
usort($list, function ($a, $b) {
|
||||
return strcmp($a['name'], $b['name']);
|
||||
});
|
||||
if ($drow['type'] == 'huawei') {
|
||||
$list = self::getHuaweiDnsRecords($list);
|
||||
}
|
||||
$records = [];
|
||||
foreach ($list as $row) {
|
||||
$domain = $row['name'] . '.' . $mainDomain;
|
||||
@@ -46,7 +49,8 @@ class CertDnsUtils
|
||||
if (!$records[$row['name']]) throw new Exception('获取'.$domain.'记录列表失败,'.$dns->getError());
|
||||
|
||||
$filter_records = array_filter($records[$row['name']]['list'], function ($v) use ($row) {
|
||||
return $v['Type'] == $row['type'] && $v['Value'] == $row['value'];
|
||||
if (is_array($v['Value'])) $v['Value'] = implode(',', $v['Value']);
|
||||
return $v['Type'] == $row['type'] && ($v['Value'] == $row['value'] || rtrim($v['Value'], '.') == $row['value']);
|
||||
});
|
||||
if (!empty($filter_records)) {
|
||||
foreach ($filter_records as $recordid => $record) {
|
||||
@@ -76,6 +80,22 @@ class CertDnsUtils
|
||||
}
|
||||
}
|
||||
|
||||
private static function getHuaweiDnsRecords($list)
|
||||
{
|
||||
//将name相同的TXT记录合并
|
||||
$txt_records = [];
|
||||
foreach ($list as $key => $row) {
|
||||
if ($row['type'] == 'TXT') {
|
||||
$txt_records[$row['name']][] = $row['value'];
|
||||
unset($list[$key]);
|
||||
}
|
||||
}
|
||||
foreach ($txt_records as $name => $rows) {
|
||||
$list[] = ['name' => $name, 'type' => 'TXT', 'value' => '"' . implode('","', $rows) . '"'];
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
public static function delDns($dnsList, callable $log, $cname = false)
|
||||
{
|
||||
$cnameDomainList = [];
|
||||
@@ -107,6 +127,9 @@ class CertDnsUtils
|
||||
usort($list, function ($a, $b) {
|
||||
return strcmp($a['name'], $b['name']);
|
||||
});
|
||||
if ($drow['type'] == 'huawei') {
|
||||
$list = self::getHuaweiDnsRecords($list);
|
||||
}
|
||||
$records = [];
|
||||
foreach ($list as $row) {
|
||||
//if ($row['type'] == 'CAA') continue;
|
||||
@@ -115,6 +138,7 @@ class CertDnsUtils
|
||||
if (!$records[$row['name']]) throw new Exception('获取'.$domain.'记录列表失败,'.$dns->getError());
|
||||
|
||||
$filter_records = array_filter($records[$row['name']]['list'], function ($v) use ($row) {
|
||||
if (is_array($v['Value'])) $v['Value'] = implode(',', $v['Value']);
|
||||
return $v['Type'] == $row['type'] && ($v['Value'] == $row['value'] || rtrim($v['Value'], '.') == $row['value']);
|
||||
});
|
||||
if (empty($filter_records)) continue;
|
||||
|
||||
@@ -74,9 +74,13 @@ class CheckUtils
|
||||
|
||||
public static function tcp($target, $port, $timeout)
|
||||
{
|
||||
if (substr($target, -1) == '.') $target = substr($target, 0, -1);
|
||||
if (!filter_var($target, FILTER_VALIDATE_IP) && checkDomain($target)) {
|
||||
$target = gethostbyname($target);
|
||||
if (!$target) return ['status' => false, 'error' => 'DNS resolve failed', 'usetime' => 0];
|
||||
if (!$target) return ['status' => false, 'errmsg' => 'DNS resolve failed', 'usetime' => 0];
|
||||
}
|
||||
if (filter_var($target, FILTER_VALIDATE_IP) && strpos($target, ':') !== false) {
|
||||
$target = '['.$target.']';
|
||||
}
|
||||
$starttime = getMillisecond();
|
||||
$fp = @fsockopen($target, $port, $errCode, $errStr, $timeout);
|
||||
@@ -93,13 +97,14 @@ class CheckUtils
|
||||
|
||||
public static function ping($target)
|
||||
{
|
||||
if (!function_exists('exec')) return ['status' => false, 'error' => 'exec函数不可用', 'usetime' => 0];
|
||||
if (!function_exists('exec')) return ['status' => false, 'errmsg' => 'exec函数不可用', 'usetime' => 0];
|
||||
if (substr($target, -1) == '.') $target = substr($target, 0, -1);
|
||||
if (!filter_var($target, FILTER_VALIDATE_IP) && checkDomain($target)) {
|
||||
$target = gethostbyname($target);
|
||||
if (!$target) return ['status' => false, 'error' => 'DNS resolve failed', 'usetime' => 0];
|
||||
if (!$target) return ['status' => false, 'errmsg' => 'DNS resolve failed', 'usetime' => 0];
|
||||
}
|
||||
if (!filter_var($target, FILTER_VALIDATE_IP)) {
|
||||
return ['status' => false, 'error' => 'Invalid IP address', 'usetime' => 0];
|
||||
return ['status' => false, 'errmsg' => 'Invalid IP address', 'usetime' => 0];
|
||||
}
|
||||
$timeout = 1;
|
||||
exec('ping -c 1 -w '.$timeout.' '.$target.'', $output, $return_var);
|
||||
|
||||
@@ -13,7 +13,7 @@ class MsgNotice
|
||||
{
|
||||
if ($action == 1) {
|
||||
$mail_title = 'DNS容灾切换-发生告警通知';
|
||||
$mail_content = '尊敬的系统管理员,您好:<br/>您的域名 <b>'.$task['domain'].'</b> 的 <b>'.$task['main_value'].'</b> 记录发生了异常';
|
||||
$mail_content = '尊敬的用户,您好:<br/>您的域名 <b>'.$task['domain'].'</b> 的 <b>'.$task['main_value'].'</b> 记录发生了异常';
|
||||
if ($task['type'] == 2) {
|
||||
$mail_content .= ',已自动切换为备用解析记录 '.$task['backup_value'].' ';
|
||||
} elseif ($task['type'] == 1) {
|
||||
@@ -22,11 +22,11 @@ class MsgNotice
|
||||
$mail_content .= ',请及时处理';
|
||||
}
|
||||
if (!empty($result['errmsg'])) {
|
||||
$mail_content .= '。<br/>异常信息:'.$result['errmsg'];
|
||||
$mail_content .= '。<br/>异常信息:<font color="warning">'.$result['errmsg'].'</font>';
|
||||
}
|
||||
} else {
|
||||
$mail_title = 'DNS容灾切换-恢复正常通知';
|
||||
$mail_content = '尊敬的系统管理员,您好:<br/>您的域名 <b>'.$task['domain'].'</b> 的 <b>'.$task['main_value'].'</b> 记录已恢复正常';
|
||||
$mail_content = '尊敬的用户,您好:<br/>您的域名 <b>'.$task['domain'].'</b> 的 <b>'.$task['main_value'].'</b> 记录已恢复正常';
|
||||
if ($task['type'] == 2) {
|
||||
$mail_content .= ',已自动切换回当前解析记录';
|
||||
} elseif ($task['type'] == 1) {
|
||||
@@ -41,7 +41,7 @@ class MsgNotice
|
||||
if (!empty($task['remark'])) {
|
||||
$mail_content .= '<br/>备注:'.$task['remark'];
|
||||
}
|
||||
$mail_content .= '<br/>'.self::$sitename.'<br/>'.date('Y-m-d H:i:s');
|
||||
$mail_content .= '<br/><font color="grey">'.self::$sitename.'</font><br/><font color="grey">'.date('Y-m-d H:i:s').'</font>';
|
||||
|
||||
if (config_get('notice_mail') == 1) {
|
||||
$mail_name = config_get('mail_recv') ? config_get('mail_recv') : config_get('mail_name');
|
||||
@@ -49,16 +49,20 @@ class MsgNotice
|
||||
}
|
||||
if (config_get('notice_wxtpl') == 1) {
|
||||
$content = str_replace(['<br/>', '<b>', '</b>'], ["\n\n", '**', '**'], $mail_content);
|
||||
self::send_wechat_tplmsg($mail_title, $content);
|
||||
self::send_wechat_tplmsg($mail_title, strip_tags($content));
|
||||
}
|
||||
if (config_get('notice_tgbot') == 1) {
|
||||
$content = str_replace('<br/>', "\n", $mail_content);
|
||||
$content = "<strong>".$mail_title."</strong>\n".$content;
|
||||
$content = "<strong>".$mail_title."</strong>\n".strip_tags($content);
|
||||
self::send_telegram_bot($content);
|
||||
}
|
||||
if (config_get('notice_webhook') == 1) {
|
||||
$content = str_replace(['<br/>', '<b>', '</b>'], ["\n", '**', '**'], $mail_content);
|
||||
self::send_webhook($mail_title, $content);
|
||||
}
|
||||
}
|
||||
|
||||
public static function cert_send($id, $result)
|
||||
public static function cert_order_send($id, $result)
|
||||
{
|
||||
$row = Db::name('cert_order')->field('id,aid,issuetime,expiretime,issuer,status,error')->where('id', $id)->find();
|
||||
if (!$row) return;
|
||||
@@ -71,7 +75,7 @@ class MsgNotice
|
||||
} else {
|
||||
$mail_title = $domainList[0] . '域名SSL证书签发成功通知';
|
||||
}
|
||||
$mail_content = '尊敬的用户,您好:您的SSL证书已签发成功!<br/>证书账户:'.CertHelper::$cert_config[$type]['name'].'('.$row['aid'].')<br/>证书域名:'.implode('、', $domainList).'<br/>签发时间:'.$row['issuetime'].'<br/>到期时间:'.$row['expiretime'].'<br/>颁发机构:'.$row['issuer'];
|
||||
$mail_content = '尊敬的用户,您好:您的SSL证书已签发成功!<br/><b>证书账户:</b> '.CertHelper::$cert_config[$type]['name'].'('.$row['aid'].')<br/><b>证书域名:</b> '.implode('、', $domainList).'<br/><b>签发时间:</b> '.$row['issuetime'].'<br/><b>到期时间:</b> '.$row['expiretime'].'<br/><b>颁发机构:</b> '.$row['issuer'];
|
||||
} else {
|
||||
$status_arr = [0 => '失败', -1 => '购买证书失败', -2 => '创建订单失败', -3 => '添加DNS失败', -4 => '验证DNS失败', -5 => '验证订单失败', -6 => '订单验证未通过', -7 => '签发证书失败'];
|
||||
if(count($domainList) > 1){
|
||||
@@ -79,27 +83,15 @@ class MsgNotice
|
||||
}else{
|
||||
$mail_title = $domainList[0].'域名SSL证书'.$status_arr[$row['status']].'通知';
|
||||
}
|
||||
$mail_content = '尊敬的用户,您好:您的SSL证书'.$status_arr[$row['status']].'!<br/>证书账户:'.CertHelper::$cert_config[$type]['name'].'('.$row['aid'].')<br/>证书域名:'.implode('、', $domainList).'<br/>失败时间:'.date('Y-m-d H:i:s').'<br/>失败原因:'.$row['error'];
|
||||
$mail_content = '尊敬的用户,您好:您的SSL证书'.$status_arr[$row['status']].'!<br/><b>证书账户:</b> '.CertHelper::$cert_config[$type]['name'].'('.$row['aid'].')<br/><b>证书域名:</b> '.implode('、', $domainList).'<br/><b>失败时间:</b> '.date('Y-m-d H:i:s').'<br/><b>失败原因:</b> <font color="warning">'.$row['error'].'</font>';
|
||||
}
|
||||
$mail_content .= '<br/>'.self::$sitename.'<br/>'.date('Y-m-d H:i:s');
|
||||
$mail_content .= '<br/><font color="grey">'.self::$sitename.'</font><br/><font color="grey">'.date('Y-m-d H:i:s').'</font>';
|
||||
|
||||
if (config_get('cert_notice_mail') == 1 || config_get('cert_notice_mail') == 2 && !$result) {
|
||||
$mail_name = config_get('mail_recv') ? config_get('mail_recv') : config_get('mail_name');
|
||||
self::send_mail($mail_name, $mail_title, $mail_content);
|
||||
}
|
||||
if (config_get('cert_notice_wxtpl') == 1 || config_get('cert_notice_wxtpl') == 2 && !$result) {
|
||||
$content = str_replace(['<br/>', '<b>', '</b>'], ["\n\n", '**', '**'], $mail_content);
|
||||
self::send_wechat_tplmsg($mail_title, $content);
|
||||
}
|
||||
if (config_get('cert_notice_tgbot') == 1 || config_get('cert_notice_tgbot') == 2 && !$result) {
|
||||
$content = str_replace('<br/>', "\n", $mail_content);
|
||||
$content = "<strong>" . $mail_title . "</strong>\n" . $content;
|
||||
self::send_telegram_bot($content);
|
||||
}
|
||||
self::cert_send($mail_title, $mail_content, $result);
|
||||
Db::name('cert_order')->where('id', $id)->update(['issend' => 1]);
|
||||
}
|
||||
|
||||
public static function deploy_send($id, $result)
|
||||
public static function cert_deploy_send($id, $result)
|
||||
{
|
||||
$row = Db::name('cert_deploy')->field('id,aid,oid,remark,status,error')->where('id', $id)->find();
|
||||
if (!$row) return;
|
||||
@@ -108,28 +100,37 @@ class MsgNotice
|
||||
$typename = DeployHelper::$deploy_config[$account['type']]['name'];
|
||||
$mail_title = $typename;
|
||||
if(!empty($row['remark'])) $mail_title .= '('.$row['remark'].')';
|
||||
$mail_title .= '证书部署'.($result?'成功':'失败').'通知';
|
||||
$mail_title .= 'SSL证书部署'.($result?'成功':'失败').'通知';
|
||||
if ($result) {
|
||||
$mail_content = '尊敬的用户,您好:您的SSL证书已成功部署到'.$typename.'!<br/>自动部署账户:['.$account['id'].']'.$typename.'('.($account['remark']?$account['remark']:$account['name']).')<br/>关联SSL证书:['.$row['oid'].']'.implode('、', $domainList).'<br/>任务备注:'.($row['remark']?$row['remark']:'无');
|
||||
$mail_content = '尊敬的用户,您好:您的SSL证书已成功部署到'.$typename.'!<br/><b>自动部署账户:</b> ['.$account['id'].']'.$typename.'('.($account['remark']?$account['remark']:$account['name']).')<br/><b>关联SSL证书:</b> ['.$row['oid'].']'.implode('、', $domainList).'<br/><b>任务备注:</b> '.($row['remark']?$row['remark']:'无');
|
||||
} else {
|
||||
$mail_content = '尊敬的用户,您好:您的SSL证书部署失败!<br/>失败原因:'.$row['error'].'<br/>自动部署账户:['.$account['id'].']'.$typename.'('.($account['remark']?$account['remark']:$account['name']).')<br/>关联SSL证书:['.$row['oid'].']'.implode('、', $domainList).'<br/>任务备注:'.($row['remark']?$row['remark']:'无');
|
||||
$mail_content = '尊敬的用户,您好:您的SSL证书部署失败!<br/><b>失败原因:</b> <font color="warning">'.$row['error'].'</font><br/><b>自动部署账户:</b> ['.$account['id'].']'.$typename.'('.($account['remark']?$account['remark']:$account['name']).')<br/><b>关联SSL证书:</b> ['.$row['oid'].']'.implode('、', $domainList).'<br/><b>任务备注:</b> '.($row['remark']?$row['remark']:'无');
|
||||
}
|
||||
$mail_content .= '<br/>'.self::$sitename.'<br/>'.date('Y-m-d H:i:s');
|
||||
$mail_content .= '<br/><font color="grey">'.self::$sitename.'</font><br/><font color="grey">'.date('Y-m-d H:i:s').'</font>';
|
||||
|
||||
self::cert_send($mail_title, $mail_content, $result);
|
||||
Db::name('cert_deploy')->where('id', $id)->update(['issend' => 1]);
|
||||
}
|
||||
|
||||
private static function cert_send($mail_title, $mail_content, $result)
|
||||
{
|
||||
if (config_get('cert_notice_mail') == 1 || config_get('cert_notice_mail') == 2 && !$result) {
|
||||
$mail_name = config_get('mail_recv') ? config_get('mail_recv') : config_get('mail_name');
|
||||
self::send_mail($mail_name, $mail_title, $mail_content);
|
||||
}
|
||||
if (config_get('cert_notice_wxtpl') == 1 || config_get('cert_notice_wxtpl') == 2 && !$result) {
|
||||
$content = str_replace(['<br/>', '<b>', '</b>'], ["\n\n", '**', '**'], $mail_content);
|
||||
self::send_wechat_tplmsg($mail_title, $content);
|
||||
self::send_wechat_tplmsg($mail_title, strip_tags($content));
|
||||
}
|
||||
if (config_get('cert_notice_tgbot') == 1 || config_get('cert_notice_tgbot') == 2 && !$result) {
|
||||
$content = str_replace('<br/>', "\n", $mail_content);
|
||||
$content = "<strong>" . $mail_title . "</strong>\n" . $content;
|
||||
$content = "<strong>".$mail_title."</strong>\n".strip_tags($content);
|
||||
self::send_telegram_bot($content);
|
||||
}
|
||||
Db::name('cert_deploy')->where('id', $id)->update(['issend' => 1]);
|
||||
if (config_get('cert_notice_webhook') == 1) {
|
||||
$content = str_replace(['*', '<br/>', '<b>', '</b>'], ['\*', "\n", '**', '**'], $mail_content);
|
||||
self::send_webhook($mail_title, $content);
|
||||
}
|
||||
}
|
||||
|
||||
public static function send_mail($to, $sub, $msg)
|
||||
@@ -187,7 +188,7 @@ class MsgNotice
|
||||
if (isset($arr['success']) && $arr['success'] == true) {
|
||||
return true;
|
||||
} else {
|
||||
return $arr['msg'];
|
||||
return isset($arr['msg']) ? $arr['msg'] : '请求失败';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +204,48 @@ class MsgNotice
|
||||
if (isset($arr['ok']) && $arr['ok'] == true) {
|
||||
return true;
|
||||
} else {
|
||||
return $arr['description'];
|
||||
return isset($arr['description']) ? $arr['description'] : '请求失败';
|
||||
}
|
||||
}
|
||||
|
||||
public static function send_webhook($title, $content)
|
||||
{
|
||||
$url = config_get('webhook_url');
|
||||
if (!$url || !parse_url($url)) return false;
|
||||
if (strpos($url, 'oapi.dingtalk.com')) {
|
||||
$content = '### '.$title." \n ".str_replace("\n", " \n ", $content);
|
||||
$post = [
|
||||
'msgtype' => 'markdown',
|
||||
'markdown' => [
|
||||
'title' => $title,
|
||||
'text' => $content,
|
||||
],
|
||||
];
|
||||
} elseif (strpos($url, 'qyapi.weixin.qq.com')) {
|
||||
$content = '## '.$title."\n".$content;
|
||||
$post = [
|
||||
'msgtype' => 'markdown',
|
||||
'markdown' => [
|
||||
'content' => $content,
|
||||
],
|
||||
];
|
||||
} elseif (strpos($url, 'open.feishu.cn') || strpos($url, 'open.larksuite.com')) {
|
||||
$content = str_replace(['\*', '**'], ['*', ''], strip_tags($content));
|
||||
$post = [
|
||||
'msg_type' => 'text',
|
||||
'content' => [
|
||||
'text' => $content,
|
||||
],
|
||||
];
|
||||
} else {
|
||||
return '不支持的Webhook地址';
|
||||
}
|
||||
$result = get_curl($url, json_encode($post), 0, 0, 0, 0, 0, ['Content-Type: application/json; charset=UTF-8']);
|
||||
$arr = json_decode($result, true);
|
||||
if (isset($arr['errcode']) && $arr['errcode'] == 0 || isset($arr['code']) && $arr['code'] == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return isset($arr['errmsg']) ? $arr['errmsg'] : (isset($arr['msg']) ? $arr['msg'] : '请求失败');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,28 +253,10 @@ class MsgNotice
|
||||
{
|
||||
$ch = curl_init();
|
||||
if (config_get('tgbot_proxy') == 1) {
|
||||
$proxy_server = config_get('proxy_server');
|
||||
$proxy_port = intval(config_get('proxy_port'));
|
||||
$proxy_userpwd = config_get('proxy_user').':'.config_get('proxy_pwd');
|
||||
$proxy_type = config_get('proxy_type');
|
||||
if ($proxy_type == 'https') {
|
||||
$proxy_type = CURLPROXY_HTTPS;
|
||||
} elseif ($proxy_type == 'sock4') {
|
||||
$proxy_type = CURLPROXY_SOCKS4;
|
||||
} elseif ($proxy_type == 'sock5') {
|
||||
$proxy_type = CURLPROXY_SOCKS5;
|
||||
} else {
|
||||
$proxy_type = CURLPROXY_HTTP;
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
|
||||
curl_setopt($ch, CURLOPT_PROXY, $proxy_server);
|
||||
curl_setopt($ch, CURLOPT_PROXYPORT, $proxy_port);
|
||||
if ($proxy_userpwd != ':') {
|
||||
curl_setopt($ch, CURLOPT_PROXYUSERPWD, $proxy_userpwd);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_PROXYTYPE, $proxy_type);
|
||||
curl_set_proxy($ch);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
$httpheader[] = "Accept: */*";
|
||||
|
||||
@@ -150,7 +150,6 @@ new Vue({
|
||||
})
|
||||
return {label: classList[key], children: tempList}
|
||||
})
|
||||
console.log(this.typeOption);
|
||||
if(this.action == 'edit'){
|
||||
Object.keys(info).forEach((key) => {
|
||||
this.set[key] = info[key]
|
||||
@@ -159,7 +158,9 @@ new Vue({
|
||||
this.inputs = typeList[this.set.type].inputs;
|
||||
this.note = typeList[this.set.type].note;
|
||||
$.each(this.inputs, (name, item) => {
|
||||
item.value = config[name];
|
||||
if(typeof config[name] != 'undefined'){
|
||||
item.value = config[name];
|
||||
}
|
||||
if(typeof item.value == 'undefined'){
|
||||
if(item.type == 'checkbox'){
|
||||
item.value = false;
|
||||
|
||||
@@ -29,7 +29,16 @@ pre.pre-log{height: 330px;overflow-y: auto;width: 100%;background-color: rgba(51
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"><i class="fa fa-search"></i> 搜索</button>
|
||||
<a href="javascript:searchClear()" class="btn btn-default" title="刷新订单列表"><i class="fa fa-refresh"></i> 刷新</a>
|
||||
<a href="/cert/order/add" class="btn btn-success"><i class="fa fa-plus"></i> 添加</a>
|
||||
<div class="btn-group">
|
||||
<a href="/cert/order/add" class="btn btn-success"><i class="fa fa-plus"></i> 添加</a>
|
||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/cert/order/import">导入已有证书</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<table id="listTable">
|
||||
@@ -130,6 +139,16 @@ $(document).ready(function(){
|
||||
} else if(value == 2) {
|
||||
return '<span class="label" style="background-color: #3e76fb;">正在验证</span>';
|
||||
} else if(value == 1) {
|
||||
if(row.retrytime != null){
|
||||
var now = new Date().getTime();
|
||||
var retry = new Date(row.retrytime).getTime();
|
||||
var diff = retry - now;
|
||||
if(diff > 0){
|
||||
var min = Math.floor(diff / 60000);
|
||||
var sec = Math.floor((diff - min * 60000) / 1000);
|
||||
return '<span title="'+min+'分'+sec+'秒后自动验证" data-toggle="tooltip" data-placement="top" class="label" style="background-color: #3e76fb;">待验证</span>';
|
||||
}
|
||||
}
|
||||
return '<span class="label" style="background-color: #3e76fb;">待验证</span>';
|
||||
} else if(value == 0) {
|
||||
return '<span class="label label-info">待提交</span>';
|
||||
@@ -142,6 +161,16 @@ $(document).ready(function(){
|
||||
else if(value == -5) title = '验证订单失败';
|
||||
else if(value == -6) title = '订单验证未通过';
|
||||
else if(value == -7) title = '签发证书失败';
|
||||
if(row.retrytime != null){
|
||||
var now = new Date().getTime();
|
||||
var retry = new Date(row.retrytime).getTime();
|
||||
var diff = retry - now;
|
||||
if(diff > 0){
|
||||
var min = Math.floor(diff / 60000);
|
||||
var sec = Math.floor((diff - min * 60000) / 1000);
|
||||
return '<span title="'+min+'分'+sec+'秒后自动重试" data-toggle="tooltip" data-placement="top" class="label label-danger">'+title+'</span>'+(row.error?' <span onclick="showmsg(\''+row.error+'\')" class="tips" title="失败原因"><i class="fa fa-info-circle"></i></span>':'');
|
||||
}
|
||||
}
|
||||
return '<span class="label label-danger">'+title+'</span>'+(row.error?' <span onclick="showmsg(\''+row.error+'\')" class="tips" title="失败原因"><i class="fa fa-info-circle"></i></span>':'');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,10 @@
|
||||
<label class="col-sm-3 control-label">Telegram机器人通知</label>
|
||||
<div class="col-sm-9"><select class="form-control" name="cert_notice_tgbot" default="{:config_get('cert_notice_tgbot')}"><option value="0">关闭</option><option value="1">开启</option><option value="2">开启(仅失败时)</option></select></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">群机器人Webhook</label>
|
||||
<div class="col-sm-9"><select class="form-control" name="cert_notice_webhook" default="{:config_get('cert_notice_webhook')}"><option value="0">关闭</option><option value="1">开启</option><option value="2">开启(仅失败时)</option></select></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9"><input type="submit" name="submit" value="保存" class="btn btn-primary btn-block"/></div>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<style>
|
||||
.copy-btn{color:#52c41a;cursor:pointer;margin-right: 5px;}
|
||||
.copy-btn:hover{color:#85ef79;}
|
||||
.btn-refresh{margin-left:5px;font-size:10px;background-color:#6896cf}
|
||||
tbody tr>td:nth-child(3){word-break:break-all;max-width:180px;}
|
||||
tbody tr>td:nth-child(4){word-break:break-all;max-width:260px;}
|
||||
</style>
|
||||
@@ -120,7 +121,7 @@ $(document).ready(function(){
|
||||
} else {
|
||||
html += '<span class="label label-warning">未验证</span>';
|
||||
}
|
||||
html += ' <a href="javascript:checkItem('+row.id+')" title="立即验证" class="btn btn-primary btn-xs"><i class="fa fa-refresh"></i></a>';
|
||||
html += '<a href="javascript:checkItem('+row.id+')" title="立即验证" class="btn btn-primary btn-xs btn-refresh"><i class="fa fa-refresh"></i></a>';
|
||||
return html;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -160,7 +160,9 @@ new Vue({
|
||||
this.inputs = typeList[this.set.type].taskinputs;
|
||||
this.note = typeList[this.set.type].tasknote;
|
||||
$.each(this.inputs, (name, item) => {
|
||||
item.value = config[name];
|
||||
if(typeof config[name] != 'undefined'){
|
||||
item.value = config[name];
|
||||
}
|
||||
if(typeof item.value == 'undefined'){
|
||||
if(item.type == 'checkbox'){
|
||||
item.value = false;
|
||||
@@ -183,7 +185,7 @@ new Vue({
|
||||
if(document.referrer.indexOf('&oid=') > 0){
|
||||
var oid = document.referrer.split('&oid=')[1].split('&')[0];
|
||||
if(oid){
|
||||
$('select[name=oid]').val(20).trigger('change');
|
||||
$('select[name=oid]').val(oid).trigger('change');
|
||||
that.set.oid = oid;
|
||||
}
|
||||
}
|
||||
|
||||
167
app/view/cert/order_import.html
Normal file
167
app/view/cert/order_import.html
Normal file
@@ -0,0 +1,167 @@
|
||||
{extend name="common/layout" /}
|
||||
{block name="title"}导入已有证书{/block}
|
||||
{block name="main"}
|
||||
<style>
|
||||
.tips{color: #f6a838; padding-left: 5px;}
|
||||
.control-label[is-required]:before {
|
||||
content: "*";
|
||||
color: #f56c6c;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.input-group-addon{padding: 6px 6px;}
|
||||
</style>
|
||||
<div class="row" id="app">
|
||||
<div class="col-xs-12 center-block" style="float: none;">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><h3 class="panel-title"><a href="/cert/certorder" class="btn btn-sm btn-default pull-right" style="margin-top:-6px"><i class="fa fa-reply fa-fw"></i> 返回</a>导入已有证书</h3></div>
|
||||
<div class="panel-body">
|
||||
<form onsubmit="return false" method="post" class="form-horizontal" role="form" id="taskform">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right" is-required>证书内容</label>
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group">
|
||||
<textarea name="fullchain" v-model="set.fullchain" class="form-control" rows="5" placeholder="输入PEM格式证书链" required></textarea>
|
||||
<a class="btn btn-default input-group-addon" @click="upload('fullchain')" title="上传证书文件"><i class="fa fa-upload"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right" is-required>私钥内容</label>
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group">
|
||||
<textarea name="privatekey" v-model="set.privatekey" class="form-control" rows="5" placeholder="输入PEM格式私钥" required></textarea>
|
||||
<a class="btn btn-default input-group-addon" @click="upload('privatekey')" title="上传私钥文件"><i class="fa fa-upload"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 col-xs-12 control-label no-padding-right" is-required>证书续期账户</label>
|
||||
<div class="col-sm-6"><select name="aid" v-model="set.aid" class="form-control" required>
|
||||
<option value="">--选择证书账户--</option>
|
||||
{foreach $accounts as $k=>$v}
|
||||
<option value="{$k}" data-type="{$v.type}">{$v.name}</option>
|
||||
{/foreach}
|
||||
</select></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right" is-required>签名算法</label>
|
||||
<div class="col-sm-6">
|
||||
<label class="radio-inline" v-for="item in keytypeList">
|
||||
<input type="radio" name="keytype" :value="item" v-model="set.keytype"> {{item}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right" is-required>密钥长度</label>
|
||||
<div class="col-sm-6">
|
||||
<label class="radio-inline" v-for="item in keysizeList">
|
||||
<input type="radio" name="keysize" :value="item.value" v-model="set.keysize"> {{item.label}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-6"><button type="button" class="btn btn-primary" @click="submit">提交</button></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
{block name="script"}
|
||||
<script src="{$cdnpublic}vue/2.6.14/vue.min.js"></script>
|
||||
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
|
||||
<script src="/static/js/bootstrapValidator.min.js"></script>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
type: '',
|
||||
set: {
|
||||
fullchain: '',
|
||||
privatekey: '',
|
||||
aid: '',
|
||||
keytype: '',
|
||||
keysize: '',
|
||||
},
|
||||
keytypeList: [
|
||||
'RSA',
|
||||
'ECC'
|
||||
],
|
||||
keysizeMap: [
|
||||
{label:'2048 bit',value:'2048',type:'RSA'},
|
||||
{label:'3072 bit',value:'3072',type:'RSA'},
|
||||
{label:'P-256',value:'256',type:'ECC'},
|
||||
{label:'P-384',value:'384',type:'ECC'},
|
||||
],
|
||||
keysizeList: [],
|
||||
},
|
||||
watch: {
|
||||
'set.aid': function(val){
|
||||
this.type = $('option:selected', 'select[name=aid]').data('type');
|
||||
},
|
||||
'set.keytype': function(val){
|
||||
this.keysizeList = this.keysizeMap.filter((item) => {
|
||||
return item.type == val;
|
||||
})
|
||||
if(!this.keysizeList.filter((item) => {return item.value == this.set.keysize}).length)
|
||||
this.set.keysize = this.keysizeList[0].value;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.set.keytype = 'RSA';
|
||||
$("#taskform").bootstrapValidator({
|
||||
live: 'submitted',
|
||||
});
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
},
|
||||
methods: {
|
||||
submit(){
|
||||
var that=this;
|
||||
$("#taskform").data("bootstrapValidator").validate();
|
||||
if(!$("#taskform").data("bootstrapValidator").isValid()){
|
||||
return false;
|
||||
}
|
||||
var ii = layer.load(2, {shade:[0.1,'#fff']});
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "",
|
||||
data: this.set,
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.alert(data.msg, {icon: 1}, function(){
|
||||
if(document.referrer.indexOf('/cert/certorder?') > 0)
|
||||
window.location.href = document.referrer;
|
||||
else
|
||||
window.location.href = '/cert/certorder';
|
||||
});
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2});
|
||||
}
|
||||
},
|
||||
error: function(data){
|
||||
layer.close(ii);
|
||||
layer.msg('服务器错误');
|
||||
}
|
||||
});
|
||||
},
|
||||
upload(name){
|
||||
//读取上传文件并填充到表单
|
||||
var file = document.createElement('input');
|
||||
file.type = 'file';
|
||||
file.accept = '.pem,.crt,.key';
|
||||
file.style.display = 'none';
|
||||
file.onchange = function(){
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e){
|
||||
this.set[name] = e.target.result;
|
||||
}.bind(this);
|
||||
reader.readAsText(file.files[0]);
|
||||
}.bind(this);
|
||||
document.body.appendChild(file);
|
||||
file.click();
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
{/block}
|
||||
@@ -103,7 +103,7 @@
|
||||
{if request()->user['type'] eq 'user'}<li class="{:checkIfActive('index')}">
|
||||
<a href="/"><i class="fa fa-home fa-fw"></i> <span>后台首页</span></a>
|
||||
</li>{/if}
|
||||
<li class="{:checkIfActive('domain,record,record_log,record_batch_add')}">
|
||||
<li class="{:checkIfActive('domain,record,record_log,record_batch_add,domain_add')}">
|
||||
<a href="/domain"><i class="fa fa-list-ul fa-fw"></i> <span>域名管理</span></a>
|
||||
</li>
|
||||
{if request()->user['level'] eq 2}
|
||||
@@ -136,7 +136,7 @@
|
||||
<li><a href="/optimizeip/opiplist"><i class="fa fa-circle-o"></i> 任务管理</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="treeview {:checkIfActive('certaccount,account_form,certorder,order_form,deployaccount,deploytask,deploy_form,certset,cname')}">
|
||||
<li class="treeview {:checkIfActive('certaccount,account_form,certorder,order_form,order_import,deployaccount,deploytask,deploy_form,certset,cname')}">
|
||||
<a href="javascript:;">
|
||||
<i class="fa fa-expeditedssl fa-fw"></i>
|
||||
<span>SSL证书</span>
|
||||
|
||||
@@ -56,6 +56,10 @@
|
||||
<label class="col-sm-4 control-label">Telegram机器人通知</label>
|
||||
<div class="col-sm-8"><select class="form-control" name="notice_tgbot" default="{:config_get('notice_tgbot')}"><option value="0">关闭</option><option value="1">开启</option></select></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label">群机器人Webhook</label>
|
||||
<div class="col-sm-8"><select class="form-control" name="notice_webhook" default="{:config_get('notice_webhook')}"><option value="0">关闭</option><option value="1">开启</option></select></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
@@ -36,12 +36,20 @@
|
||||
<input type="text" class="form-control" name="sk" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group" id="ext_name_div" style="display:none;">
|
||||
<label class="col-sm-3 control-label no-padding-right" id="ext_name">扩展字段</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" name="ext" placeholder="没有请勿填写">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right" id="ext_name">使用代理</label>
|
||||
<div class="col-sm-9">
|
||||
<label class="radio-inline"><input type="radio" name="proxy" value="0"> 否
|
||||
</label><label class="radio-inline"><input type="radio" name="proxy" value="1"> 是
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label no-padding-right">备注</label>
|
||||
<div class="col-sm-9">
|
||||
@@ -137,8 +145,12 @@ $(document).ready(function(){
|
||||
if(dnsconfig[type] == undefined) return;
|
||||
$("#ak_name").html(dnsconfig[type].config.ak);
|
||||
$("#sk_name").html(dnsconfig[type].config.sk);
|
||||
if(dnsconfig[type].config.ext == undefined) dnsconfig[type].config.ext = '扩展字段';
|
||||
else $("#ext_name").html(dnsconfig[type].config.ext);
|
||||
if(dnsconfig[type].config.ext == undefined){
|
||||
$("#ext_name_div").hide();
|
||||
}else{
|
||||
$("#ext_name_div").show();
|
||||
$("#ext_name").html(dnsconfig[type].config.ext);
|
||||
}
|
||||
});
|
||||
})
|
||||
function addframe(){
|
||||
@@ -149,6 +161,7 @@ function addframe(){
|
||||
$("#form-store input[name=ak]").val('');
|
||||
$("#form-store input[name=sk]").val('');
|
||||
$("#form-store input[name=ext]").val('');
|
||||
$("#form-store input[name=proxy]").eq(0).prop('checked',true);
|
||||
$("#form-store input[name=remark]").val('');
|
||||
$("select[name=type]").change();
|
||||
}
|
||||
@@ -170,6 +183,7 @@ function editframe(id){
|
||||
$("#form-store input[name=ak]").val(data.data.ak);
|
||||
$("#form-store input[name=sk]").val(data.data.sk);
|
||||
$("#form-store input[name=ext]").val(data.data.ext);
|
||||
$("#form-store input[name=proxy]").eq(data.data.proxy).prop('checked',true);
|
||||
$("#form-store input[name=remark]").val(data.data.remark);
|
||||
$("select[name=type]").change();
|
||||
}else{
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" id="form-store">
|
||||
<input type="hidden" name="recordcount"/>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">域名账户</label>
|
||||
<div class="col-sm-9">
|
||||
@@ -27,8 +26,10 @@
|
||||
<label class="col-sm-3 control-label">选择域名</label>
|
||||
<div class="col-sm-9">
|
||||
<select name="domain" id="domainList" class="form-control"></select>
|
||||
<span class="pull-right"><a href="/domain/add">批量添加</a></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
@@ -200,11 +201,6 @@ $(document).ready(function(){
|
||||
getDomainList()
|
||||
})
|
||||
|
||||
$('#domainList').on('select2:select', function (e) {
|
||||
var data = e.params.data;
|
||||
$("#form-store input[name=recordcount]").val(data.recordcount);
|
||||
});
|
||||
|
||||
$('[data-toggle="popover"]').popover()
|
||||
})
|
||||
function addframe(){
|
||||
@@ -222,7 +218,7 @@ function saveAdd(){
|
||||
}
|
||||
var name = select[0].text;
|
||||
var thirdid = select[0].id;
|
||||
var recordcount = $("#form-store input[name=recordcount]").val();
|
||||
var recordcount = select[0].recordcount;
|
||||
if(aid=='' || thirdid==''){
|
||||
layer.alert('请确保各项不能为空!');return false;
|
||||
}
|
||||
@@ -342,9 +338,9 @@ function getDomainList(){
|
||||
params.page = params.page || 1
|
||||
if(data.code == 0){
|
||||
var resultData = [];
|
||||
for (var i = 0; i < data.data.list.length; i++) {
|
||||
resultData.push({'id': data.data.list[i].DomainId, 'text': data.data.list[i].Domain, 'recordcount': data.data.list[i].RecordCount});
|
||||
}
|
||||
$.each(data.data.list, function(index, item){
|
||||
resultData.push({'id': item.DomainId, 'text': item.Domain + (item.disabled ? ' (已添加)' : ''), 'recordcount': item.RecordCount, disabled:item.disabled});
|
||||
})
|
||||
return {
|
||||
results: resultData,
|
||||
pagination: {
|
||||
|
||||
158
app/view/domain/domain_add.html
Normal file
158
app/view/domain/domain_add.html
Normal file
@@ -0,0 +1,158 @@
|
||||
{extend name="common/layout" /}
|
||||
{block name="title"}批量添加域名{/block}
|
||||
{block name="main"}
|
||||
<div class="row" id="app">
|
||||
<div class="col-xs-12 col-sm-10 col-md-8 col-lg-6 center-block" style="float: none;">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><h3 class="panel-title"><a href="/domain" class="btn btn-sm btn-default pull-right" style="margin-top:-6px"><i class="fa fa-reply fa-fw"></i> 返回</a>批量添加域名</h3></div>
|
||||
<div class="panel-body">
|
||||
<form onsubmit="return false" method="post" class="form-horizontal" role="form" id="form-store">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">域名账户</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group">
|
||||
<select name="aid" class="form-control" v-model="aid">
|
||||
{foreach $accounts as $k=>$v}
|
||||
<option value="{$k}">{$v}</option>
|
||||
{/foreach}
|
||||
</select>
|
||||
<div class="input-group-btn">
|
||||
<button type="button" @click="getDomainList" class="btn btn-info">获取域名</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">选择域名</label>
|
||||
<div class="col-sm-9">
|
||||
<table class="table table-striped table-hover table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><input type="checkbox" v-model="checkall"></th>
|
||||
<th>域名</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in domainList">
|
||||
<td><input type="checkbox" name="domain[]" :value="item.DomainId" v-model="item.checked" :disabled="item.disabled"></td>
|
||||
<td><span :title="item.DomainId">{{item.Domain}}</span><font color="#888" v-if="item.disabled"> (已添加)</font></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9"><button type="button" class="btn btn-primary" @click="submit">确定添加</button></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
{block name="script"}
|
||||
<script src="{$cdnpublic}vue/2.6.14/vue.min.js"></script>
|
||||
<script src="{$cdnpublic}layer/3.1.1/layer.js"></script>
|
||||
<script>
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
aid: '',
|
||||
domainList: [],
|
||||
page: 1,
|
||||
pagesize: 10,
|
||||
checkall: false,
|
||||
},
|
||||
watch: {
|
||||
aid: function(val){
|
||||
this.domainList = [];
|
||||
},
|
||||
checkall: function(val){
|
||||
this.domainList.forEach(function(item){
|
||||
item.checked = val&&!item.disabled;
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.aid = '{$accounts|@key}';
|
||||
},
|
||||
methods: {
|
||||
async getDomainListPaged(){
|
||||
var that = this;
|
||||
return new Promise((resolve, reject) => {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/domain/list",
|
||||
data: {aid: that.aid, page: that.page, pagesize: that.pagesize},
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if(data.code == 0){
|
||||
resolve(data.data);
|
||||
}else{
|
||||
reject(data.msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
async getDomainList(){
|
||||
this.domainList = [];
|
||||
while(true){
|
||||
try{
|
||||
layer.msg('正在获取第'+this.page+'页域名', {icon: 16, shade: 0.01});
|
||||
var data = await this.getDomainListPaged();
|
||||
if(data.total == 0 || data.list.length == 0){
|
||||
layer.closeAll();
|
||||
break;
|
||||
}
|
||||
this.domainList = this.domainList.concat(data.list);
|
||||
if(this.domainList.length >= data.total){
|
||||
layer.closeAll();
|
||||
break;
|
||||
}
|
||||
this.page++;
|
||||
}catch(e){
|
||||
layer.alert(e, {icon: 2});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
submit(){
|
||||
var domains = [];
|
||||
this.domainList.forEach(function(item){
|
||||
if(item.checked && !item.disabled){
|
||||
domains.push({name: item.Domain, id: item.DomainId, recordcount:item.RecordCount});
|
||||
}
|
||||
});
|
||||
if(this.aid == ''){
|
||||
layer.alert('请选择域名账户');
|
||||
return;
|
||||
}
|
||||
if(domains.length == 0){
|
||||
layer.alert('请选择要添加的域名');
|
||||
return;
|
||||
}
|
||||
var ii = layer.load(2, {shade:[0.1,'#fff']});
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/domain/op/act/batchadd",
|
||||
data: {aid: this.aid, domains: domains},
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.alert(data.msg, {icon: 1}, function(){
|
||||
window.location.href = '/domain';
|
||||
});
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2});
|
||||
}
|
||||
},
|
||||
error: function(data){
|
||||
layer.close(ii);
|
||||
layer.msg('服务器错误');
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
{/block}
|
||||
@@ -109,6 +109,26 @@
|
||||
与<a href="https://t.me/BotFather" target="_blank" rel="noopener noreferrer">@BotFather</a>对话,使用/newbot命令创建一个新的机器人,根据提示输入机器人的名称和用户名,可得到Token,或使用/mybots命令查看已创建的机器人;与<a href="https://t.me/getmyid_bot" target="_blank" rel="noopener noreferrer">@getmyid_bot</a>对话,可得到Chat Id<br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading"><h3 class="panel-title">群机器人Webhook</h3></div>
|
||||
<div class="panel-body">
|
||||
<form onsubmit="return saveSetting(this)" method="post" class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">Webhook地址</label>
|
||||
<div class="col-sm-9"><input type="text" name="webhook_url" value="{:config_get('webhook_url')}" class="form-control"/></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<input type="submit" name="submit" value="保存" class="btn btn-primary btn-block"/>
|
||||
<a href="javascript:webhooktest()" class="btn btn-default btn-block">发送测试消息</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
仅支持填写企业微信、钉钉、飞书群机器人的Webhook地址
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
@@ -139,7 +159,7 @@ function saveSetting(obj){
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.alert('设置保存成功!<br/>重启检测进程或容器后生效', {
|
||||
layer.alert('设置保存成功!<br/>如有使用容灾切换,重启检测进程后生效', {
|
||||
icon: 1,
|
||||
closeBtn: false
|
||||
}, function(){
|
||||
@@ -196,5 +216,25 @@ function tgbottest(){
|
||||
}
|
||||
});
|
||||
}
|
||||
function webhooktest(){
|
||||
var ii = layer.load(2, {shade:[0.1,'#fff']});
|
||||
$.ajax({
|
||||
type : 'GET',
|
||||
url : '/system/webhooktest',
|
||||
dataType : 'json',
|
||||
success : function(data) {
|
||||
layer.close(ii);
|
||||
if(data.code == 0){
|
||||
layer.alert(data.msg, {icon: 1});
|
||||
}else{
|
||||
layer.alert(data.msg, {icon: 2})
|
||||
}
|
||||
},
|
||||
error:function(data){
|
||||
layer.close(ii);
|
||||
layer.msg('服务器错误');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
@@ -1,5 +1,5 @@
|
||||
{extend name="common/layout" /}
|
||||
{block name="title"}容灾切换代理设置{/block}
|
||||
{block name="title"}代理设置{/block}
|
||||
{block name="main"}
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-8 col-lg-6 center-block" style="float: none;">
|
||||
|
||||
@@ -31,7 +31,7 @@ return [
|
||||
'show_error_msg' => true,
|
||||
'exception_tmpl' => \think\facade\App::getAppPath() . 'view/exception.tpl',
|
||||
|
||||
'version' => '1021',
|
||||
'version' => '1027',
|
||||
|
||||
'dbversion' => '1021'
|
||||
'dbversion' => '1023'
|
||||
];
|
||||
|
||||
BIN
public/static/images/mwpanel.ico
Normal file
BIN
public/static/images/mwpanel.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
@@ -52,6 +52,7 @@ Route::group(function () {
|
||||
Route::post('/domain/data', 'domain/domain_data');
|
||||
Route::post('/domain/op', 'domain/domain_op');
|
||||
Route::post('/domain/list', 'domain/domain_list');
|
||||
Route::get('/domain/add', 'domain/domain_add');
|
||||
Route::get('/domain', 'domain/domain');
|
||||
|
||||
Route::post('/record/data/:id', 'domain/record_data');
|
||||
@@ -73,6 +74,7 @@ Route::group(function () {
|
||||
Route::get('/dmonitor/task/info/:id', 'dmonitor/taskinfo');
|
||||
Route::any('/dmonitor/task/:action', 'dmonitor/taskform');
|
||||
Route::get('/dmonitor/task', 'dmonitor/task');
|
||||
Route::post('/dmonitor/noticeset', 'dmonitor/noticeset');
|
||||
Route::post('/dmonitor/clean', 'dmonitor/clean');
|
||||
|
||||
Route::any('/optimizeip/opipset', 'optimizeip/opipset');
|
||||
@@ -91,6 +93,7 @@ Route::group(function () {
|
||||
Route::post('/cert/order/data', 'cert/order_data');
|
||||
Route::post('/cert/order/process', 'cert/order_process');
|
||||
Route::post('/cert/order/:action', 'cert/order_op');
|
||||
Route::get('/cert/order/import', 'cert/order_import');
|
||||
Route::get('/cert/order/:action', 'cert/order_form');
|
||||
|
||||
Route::get('/cert/deploytask', 'cert/deploytask');
|
||||
@@ -109,6 +112,7 @@ Route::group(function () {
|
||||
Route::any('/system/proxyset', 'system/proxyset');
|
||||
Route::get('/system/mailtest', 'system/mailtest');
|
||||
Route::get('/system/tgbottest', 'system/tgbottest');
|
||||
Route::get('/system/webhooktest', 'system/webhooktest');
|
||||
Route::post('/system/proxytest', 'system/proxytest');
|
||||
|
||||
})->middleware(CheckLogin::class)
|
||||
|
||||
Reference in New Issue
Block a user