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

namespace App\Console\Commands\Domain;

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(){
        $domainModel = new DomainInfoModel();
        $map = ['status'=>['!=',2]];
        $list = $domainModel->list($map);
        foreach ($list as $v){
            if(empty($v['private_key']) || empty($v['private_cert'])){
                //域名结束时间<2天时,重新生成
                if(!empty($v['certificate_end_time']) && ($v['certificate_end_time'] > date('Y-m-d H:i:s',time() + 24*3600))){
                    $this->updatePrivate($v);
                }
            }
            $ssl = $this->updateDomainSsl($v['domain']);
            $time = $this->updateDomain($v['domain']);
            if(!empty($time['start']) && !!empty($time['end'])){
                $data = [
                    'certificate_start_time'=>$ssl['from'],
                    'certificate_end_time'=>$ssl['to'],
                    'domain_start_time'=>$time['start'],
                    'domain_end_time'=>$time['end']
                ];
            }else{
                $data = [
                    'domain_start_time'=>$time['start'],
                    'domain_end_time'=>$time['end']
                ];
            }
            $domainModel->edit($data,['id'=>$v['id']]);
        }
        return 1;
    }

    /**
     * @remark :更新正式
     * @name   :updatePrivate
     * @author :lyh
     * @method :post
     * @time   :2023/12/8 16:16
     */
    public function updatePrivate($param)
    {
        $url = 'https://' . $param['domain']. '/api/applySsl/';
        $extend_config = json_decode($param['extend_config'], true);
        $top_domain = $this->getTopDomain($param['domain']);
        if ((empty($extend_config) || empty($extend_config[0]['origin'])) && $param['id'] != 3) {
            $extend_config = [
                ['origin' => $top_domain, 'target' => $param['domain']]
            ];
        }
        $param = [
            'project_id' => $param['project_id'],
            'type' => 1,
            'route' => 1,
            "domain" =>$param['domain'],
            "rewrite"=> $extend_config,
            'other_domain' => [$top_domain, '*.' . $top_domain],
            'private_key' => '',
            'cert' => ''
        ];
        $result = $this->curlRequest($url, $param);
        Log::info('domain id: ' . $param['id'] . ', domain: ' . $param['domain'] . ', result: ' . var_export($result, true));
    }

    public static function getTopDomain ($url) {
        $url = strtolower($url);  //首先转成小写
        $url = mb_ereg_replace('^( | )+', '', trim($url));
        $url = mb_ereg_replace('( | )+$', '', $url);
        if (!preg_match('/^(http:\/\/|https)/', $url)) {
            $url = "https://".$url;
        }
        $hosts = parse_url($url);
        $host = $hosts['host'] ?? '';
        //查看是几级域名
        $data = explode('.', $host);
        $n = count($data);
        if ($n < 2) {
            return $host;
        }
        //判断是否是双后缀
        $preg = '/[\w].+\.(com|net|org|gov|edu|co|ne)\.[\w]/';
        if (($n > 2) && preg_match($preg, $host)) {
            //双后缀取后3位
            $host = $data[$n - 3].'.'.$data[$n - 2].'.'.$data[$n - 1];
        } else {
            //非双后缀取后两位
            $host = $data[$n - 2].'.'.$data[$n - 1];
        }
        return $host;
    }

    public function curlRequest($url, $data, $method = 'POST', $header = [], $time_out = 60)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_TIMEOUT, $time_out);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        if ($data)
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge([
                'Expect:',
                'Content-type: application/json',
                'Accept: application/json',
            ], $header)
        );
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
        $response = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return [$code, $response];
    }

    /**
     * @remark :更新域名证书
     * @name   :updateDomainSsl
     * @author :lyh
     * @method :post
     * @time   :2023/9/11 15:07
     */
    public function updateDomainSsl($domain){
        try {
            $context = stream_context_create([
                'ssl' => [
                    'capture_peer_cert' => true,
                    'capture_peer_cert_chain' => false,
                ],
            ]);
            $stream = stream_socket_client('ssl://'.$domain.':443', $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
            if(!$stream) {
                die("Failed to connect: $errno - $errstr");
            }
            $remote_cert = stream_context_get_params($stream)['options']['ssl']['peer_certificate'];
            if(!$remote_cert) {
                die("Failed to retrieve certificate");
            }
            $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];
    }

    /**
     * @remark :更新域名有限时间
     * @name   :updateDomain
     * @author :lyh
     * @method :post
     * @time   :2023/9/11 15:11
     */
    public function updateDomain($domain){
        $url = 'http://openai.waimaoq.com/v1/whois_api?domain='.$domain;
        $response = http_get($url);
        $start = date('Y-m-d H:i:s');
        $end = date('Y-m-d H:i:s');
        if($response['code'] == 200){
            $start = $response['text']['creation_date'];
            $end = $response['text']['expiration_date'];
        }
        return ['start'=>$start,'end'=>$end];
    }
}