作者 周海龙

合并分支 'zhl' 到 'master'

Zhl



查看合并请求 !1
@@ -13,4 +13,5 @@ npm-debug.log @@ -13,4 +13,5 @@ npm-debug.log
13 yarn-error.log 13 yarn-error.log
14 /.idea 14 /.idea
15 /.vscode 15 /.vscode
16 -/app/Console/Commands/Demo.php  
  16 +/app/Console/Commands/Demo.php
  17 +composer.lock
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2022/11/05
  6 + * Time: 14:11
  7 + */
  8 +namespace App\Console\Commands;
  9 +
  10 +use App\Models\BtEvents;
  11 +use App\Repositories\BtRepository;
  12 +use App\Repositories\ToolRepository;
  13 +use Illuminate\Console\Command;
  14 +
  15 +/**
  16 + * Class EventExpend
  17 + * @package App\Console\Commands
  18 + */
  19 +class EventExpend extends Command
  20 +{
  21 + /**
  22 + * The name and signature of the console command.
  23 + *
  24 + * @var string
  25 + */
  26 + protected $signature = 'event:expend';
  27 +
  28 + /**
  29 + * The console command description.
  30 + *
  31 + * @var string
  32 + */
  33 + protected $description = '消费提交事件';
  34 +
  35 + /**
  36 + * Create a new command instance.
  37 + *
  38 + * @return void
  39 + */
  40 + public function __construct()
  41 + {
  42 + parent::__construct();
  43 + }
  44 +
  45 + /**
  46 + * Execute the console command.
  47 + *
  48 + * @return bool
  49 + */
  50 + public function handle()
  51 + {
  52 + while (true) {
  53 + $start_at = date('Y-m-d H:i:s');
  54 + $events = BtEvents::where('status', 0)->where('times', '<', BtEvents::MAX_TRIES_TIMES)->where('start_at', '<', $start_at)->orderBy('id', 'asc')->limit(10)->get();
  55 + // 没有需要处理的数据
  56 + if ($events->isEmpty()) {
  57 + echo $start_at . ', empty event.' . PHP_EOL;
  58 + sleep(30);
  59 + } else {
  60 + $this->expend($events);
  61 + }
  62 + }
  63 + return true;
  64 + }
  65 +
  66 + /**
  67 + * @param $data
  68 + * @return bool
  69 + */
  70 + public function expend($data)
  71 + {
  72 + foreach ($data as $val) {
  73 + $param = json_decode($val->param, true);
  74 + switch ($val->type) {
  75 + case BtEvents::TYPE_CREATE_SITE:
  76 + $result = $this->createSiteEvent($val->id, $param);
  77 + break;
  78 + case BtEvents::TYPE_DELETE_SITE:
  79 + $result = $this->deleteSiteEvent($val->id, $param);
  80 + break;
  81 + case BtEvents::TYPE_CREATE_SSL:
  82 + $result = $this->createSiteSsl($val->id, $param);
  83 + break;
  84 + case BtEvents::TYPE_RENEWAL_SSL:
  85 + $result = $this->renewalSiteSsl($val->id, $param);
  86 + break;
  87 + case BtEvents::TYPE_EVENT_CALLBACK:
  88 + $result = $this->callbackEvent($val->id, $param);
  89 + break;
  90 + default:
  91 + $result = false;
  92 + break;
  93 + }
  94 + }
  95 + return true;
  96 + }
  97 +
  98 + /**
  99 + * 创建站点
  100 + * @param $id
  101 + * @param $param
  102 + * @return bool
  103 + */
  104 + public function createSiteEvent($id, $param)
  105 + {
  106 + if (empty($param) || FALSE == is_array($param))
  107 + return false;
  108 +
  109 + $callback = $param['callback'] ?? '';
  110 + $domain = $param['domain'] ?? '';
  111 + $ssl_open = empty($param['ssl_open']) ? 1 : 0;
  112 + $ssl_auto = empty($param['ssl_auto']) ? 1 : 0;
  113 + $ssl_auto_day = $param['ssl_auto_day'] ?? 10;
  114 + $ssl_auto_day = $ssl_auto_day > 15 ? 15 : max($ssl_auto_day, 5);
  115 + if (empty($domain) || FALSE == filter_var($domain, FILTER_VALIDATE_URL)) {
  116 + if (FALSE == empty($callback) && filter_var($callback, FILTER_VALIDATE_URL)) {
  117 + $param['result_message'] = 'domain信息错误';
  118 + BtEvents::createBtEvent(BtEvents::TYPE_EVENT_CALLBACK, json_encode($param));
  119 + }
  120 + return $this->setEvent($id, BtEvents::STATUS_FINISH, 'domain信息错误');
  121 + }
  122 +
  123 + try {
  124 + $flag = app(BtRepository::class)->createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day);
  125 + $status = $flag ? BtEvents::STATUS_FINISH : BtEvents::STATUS_ERROR;
  126 + $note = $flag ? '' : '创建站点失败';
  127 + } catch (\Exception $e) {
  128 + $status = BtEvents::STATUS_ERROR;
  129 + $note = $e->getMessage();
  130 + }
  131 +
  132 + if (FALSE == empty($callback) && filter_var($callback, FILTER_VALIDATE_URL)) {
  133 + $param['result_status'] = $status == BtEvents::STATUS_FINISH ? 200 : 400;
  134 + $param['result_message'] = $note;
  135 + BtEvents::createBtEvent(BtEvents::TYPE_EVENT_CALLBACK, json_encode($param));
  136 + }
  137 +
  138 + return $this->setEvent($id, $status, $note);
  139 + }
  140 +
  141 + /**
  142 + * 删除站点
  143 + * @param $id
  144 + * @param $param
  145 + * @return bool
  146 + */
  147 + public function deleteSiteEvent($id, $param)
  148 + {
  149 + if (empty($param) || FALSE == is_array($param))
  150 + return false;
  151 + $callback = $param['callback'] ?? '';
  152 + $domain = $param['domain'] ?? '';
  153 + if (empty($domain) || FALSE == filter_var($domain, FILTER_VALIDATE_URL)) {
  154 + if (FALSE == empty($callback) && filter_var($callback, FILTER_VALIDATE_URL)) {
  155 + $param['result_status'] = 400;
  156 + $param['result_message'] = 'domain信息错误';
  157 + BtEvents::createBtEvent(BtEvents::TYPE_EVENT_CALLBACK, json_encode($param));
  158 + }
  159 + return $this->setEvent($id, BtEvents::STATUS_FINISH, 'domain信息错误');
  160 + }
  161 +
  162 + try {
  163 + $flag = app(BtRepository::class)->deleteBtSite($domain);
  164 + $status = $flag ? BtEvents::STATUS_FINISH : BtEvents::STATUS_ERROR;
  165 + $note = $flag ? '' : '删除站点失败';
  166 + } catch (\Exception $e) {
  167 + $status = BtEvents::STATUS_ERROR;
  168 + $note = $e->getMessage();
  169 + }
  170 +
  171 + if (FALSE == empty($callback) && filter_var($callback, FILTER_VALIDATE_URL)) {
  172 + $param['result_status'] = $status == BtEvents::STATUS_FINISH ? 200 : 400;
  173 + $param['result_message'] = $note;
  174 + BtEvents::createBtEvent(BtEvents::TYPE_EVENT_CALLBACK, json_encode($param));
  175 + }
  176 +
  177 + return $this->setEvent($id, $status, $note);
  178 + }
  179 +
  180 + /**
  181 + * 创建ssl证书
  182 + * @param $id
  183 + * @param $param
  184 + * @return bool
  185 + */
  186 + public function createSiteSsl($id, $param)
  187 + {
  188 + if (empty($param) || FALSE == is_array($param))
  189 + return false;
  190 + $callback = $param['callback'] ?? '';
  191 + $host = $param['host'] ?? '';
  192 + if (empty($host)) {
  193 + if (FALSE == empty($callback) && filter_var($callback, FILTER_VALIDATE_URL)) {
  194 + $param['result_status'] = 400;
  195 + $param['result_message'] = 'host信息错误';
  196 + BtEvents::createBtEvent(BtEvents::TYPE_EVENT_CALLBACK, json_encode($param));
  197 + }
  198 + return $this->setEvent($id, BtEvents::STATUS_FINISH, 'host信息错误');
  199 + }
  200 +
  201 + try {
  202 + $flag = app(BtRepository::class)->applySsl($host);
  203 + $status = $flag ? BtEvents::STATUS_FINISH : BtEvents::STATUS_ERROR;
  204 + $note = $flag ? '' : '删除站点失败';
  205 + } catch (\Exception $e) {
  206 + $status = BtEvents::STATUS_ERROR;
  207 + $note = $e->getMessage();
  208 + }
  209 +
  210 + if (FALSE == empty($callback) && filter_var($callback, FILTER_VALIDATE_URL)) {
  211 + $param['result_status'] = $status == BtEvents::STATUS_FINISH ? 200 : 400;
  212 + $param['result_message'] = $note;
  213 + BtEvents::createBtEvent(BtEvents::TYPE_EVENT_CALLBACK, json_encode($param));
  214 + }
  215 +
  216 + return $this->setEvent($id, $status, $note);
  217 + }
  218 +
  219 + /**
  220 + * 续签证书
  221 + * @param $id
  222 + * @param $param
  223 + * @return bool
  224 + */
  225 + public function renewalSiteSsl($id, $param)
  226 + {
  227 + if (empty($param) || FALSE == is_array($param))
  228 + return false;
  229 + $callback = $param['callback'] ?? '';
  230 + $host = $param['host'] ?? '';
  231 + if (empty($host)) {
  232 + if (FALSE == empty($callback) && filter_var($callback, FILTER_VALIDATE_URL)) {
  233 + $param['result_status'] = 400;
  234 + $param['result_message'] = 'host信息错误';
  235 + BtEvents::createBtEvent(BtEvents::TYPE_EVENT_CALLBACK, json_encode($param));
  236 + }
  237 + return $this->setEvent($id, BtEvents::STATUS_FINISH, 'host信息错误');
  238 + }
  239 +
  240 + try {
  241 + $flag = app(BtRepository::class)->renewalSsl($host);
  242 + $status = $flag ? BtEvents::STATUS_FINISH : BtEvents::STATUS_ERROR;
  243 + $note = $flag ? '' : '删除站点失败';
  244 + } catch (\Exception $e) {
  245 + $status = BtEvents::STATUS_ERROR;
  246 + $note = $e->getMessage();
  247 + }
  248 +
  249 + if (FALSE == empty($callback) && filter_var($callback, FILTER_VALIDATE_URL)) {
  250 + $param['result_status'] = $status == BtEvents::STATUS_FINISH ? 200 : 400;
  251 + $param['result_message'] = $note;
  252 + BtEvents::createBtEvent(BtEvents::TYPE_EVENT_CALLBACK, json_encode($param));
  253 + }
  254 +
  255 + return $this->setEvent($id, $status, $note);
  256 + }
  257 +
  258 + /**
  259 + * 回调信息
  260 + * @param $id
  261 + * @param $param
  262 + * @return bool
  263 + */
  264 + public function callbackEvent($id, $param)
  265 + {
  266 + if (empty($param) || FALSE == is_array($param))
  267 + return false;
  268 + $callback = $param['callback'] ?? '';
  269 + if (empty($callback) || FALSE == filter_var($callback, FILTER_VALIDATE_URL))
  270 + return $this->setEvent($id, BtEvents::STATUS_FINISH, 'callback信息错误');
  271 + $status = $param['result_status'];
  272 + $message = $param['result_message'];
  273 + unset($param['result_status']);
  274 + unset($param['result_message']);
  275 + $array = [
  276 + 'status' => $status,
  277 + 'message' => $message,
  278 + 'data' => [],
  279 + 'param' => $param
  280 + ];
  281 + list($code, $result) = app(ToolRepository::class)->curlRequest($callback, $array);
  282 + $status = $code == 200 ? BtEvents::STATUS_FINISH : BtEvents::STATUS_ERROR;
  283 + return $this->setEvent($id, $status, $result);
  284 + }
  285 +
  286 +
  287 + /**
  288 + * 更新任务状态
  289 + * @param $id
  290 + * @param $status
  291 + * @param string $note
  292 + * @return bool
  293 + */
  294 + public function setEvent($id, $status, $note = '')
  295 + {
  296 + $event = BtEvents::where(['id' => $id])->first();
  297 + if (empty($event))
  298 + return false;
  299 +
  300 + $times = $event->times + 1;
  301 +
  302 + if ($status == BtEvents::STATUS_ERROR && $times < BtEvents::MAX_TRIES_TIMES) {
  303 + $status = BtEvents::STATUS_INIT;
  304 + // 第一次执行失败以后, 5分钟后再执行一次; 第二次执行失败以后, 10分钟后再执行一次 0->5->15
  305 + if ($times == 1)
  306 + $event->start_at = date('Y-m-d H:i:s', time() + 300);
  307 + if ($times == 2)
  308 + $event->start_at = date('Y-m-d H:i:s', time() + 600);
  309 + }
  310 + $event->stauts = $status;
  311 + $event->times = $times;
  312 + $event->note = $note;
  313 + $event->save();
  314 + return true;
  315 + }
  316 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2022/11/05
  6 + * Time: 09:09
  7 + */
  8 +namespace App\Console\Commands;
  9 +
  10 +use App\Models\BtEvents;
  11 +use App\Models\BtSites;
  12 +use App\Repositories\BtRepository;
  13 +use Illuminate\Console\Command;
  14 +
  15 +/**
  16 + * Class SiteSslRenewal
  17 + * @package App\Console\Commands
  18 + */
  19 +class SiteSslRenewal extends Command
  20 +{
  21 + /**
  22 + * The name and signature of the console command.
  23 + *
  24 + * @var string
  25 + */
  26 + protected $signature = 'site:ssl_renewal';
  27 +
  28 + /**
  29 + * The console command description.
  30 + *
  31 + * @var string
  32 + */
  33 + protected $description = '检测ssl续签';
  34 +
  35 + /**
  36 + * Create a new command instance.
  37 + *
  38 + * @return void
  39 + */
  40 + public function __construct()
  41 + {
  42 + parent::__construct();
  43 + }
  44 +
  45 + /**
  46 + * Execute the console command.
  47 + *
  48 + * @return bool
  49 + */
  50 + public function handle()
  51 + {
  52 + $sites = BtSites::where(['is_del' => 0])->get();
  53 +
  54 + if ($sites->isEmpty())
  55 + return true;
  56 +
  57 + foreach ($sites as $val) {
  58 + // 未开启ssl 抛弃
  59 + if ($val->ssl_open == 0)
  60 + continue;
  61 +
  62 + // 未生成ssl 申请ssl
  63 + if ($val->ssl_status == 0) {
  64 + $result = app(BtRepository::class)->applySsl($sites->domain);
  65 + if (empty($result))
  66 + BtEvents::createBtEvent(BtEvents::TYPE_CREATE_SSL, json_encode(['host' => $sites->domain]));
  67 + continue;
  68 + }
  69 +
  70 + // 开启ssl续签 检查是否到期进行续签
  71 + if ($val->ssl_auto) {
  72 + $result = app(BtRepository::class)->renewalSsl($sites->domain);
  73 + if (empty($result))
  74 + BtEvents::createBtEvent(BtEvents::TYPE_RENEWAL_SSL, json_encode(['host' => $sites->domain]));
  75 + continue;
  76 + }
  77 +
  78 + sleep(2);
  79 + }
  80 + return true;
  81 + }
  82 +}
