DomainInfo.php 13.4 KB
<?php
/**
 * @remark :
 * @name   :DomainInfo.php
 * @author :lyh
 * @method :post
 * @time   :2023/9/11 14:37
 */

namespace App\Console\Commands\Domain;

use App\Models\Devops\ServerConfig;
use App\Models\Devops\ServersIp;
use App\Models\Domain\DomainCreateTask;
use App\Models\Project\CountryCustom;
use App\Models\Project\Project;
use Illuminate\Console\Command;
use App\Models\Domain\DomainInfo as DomainInfoModel;
use Illuminate\Support\Facades\Log;

class DomainInfo extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'domain_info';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '域名相关';

    /**
     * @remark :更新证书+证书有效时间
     * @name   :handle
     * @author :lyh
     * @method :post
     * @time   :2023/9/11 15:09
     */
    public function handle()
    {
        //先更新所有域名证书有效期
        $this->startUpdateSslTime();

        //主站证书到期更新
        $this->startUpdateCert();

        //AMP站证书到期更新
        $this->startUpdateAmpCert();

        //创建的自定义小语种域名证书到期更新
        $this->startUpdateCustomCert();

        return true;
    }

    /**
     * 更新域名证书有效期
     * @author Akun
     * @date 2024/09/06 11:16
     */
    public function startUpdateSslTime()
    {
        $domainModel = new DomainInfoModel();
        $projectModel = new Project();
        $serverIpModel = new ServersIp();
        $domainCreateTaskModel = new DomainCreateTask();
        $list = $domainModel->where('status', '=', 1)->get();
        foreach ($list as $v) {
            $project_info = $projectModel->read(['id' => $v['project_id'], 'type' => ['!=', Project::TYPE_CLOSE]], ['serve_id', 'project_type']);
            if (!$project_info) {
                continue;
            }

            $servers_ip_info = $serverIpModel->read(['id' => $project_info['serve_id']], ['servers_id', 'ip', 'domain']);
            if (!$servers_ip_info) {
                continue;
            }

            //除自建站项目外,记录已解析到别的ip的域名
            if ($servers_ip_info['servers_id'] != ServerConfig::SELF_SITE_ID) {
                //过滤已解析到别的ip的域名
                if (!check_domain_record($v['domain'], $servers_ip_info)) {
                    Log::channel('analyze_other')->error('域名 [' . $v['domain'] . '] 已解析到别的IP');
                    continue;
                }
            }

            //判断是否已经建站
            if ($project_info['project_type'] == Project::PROJECT_TYPE_SEO) {
                $type = DomainCreateTask::TYPE_BLOG;
            } else {
                $type = DomainCreateTask::TYPE_MAIN;
            }
            $task_info = $domainCreateTaskModel->read(['type' => $type, 'domain_id' => $v['id'], 'status' => DomainCreateTask::STATUS_SUC], ['id']);
            if (!$task_info) {
                continue;
            }

            //获取主站证书有效期并更新
            $ssl_time = $this->getDomainSslTime($v['domain']);
            if ($ssl_time['from'] && $ssl_time['to']) {
                $v->certificate_start_time = $ssl_time['from'];
                $v->certificate_end_time = $ssl_time['to'];
                $v->save();
            }

            if (empty($v['domain_end_time']) || $v['domain_end_time'] < date('Y-m-d H:i:s')) {
                //获取主站域名有效期并更新
                $valid_time = $this->getDomainValidTime($v['domain']);
                if ($valid_time['start'] && $valid_time['end']) {
                    $v->domain_start_time = $valid_time['start'];
                    $v->domain_end_time = $valid_time['end'];
                    $v->save();
                }
            }

            if ($v['amp_status'] == 1) {
                $domain_array = parse_url($v['domain']);
                $host = $domain_array['host'] ?? $domain_array['path'];
                $host_array = explode('.', $host);
                if (count($host_array) <= 2) {
                    array_unshift($host_array, 'm');
                } else {
                    $host_array[0] = 'm';
                }
                $amp_domain = implode('.', $host_array);

                if ($servers_ip_info['servers_id'] != ServerConfig::SELF_SITE_ID) {
                    //过滤已解析到别的ip的AMP域名
                    if (!check_domain_record($amp_domain, $servers_ip_info)) {
                        Log::channel('analyze_other')->error('AMP域名 [' . $amp_domain . '] 已解析到别的IP');
                        continue;
                    }
                }

                //获取AMP站证书有效期并更新
                $amp_ssl_time = $this->getDomainSslTime($amp_domain);
                if ($amp_ssl_time['from'] && $amp_ssl_time['to']) {
                    $v->amp_certificate_start_time = $amp_ssl_time['from'];
                    $v->amp_certificate_end_time = $amp_ssl_time['to'];
                    $v->save();
                }
            }
        }
    }

    /**
     * 主站证书到期更新
     * @author Akun
     * @date 2024/02/26 10:26
     */
    public function startUpdateCert()
    {
        $domainModel = new DomainInfoModel();
        $projectModel = new Project();
        $serverIpModel = new ServersIp();
        $domainCreateTaskModel = new DomainCreateTask();
        $end_day = date('Y-m-d H:i:s', time() + 3 * 24 * 3600);//3天后到期
        $list = $domainModel->where('status', '=', 1)->where('type', '!=', 2)->where('certificate_end_time', '<', $end_day)->get()->toArray();
        foreach ($list as $v) {
            $project_info = $projectModel->read(['id' => $v['project_id'], 'type' => ['!=', Project::TYPE_CLOSE]], ['serve_id', 'project_type']);
            if (!$project_info) {
                continue;
            }

            $servers_ip_info = $serverIpModel->read(['id' => $project_info['serve_id']], ['servers_id', 'ip', 'domain']);
            if (!$servers_ip_info) {
                continue;
            }

            //过滤自建站项目域名
            if ($servers_ip_info['servers_id'] == ServerConfig::SELF_SITE_ID) {
                continue;
            }

            //过滤已解析到别的ip的域名
            if (!check_domain_record($v['domain'], $servers_ip_info)) {
                continue;
            }

            if ($project_info['project_type'] == Project::PROJECT_TYPE_SEO) {
                $type = DomainCreateTask::TYPE_BLOG;
            } else {
                $type = DomainCreateTask::TYPE_MAIN;
            }

            //创建更新站点证书任务
            $task_info = $domainCreateTaskModel->read(['type' => $type, 'domain_id' => $v['id'], 'status' => ['<', DomainCreateTask::STATUS_SUC]], ['id']);
            if (!$task_info) {
                $domainCreateTaskModel->add([
                    'server_id' => $servers_ip_info['servers_id'],
                    'project_id' => $v['project_id'],
                    'domain_id' => $v['id'],
                    'type' => $type
                ]);
            }
        }
    }

    /**
     * AMP站证书到期更新
     * @author Akun
     * @date 2024/02/26 10:26
     */
    public function startUpdateAmpCert()
    {
        $domainModel = new DomainInfoModel();
        $projectModel = new Project();
        $serverIpModel = new ServersIp();
        $domainCreateTaskModel = new DomainCreateTask();
        $end_day = date('Y-m-d H:i:s', time() + 3 * 24 * 3600);//3天后到期
        $list = $domainModel->where('status', '=', 1)->where('amp_status', 1)->where('amp_type', '!=', 2)->where('amp_certificate_end_time', '<', $end_day)->get()->toArray();
        foreach ($list as $v) {
            $domain_array = parse_url($v['domain']);
            $host = $domain_array['host'] ?? $domain_array['path'];
            $host_array = explode('.', $host);
            if (count($host_array) <= 2) {
                array_unshift($host_array, 'm');
            } else {
                $host_array[0] = 'm';
            }
            $amp_domain = implode('.', $host_array);

            $project_info = $projectModel->read(['id' => $v['project_id'], 'type' => ['!=', Project::TYPE_CLOSE]], ['serve_id']);
            if (!$project_info) {
                continue;
            }

            $servers_ip_info = $serverIpModel->read(['id' => $project_info['serve_id']], ['servers_id', 'ip', 'domain']);
            if (!$servers_ip_info) {
                continue;
            }

            //过滤自建站项目域名
            if ($servers_ip_info['servers_id'] == ServerConfig::SELF_SITE_ID) {
                continue;
            }

            //过滤已解析到别的ip的域名
            if (!check_domain_record($amp_domain, $servers_ip_info)) {
                continue;
            }

            //创建更新站点证书任务
            $task_info = $domainCreateTaskModel->read(['type' => DomainCreateTask::TYPE_AMP, 'domain_id' => $v['id'], 'status' => ['<', DomainCreateTask::STATUS_SUC]], ['id']);
            if (!$task_info) {
                $domainCreateTaskModel->add([
                    'server_id' => $servers_ip_info['servers_id'],
                    'project_id' => $v['project_id'],
                    'domain_id' => $v['id'],
                    'type' => DomainCreateTask::TYPE_AMP
                ]);
            }
        }
    }

    /**
     * 自定义小语种站证书到期更新
     * @author Akun
     * @date 2024/03/23 10:08
     */
    public function startUpdateCustomCert()
    {
        $customModel = new CountryCustom();
        $projectModel = new Project();
        $serverIpModel = new ServersIp();
        $domainCreateTaskModel = new DomainCreateTask();
        $end_day = date('Y-m-d H:i:s', time() + 3 * 24 * 3600);//3天后到期
        $list = $customModel->where('status', 1)->where('is_create', 1)->where('type', '=', 1)->where('certificate_end_time', '<', $end_day)->get()->toArray();
        foreach ($list as $v) {
            $project_info = $projectModel->read(['id' => $v['project_id'], 'type' => ['!=', Project::TYPE_CLOSE]], ['serve_id']);
            if (!$project_info) {
                continue;
            }

            $servers_ip_info = $serverIpModel->read(['id' => $project_info['serve_id']], ['servers_id', 'ip', 'domain']);
            if (!$servers_ip_info) {
                continue;
            }

            //过滤自建站项目域名
            if ($servers_ip_info['servers_id'] == ServerConfig::SELF_SITE_ID) {
                continue;
            }

            //过滤已解析到别的ip的域名
            if (!check_domain_record($v['custom_domain'], $servers_ip_info)) {
                Log::channel('analyze_other')->error('自定义跳转域名 [' . $v['custom_domain'] . '] 已解析到别的IP');
                continue;
            }

            //创建更新站点证书任务
            $task_info = $domainCreateTaskModel->read(['type' => DomainCreateTask::TYPE_CUSTOM, 'domain_id' => $v['id'], 'status' => ['<', DomainCreateTask::STATUS_SUC]], ['id']);
            if (!$task_info) {
                $domainCreateTaskModel->add([
                    'server_id' => $servers_ip_info['servers_id'],
                    'project_id' => $v['project_id'],
                    'domain_id' => $v['id'],
                    'type' => DomainCreateTask::TYPE_CUSTOM
                ]);
            }
        }
    }

    /**
     * 获取域名证书有效时间
     * @param $domain
     * @return string[]
     * @author Akun
     * @date 2024/08/29 9:59
     */
    public function getDomainSslTime($domain)
    {
        $valid_from = '';
        $valid_to = '';
        try {
            $context = stream_context_create([
                'ssl' => [
                    'capture_peer_cert' => true,
                    'capture_peer_cert_chain' => false,
                    'verify_peer' => false,
                    'verify_peer_name' => false
                ],
            ]);
            $stream = stream_socket_client('ssl://' . $domain . ':443', $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
            if ($stream) {
                $remote_cert = stream_context_get_params($stream)['options']['ssl']['peer_certificate'];
                if ($remote_cert) {
                    $valid_from = date('Y-m-d H:i:s', openssl_x509_parse($remote_cert)['validFrom_time_t']);
                    $valid_to = date('Y-m-d H:i:s', openssl_x509_parse($remote_cert)['validTo_time_t']);
                }
            }
            fclose($stream);
        } catch (\Exception $e) {
            $valid_from = '';
            $valid_to = '';
        }
        return ['from' => $valid_from, 'to' => $valid_to];
    }

    /**
     * 获取域名有效时间
     * @param $domain
     * @return array
     * @author Akun
     * @date 2024/08/29 9:43
     */
    public function getDomainValidTime($domain)
    {
        $url = 'http://openai.waimaoq.com/v1/whois_api?domain=' . $domain;
        $response = curlGet($url);
        $start = '';
        $end = '';
        if (isset($response['code']) && $response['code'] == 200) {
            $start = $response['text']['creation_date'] != 'None' ? $response['text']['creation_date'] : '';
            $end = $response['text']['expiration_date'] != 'None' ? $response['text']['expiration_date'] : '';
        }
        return ['start' => $start, 'end' => $end];
    }
}