@@ -16,6 +16,7 @@ class Kernel extends ConsoleKernel @@ -16,6 +16,7 @@ class Kernel extends ConsoleKernel
16 protected function schedule(Schedule $schedule) 16 protected function schedule(Schedule $schedule)
17 { 17 {
18 // $schedule->command('inspire')->hourly(); 18 // $schedule->command('inspire')->hourly();
  19 + $schedule->command('site:ssl_renewal')->dailyAt('01:00'); // 站点创建ssl证书, 续签
19 } 20 }
20 21
21 /** 22 /**
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 namespace App\Http\Controllers\Api; 8 namespace App\Http\Controllers\Api;
9 9
10 use App\Http\Controllers\Controller; 10 use App\Http\Controllers\Controller;
11 -use App\Repositories\BtRepositories; 11 +use App\Repositories\BtRepository;
12 use Illuminate\Http\Request; 12 use Illuminate\Http\Request;
13 13
14 /** 14 /**
@@ -27,14 +27,14 @@ public function createSite(Request $request) @@ -27,14 +27,14 @@ public function createSite(Request $request)
27 try { 27 try {
28 // $this->validate(); 28 // $this->validate();
29 $domain = $request->input('domain'); 29 $domain = $request->input('domain');
30 - $ssl_open = intval($request->input('ssl_open', 0)) ? 1 : 0;  
31 - $ssl_auto = intval($request->input('ssl_auto', 0)) ? 1 : 0;  
32 - $ssl_auto_day = intval($request->input('ssl_auto_day', 0)); 30 + $ssl_open = intval($request->input('ssl_open', 1)) ? 1 : 0;
  31 + $ssl_auto = intval($request->input('ssl_auto', 1)) ? 1 : 0;
  32 + $ssl_auto_day = intval($request->input('ssl_auto_day', 10));
33 $ssl_auto_day = $ssl_auto_day > 15 ? 15 : max($ssl_auto_day, 5); 33 $ssl_auto_day = $ssl_auto_day > 15 ? 15 : max($ssl_auto_day, 5);
34 - if (empty($domain) && filter_var($domain, FILTER_VALIDATE_URL)) 34 + if (empty($domain) || FALSE == filter_var($domain, FILTER_VALIDATE_URL))
35 return $this->error('请提交有效domain信息'); 35 return $this->error('请提交有效domain信息');
36 36
37 - $result = app(BtRepositories::class)->createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day); 37 + $result = app(BtRepository::class)->createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day);
38 return $result ? $this->success($result) : $this->error('创建站点失败,提交异步创建任务!'); 38 return $result ? $this->success($result) : $this->error('创建站点失败,提交异步创建任务!');
39 } catch (\Exception $e) { 39 } catch (\Exception $e) {
40 return $this->error($e->getMessage()); 40 return $this->error($e->getMessage());
@@ -54,10 +54,10 @@ public function deleteSite(Request $request) @@ -54,10 +54,10 @@ public function deleteSite(Request $request)
54 if (empty($domain) && filter_var($domain, FILTER_VALIDATE_URL)) 54 if (empty($domain) && filter_var($domain, FILTER_VALIDATE_URL))
55 return $this->error('请提交有效domain信息'); 55 return $this->error('请提交有效domain信息');
56 56
57 - $result = app(BtRepositories::class)->deleteBtSite($domain); 57 + $result = app(BtRepository::class)->deleteBtSite($domain);
58 return $result ? $this->success() : $this->error('删除站点失败,提交异步删除任务!'); 58 return $result ? $this->success() : $this->error('删除站点失败,提交异步删除任务!');
59 - } catch (\Exception $d) {  
60 - return $this->error(); 59 + } catch (\Exception $e) {
  60 + return $this->error($e->getMessage());
61 } 61 }
62 } 62 }
63 63
@@ -68,7 +68,17 @@ public function deleteSite(Request $request) @@ -68,7 +68,17 @@ public function deleteSite(Request $request)
68 */ 68 */
69 public function createSsl(Request $request) 69 public function createSsl(Request $request)
70 { 70 {
71 - return $this->error(); 71 + try {
  72 +// $this->validate();
  73 + $host = $request->input('host');
  74 + if (empty($host))
  75 + return $this->error('请提交有效host信息');
  76 +
  77 + $result = app(BtRepository::class)->applySsl($host);
  78 + return $result ? $this->success() : $this->error('创建ssl失败,提交异步任务!');
  79 + } catch (\Exception $e) {
  80 + return $this->error($e->getMessage());
  81 + }
72 } 82 }
73 83
74 /** 84 /**
@@ -76,8 +86,18 @@ public function createSsl(Request $request) @@ -76,8 +86,18 @@ public function createSsl(Request $request)
76 * @param Request $request 86 * @param Request $request
77 * @return string 87 * @return string
78 */ 88 */
79 - public function updateSsl(Request $request) 89 + public function renewalSsl(Request $request)
80 { 90 {
81 - return $this->error(); 91 + try {
  92 +// $this->validate();
  93 + $host = $request->input('host');
  94 + if (empty($host))
  95 + return $this->error('请提交有效host信息');
  96 +
  97 + $result = app(BtRepository::class)->renewalSsl($host);
  98 + return $result ? $this->success() : $this->error('续签ssl失败,提交异步任务!');
  99 + } catch (\Exception $e) {
  100 + return $this->error($e->getMessage());
  101 + }
82 } 102 }
83 } 103 }
@@ -31,7 +31,7 @@ protected function success($data = [], $message = 'success', $status = 200) @@ -31,7 +31,7 @@ protected function success($data = [], $message = 'success', $status = 200)
31 */ 31 */
32 protected function error($message = 'error', $status = 400, $data = []) 32 protected function error($message = 'error', $status = 400, $data = [])
33 { 33 {
34 - $array = compact('status', 'message', $data); 34 + $array = compact('status', 'message', 'data');
35 return json_encode($array, JSON_UNESCAPED_UNICODE); 35 return json_encode($array, JSON_UNESCAPED_UNICODE);
36 } 36 }
37 } 37 }
@@ -14,8 +14,8 @@ class Kernel extends HttpKernel @@ -14,8 +14,8 @@ class Kernel extends HttpKernel
14 * @var array<int, class-string|string> 14 * @var array<int, class-string|string>
15 */ 15 */
16 protected $middleware = [ 16 protected $middleware = [
17 - // \App\Http\Middleware\TrustHosts::class,  
18 - \App\Http\Middleware\TrustProxies::class, 17 + \App\Http\Middleware\TrustHosts::class,
  18 +// \App\Http\Middleware\TrustProxies::class,
19 \Fruitcake\Cors\HandleCors::class, 19 \Fruitcake\Cors\HandleCors::class,
20 \App\Http\Middleware\PreventRequestsDuringMaintenance::class, 20 \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
21 \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, 21 \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
@@ -20,20 +20,48 @@ class BtEvents extends Model @@ -20,20 +20,48 @@ class BtEvents extends Model
20 */ 20 */
21 protected $table = 'bt_events'; 21 protected $table = 'bt_events';
22 22
  23 + // 最大执行次数
  24 + const MAX_TRIES_TIMES = 3;
  25 +
23 const STATUS_INIT = 0; 26 const STATUS_INIT = 0;
24 const STATUS_FINISH = 1; 27 const STATUS_FINISH = 1;
25 const STATUS_ERROR = 9; 28 const STATUS_ERROR = 9;
26 29
  30 + const TYPE_CREATE_SITE = 1;
  31 + const TYPE_DELETE_SITE = 2;
  32 + const TYPE_CREATE_SSL = 3;
  33 + const TYPE_RENEWAL_SSL = 4;
  34 + const TYPE_HTTP_TO_HTTPS_OPEN = 5;
  35 + const TYPE_HTTP_TO_HTTPS_CLOSE = 6;
  36 + const TYPE_EVENT_CALLBACK = 99;
  37 +
  38 + /**
  39 + * @return array
  40 + */
  41 + public static function typeMap()
  42 + {
  43 + return [
  44 + self::TYPE_CREATE_SITE => '创建站点',
  45 + self::TYPE_DELETE_SITE => '删除站点',
  46 + self::TYPE_CREATE_SSL => '创建ssl证书',
  47 + self::TYPE_RENEWAL_SSL => '续签ssl证书',
  48 + self::TYPE_HTTP_TO_HTTPS_OPEN => '开启强制https',
  49 + self::TYPE_HTTP_TO_HTTPS_CLOSE => '关闭强制https',
  50 + ];
  51 + }
  52 +
27 /** 53 /**
28 * @param $type 54 * @param $type
29 * @param $param 55 * @param $param
30 * @return mixed 56 * @return mixed
31 */ 57 */
32 - public static function createBtEvent($type, $param) 58 + public static function createBtEvent($type, $param, $start_at = '')
33 { 59 {
  60 + $start_at = $start_at ?: date('Y-m-d H:i:s');
34 $event = new self(); 61 $event = new self();
35 $event->type = $type; 62 $event->type = $type;
36 $event->param = $param; 63 $event->param = $param;
  64 + $event->start_at = $start_at;
37 $event->save(); 65 $event->save();
38 return $event->id; 66 return $event->id;
39 } 67 }
@@ -37,7 +37,7 @@ class BtSites extends Model @@ -37,7 +37,7 @@ class BtSites extends Model
37 */ 37 */
38 public static function createBtSite($domain, $site_id, $ssl_open, $ssl_status, $ssl_auto, $ssl_auto_day) 38 public static function createBtSite($domain, $site_id, $ssl_open, $ssl_status, $ssl_auto, $ssl_auto_day)
39 { 39 {
40 - $site = self::where(['domain' => $domain])->fisrt(); 40 + $site = self::where(['domain' => $domain])->first();
41 if (empty($site)) { 41 if (empty($site)) {
42 $site = new self(); 42 $site = new self();
43 } 43 }
@@ -59,6 +59,6 @@ public static function createBtSite($domain, $site_id, $ssl_open, $ssl_status, $ @@ -59,6 +59,6 @@ public static function createBtSite($domain, $site_id, $ssl_open, $ssl_status, $
59 */ 59 */
60 public static function getSiteByDomain($domain) 60 public static function getSiteByDomain($domain)
61 { 61 {
62 - return self::where(['domain' => $domain, 'is_del' => self::IS_DEL_FALSE])->fisrt(); 62 + return self::where(['domain' => $domain, 'is_del' => self::IS_DEL_FALSE])->first();
63 } 63 }
64 } 64 }
@@ -12,10 +12,10 @@ @@ -12,10 +12,10 @@
12 use App\Repositories\Bt\Bt; 12 use App\Repositories\Bt\Bt;
13 13
14 /** 14 /**
15 - * Class BtRepositories 15 + * Class BtRepository
16 * @package App\Repositories 16 * @package App\Repositories
17 */ 17 */
18 -class BtRepositories 18 +class BtRepository
19 { 19 {
20 public $instance = []; 20 public $instance = [];
21 21
@@ -24,15 +24,23 @@ class BtRepositories @@ -24,15 +24,23 @@ class BtRepositories
24 * @param $ssl_open 24 * @param $ssl_open
25 * @param $ssl_auto 25 * @param $ssl_auto
26 * @param $ssl_auto_day 26 * @param $ssl_auto_day
  27 + * @param int $ssl_status
27 * @return array|bool 28 * @return array|bool
28 */ 29 */
29 - public function createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day) 30 + public function createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day, $ssl_status = 0)
30 { 31 {
31 $domain_array = parse_url($domain); 32 $domain_array = parse_url($domain);
32 $host = $domain_array['host']; 33 $host = $domain_array['host'];
33 34
  35 + // 如果站点已经存在, 更新数据
  36 + $site = BtSites::getSiteByDomain($host);
  37 + if ($site) {
  38 + $result = BtSites::createBtSite($host, $site->site_id, $ssl_open, $ssl_status, $ssl_auto, $ssl_auto_day);
  39 + return $result->toArray();
  40 + }
  41 +
34 $host_array = explode('.', $host); 42 $host_array = explode('.', $host);
35 - if (empty($host_array[0]) && $host_array[0] == 'www') 43 + if (FALSE == empty($host_array[0]) && $host_array[0] == 'www')
36 unset($host_array[0]); 44 unset($host_array[0]);
37 $domain_top = implode('.', $host_array); 45 $domain_top = implode('.', $host_array);
38 46
@@ -42,7 +50,7 @@ public function createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day) @@ -42,7 +50,7 @@ public function createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day)
42 'path' => env('PROJECT_PATH') ? env('PROJECT_PATH') : dirname(dirname(app_path())) . DIRECTORY_SEPARATOR . $domain, 50 'path' => env('PROJECT_PATH') ? env('PROJECT_PATH') : dirname(dirname(app_path())) . DIRECTORY_SEPARATOR . $domain,
43 'type_id' => 0, 51 'type_id' => 0,
44 'type' => 'PHP', 52 'type' => 'PHP',
45 - 'version' => '73', 53 + 'version' => '74',
46 'port' => '80', 54 'port' => '80',
47 'ps' => $host, 55 'ps' => $host,
48 'ftp' => false, 56 'ftp' => false,
@@ -56,13 +64,43 @@ public function createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day) @@ -56,13 +64,43 @@ public function createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day)
56 64
57 $bt = $this->getBtObject(); 65 $bt = $this->getBtObject();
58 $result = $bt->AddSite($array); 66 $result = $bt->AddSite($array);
59 -  
60 - if (empty($result) || empty($result['id'])) 67 + // result 返回信息
  68 + // $result = ['siteStatus' => true, 'siteId' => 39, 'ftpStatus' => false, 'databaseStatus' => false,];
  69 + if (empty($result) || empty($result['siteId']))
61 return false; 70 return false;
  71 + // 伪静态设置
  72 + $htaccess = '# SEO URL Settings
  73 + # Nginx configuration of OC htaccess
  74 + location = /sitemap.xml {
  75 + rewrite ^(.*)$ /index.php?route=feed/google_sitemap break;
  76 + }
  77 +
  78 + location = /googlebase.xml {
  79 + rewrite ^(.*)$ /index.php?route=feed/google_base break;
  80 + }
  81 +
  82 + location / {
  83 + # This try_files directive is used to enable SEO-friendly URLs for OpenCart
  84 + try_files $uri $uri/ @opencart;
  85 + # 隐藏index.php
  86 + if (!-e $request_filename) {
  87 + rewrite ^/(.*)$ /index.php?$1 last;
  88 + }
  89 + }
  90 +
  91 + location @opencart {
  92 + rewrite ^/(.+)$ /index.php?_route_=$1 last;
  93 + }
  94 + # End SEO settings';
  95 + $bt->SaveFileBody($host, $htaccess);
62 96
63 - $ssl_status = 0;  
64 - $result = BtSites::createBtSite($host, $result['id'], $ssl_open, $ssl_status, $ssl_auto, $ssl_auto_day);  
65 - return $result->toArray(); 97 + $result = BtSites::createBtSite($host, $result['siteId'], $ssl_open, $ssl_status, $ssl_auto, $ssl_auto_day);
  98 + $site = $result->toArray();
  99 + unset($site['id']);
  100 + unset($site['created_at']);
  101 + unset($site['updated_at']);
  102 + unset($site['is_del']);
  103 + return $site;
66 } 104 }
67 105
68 /** 106 /**
@@ -72,21 +110,20 @@ public function createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day) @@ -72,21 +110,20 @@ public function createBtSite($domain, $ssl_open, $ssl_auto, $ssl_auto_day)
72 */ 110 */
73 public function deleteBtSite($domain) 111 public function deleteBtSite($domain)
74 { 112 {
75 - $domain = parse_url($domain);  
76 $domain_array = parse_url($domain); 113 $domain_array = parse_url($domain);
77 $host = $domain_array['host']; 114 $host = $domain_array['host'];
78 115
79 $bt = $this->getBtObject(); 116 $bt = $this->getBtObject();
80 117
81 $site = BtSites::getSiteByDomain($host); 118 $site = BtSites::getSiteByDomain($host);
82 -// $id = $site->site_id; 119 + // $id = $site->site_id;
83 // 获取bt数据 可能要可靠一些 120 // 获取bt数据 可能要可靠一些
84 $result = $bt->Websites($host); 121 $result = $bt->Websites($host);
85 if (empty($result['data'])) 122 if (empty($result['data']))
86 return false; 123 return false;
87 $id = 0; 124 $id = 0;
88 foreach ($result['data'] as $v) { 125 foreach ($result['data'] as $v) {
89 - if ($v['name'] == $domain) { 126 + if ($v['name'] == $host) {
90 $id = $v['id']; 127 $id = $v['id'];
91 break; 128 break;
92 } 129 }
@@ -94,14 +131,103 @@ public function deleteBtSite($domain) @@ -94,14 +131,103 @@ public function deleteBtSite($domain)
94 131
95 if (empty($id)) 132 if (empty($id))
96 return false; 133 return false;
97 - $result = $bt->WebDeleteSite($id,$domain,false,false,false); 134 + $result = $bt->WebDeleteSite($id,$host,false,false,false);
  135 + // $result 返回信息
  136 + // $result = ['status' => true, 'msg' => '站点删除成功!',]
  137 + if (empty($result['status']))
  138 + return false;
  139 +
  140 + if ($site) {
  141 + $site->is_del = BtSites::IS_DEL_TRUE;
  142 + $site->save();
  143 + }
  144 + return true;
  145 + }
  146 +
  147 + /**
  148 + * 申请ssl 并设置ssl访问
  149 + * @param $host
  150 + * @return bool
  151 + */
  152 + public function applySsl($host)
  153 + {
  154 + $site = BtSites::getSiteByDomain($host);
  155 + if (empty($site) || empty($site->ssl_open))
  156 + return false;
  157 +
  158 + $bt = $this->getBtObject();
  159 + // $domains = [["id" => 71, "pid" => 35, "name" => "www.shopk.com", "port" => 80, "addtime" => "2022-11-03 14:22:08",]];
  160 + $domain_list = $bt->WebDoaminList($site->site_id);
  161 + // 被删除的站点 返回空数组 不做数据删除同步 可能bt接口问题
  162 + if (empty($domain_list))
  163 + return false;
  164 +
  165 + // $result = ["status" => false, "msg" => "指定网站配置文件不存在!"];
  166 + // $result = ["status" => true, "oid" => -1, "domain" => [["name" => "*.shopk.com"],["name" => "www.shopk.com"]], "key" => "key", "csr" => "csr", "type" => 0, "httpTohttps" => true,
  167 + // "cert_data" => ["issuer" => "TrustAsia TLS RSA CA", "notAfter" => "2023-02-22", "notBefore" => "2022-02-21", "dns" => [0 => "*.shopk.com", 1 => "shopk.com"],
  168 + // "subject" => "*.shopk.com", "endtime" => 110], "email" => "test@message.com", "index" => null, "auth_type" => "http", "push" => ["status" => false]];
  169 + $ssl = $bt->GetSSL($host);
  170 + // 已经有ssl证书了
  171 + if (FALSE == empty($ssl['status'])) {
  172 + $bt->SetSSL('1', $host, $ssl['key'], $ssl['csr']);
  173 + // 开启强制https
  174 + // $bt->HttpToHttps($host);
  175 + $site->ssl_status = 1;
  176 + $site->save();
  177 + return true;
  178 + }
  179 +
  180 + $domain = array_column($domain_list, 'name');
  181 + $result = $bt->ApplyCert(json_encode($domain), $site->site_id);
  182 + if (empty($result) || empty($result['cert']))
  183 + return false;
98 184
99 - $site->is_del = BtSites::IS_DEL_TRUE; 185 + $bt->SetSSL('1', $host, $result['private_key'], $result['cert']);
  186 + // 开启强制https
  187 + // $bt->HttpToHttps($host);
  188 + $site->ssl_status = 1;
100 $site->save(); 189 $site->save();
101 return true; 190 return true;
102 } 191 }
103 192
104 /** 193 /**
  194 + * 续签ssl
  195 + * @param $host
  196 + * @return bool
  197 + */
  198 + public function renewalSsl($host)
  199 + {
  200 + $site = BtSites::getSiteByDomain($host);
  201 + if (empty($site) || empty($site->ssl_open) || empty($site->ssl_auto))
  202 + return false;
  203 +
  204 + $bt = $this->getBtObject();
  205 + // $result = ["status" => false, "oid" => -1, "domain" => [["name" => "test.hagro.cn"], ["name" => "test.hagro.cn"]], "key" => false, "csr" => false,
  206 + // "type" => -1, "httpTohttps" => false, "cert_data" => [], "email" => "test@message.com", "index" => "", "auth_type" => "http", "push" => ["status" => false]];
  207 + $ssl = $bt->GetSSL($host);
  208 + if (empty($ssl['status']))
  209 + return $this->applySsl($host);
  210 +
  211 + $end = strtotime($ssl["cert_data"]["notAfter"]);
  212 +
  213 + if ($end - time() >= $site->ssl_auto_day * 86400)
  214 + return true;
  215 +
  216 + $domain_list = $bt->WebDoaminList($site->site_id);
  217 + // 被删除的站点 返回空数组 不做数据删除同步 可能bt接口问题
  218 + if (empty($domain_list))
  219 + return false;
  220 +
  221 + // 不是宝塔生成的ssl 不能续签, 直接申请ssl
  222 + $result = $bt->RenewCert($ssl["index"]);
  223 + if (empty($result['status']))
  224 + return $this->applySsl($host);
  225 +
  226 + $bt->SetSSL(1, $host, $result['private_key'], $result['cert']);
  227 + return true;
  228 + }
  229 +
  230 + /**
105 * 获取bt对象 231 * 获取bt对象
106 * @param string $key 232 * @param string $key
107 * @param string $panel 233 * @param string $panel
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2022/11/05
  6 + * Time: 16:40
  7 + */
  8 +
  9 +namespace App\Repositories;
  10 +
  11 +
  12 +/**
  13 + * Class ToolRepository
  14 + * @package App\Repositories
  15 + */
  16 +class ToolRepository
  17 +{
  18 + /**
  19 + * @param $url
  20 + * @param $data
  21 + * @param string $method
  22 + * @param array $header
  23 + * @param int $time_out
  24 + * @return array
  25 + */
  26 + public function curlRequest($url, $data, $method = 'POST', $header = [], $time_out = 30)
  27 + {
  28 + $ch = curl_init();
  29 + curl_setopt($ch, CURLOPT_TIMEOUT, $time_out);
  30 + curl_setopt($ch, CURLOPT_URL, $url);
  31 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  32 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  33 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  34 + if ($data)
  35 + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  36 + curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge([
  37 + 'Expect:',
  38 + 'Content-type: application/json',
  39 + 'Accept: application/json',
  40 + ], $header)
  41 + );
  42 + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
  43 + $response = curl_exec($ch);
  44 + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  45 + curl_close($ch);
  46 + return [$code, $response];
  47 + }
  48 +}
@@ -6,9 +6,11 @@ @@ -6,9 +6,11 @@
6 "license": "MIT", 6 "license": "MIT",
7 "require": { 7 "require": {
8 "php": "^7.3|^8.0", 8 "php": "^7.3|^8.0",
  9 + "ext-json": "*",
  10 + "ext-curl": "*",
9 "fruitcake/laravel-cors": "^2.0", 11 "fruitcake/laravel-cors": "^2.0",
10 "guzzlehttp/guzzle": "^7.0.1", 12 "guzzlehttp/guzzle": "^7.0.1",
11 - "laravel/framework": "^8.75", 13 + "laravel/framework": "^8.0",
12 "laravel/sanctum": "^2.11", 14 "laravel/sanctum": "^2.11",
13 "laravel/tinker": "^2.5" 15 "laravel/tinker": "^2.5"
14 }, 16 },
@@ -18,7 +20,8 @@ @@ -18,7 +20,8 @@
18 "laravel/sail": "^1.0.1", 20 "laravel/sail": "^1.0.1",
19 "mockery/mockery": "^1.4.4", 21 "mockery/mockery": "^1.4.4",
20 "nunomaduro/collision": "^5.10", 22 "nunomaduro/collision": "^5.10",
21 - "phpunit/phpunit": "^9.5.10" 23 + "phpunit/phpunit": "^9.5.10",
  24 + "fzaninotto/faker": "^1.4"
22 }, 25 },
23 "autoload": { 26 "autoload": {
24 "psr-4": { 27 "psr-4": {
此 diff 太大无法显示。
@@ -67,7 +67,7 @@ @@ -67,7 +67,7 @@
67 | 67 |
68 */ 68 */
69 69
70 - 'timezone' => 'UTC', 70 + 'timezone' => 'PRC',
71 71
72 /* 72 /*
73 |-------------------------------------------------------------------------- 73 |--------------------------------------------------------------------------
@@ -22,7 +22,7 @@ @@ -22,7 +22,7 @@
22 Route::any('/create_site', 'WebSiteController@createSite')->name('create_site'); 22 Route::any('/create_site', 'WebSiteController@createSite')->name('create_site');
23 Route::any('/delete_site', 'WebSiteController@deleteSite')->name('delete_site'); 23 Route::any('/delete_site', 'WebSiteController@deleteSite')->name('delete_site');
24 Route::any('/create_site_ssl', 'WebSiteController@createSsl')->name('create_site_ssl'); 24 Route::any('/create_site_ssl', 'WebSiteController@createSsl')->name('create_site_ssl');
25 - Route::any('/update_site_ssl', 'WebSiteController@updateSsl')->name('update_site_ssl'); 25 + Route::any('/renewal_site_ssl', 'WebSiteController@renewalSsl')->name('renewal_site_ssl');
26 26
27 Route::get('/create_event', 'ReceiveController@createEvent')->name('create_event'); 27 Route::get('/create_event', 'ReceiveController@createEvent')->name('create_event');
28 }); 28 });