UpdateController.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\admin\controllers;
  8. use app\models\Admin;
  9. use Comodojo\Zip\Zip;
  10. use Curl\Curl;
  11. class UpdateController extends BaseController
  12. {
  13. private $api_root = 'http://v7.we10.cn/update.php';
  14. public function actionIndex()
  15. {
  16. $is_platform = \Yii::$app->cache->get('is_platform'); //
  17. $admin = get_admin();
  18. if ($is_platform === false && (int)$admin->store_id !== 1) {
  19. return $this->asJson([
  20. 'code' => 1,
  21. 'msg' => '您当前的系统不支持在线更新!',
  22. ]);
  23. }
  24. $version = 'version.json';
  25. $app_root = str_replace('\\', '/', \Yii::$app->basePath) . '/';
  26. if (!file_exists($app_root . $version)) {
  27. return $this->asJson([
  28. 'code' => 1,
  29. 'msg' => '版本文件获取失败!'
  30. ]);
  31. }
  32. $json_string = file_get_contents($app_root . $version);
  33. $data = json_decode($json_string, true);
  34. $ver = $data['version'];
  35. // TODO: test ver
  36. // $ver = 8.3;
  37. $updatehost = $this->api_root;
  38. // 检查客户下一个需要更新的版本
  39. $lastver = $this->http_get(($updatehost . '?a=check&v=') . $ver);
  40. $cache_data = cache()->get('cyy_check_auth');
  41. if ($cache_data === false) {
  42. return $this->asJson([
  43. 'code' => 1,
  44. 'msg' => '您当前的系统不支持在线更新!'
  45. ]);
  46. }
  47. if ($cache_data['code'] == 1) {
  48. return $this->asJson([
  49. 'code' => 1,
  50. 'msg' => $cache_data['msg']
  51. ]);
  52. }
  53. if ($cache_data['data']['is_can'] == 0) {
  54. return $this->asJson([
  55. 'code' => 1,
  56. 'msg' => $cache_data['data']['expires_message'],
  57. ]);
  58. }
  59. // $key = $cache_data['data']['key'];
  60. if (empty($lastver)) {
  61. return $this->asJson([
  62. 'code' => 1,
  63. 'msg' => '云服务器连接失败,请检查您的服务器与云服务器的连接是否正常',
  64. ]);
  65. }
  66. $hosturl = \Yii::$app->getHost();
  67. // TODO: test hosturl
  68. // $hosturl = 'qijian.cyyvip.com';
  69. // 验证授权时间
  70. if (time() > $cache_data['data']['expire_time']) {
  71. return $this->asJson([
  72. 'code' => 1,
  73. 'msg' => $cache_data['data']['expires_message'],
  74. ]);
  75. }
  76. // 检查版本更新内容
  77. $vern = $ver + 0.1;
  78. $chosturl = $updatehost . '?a=chanage&v=' . $vern . '&u=' . $hosturl;
  79. $cinfo = $this->http_get($chosturl);
  80. $chosturl_time = $updatehost . '?a=chanagetime&v=' . $vern . '&u=' . $hosturl;
  81. $update_datetime = $this->http_get($chosturl_time);
  82. $update_datetime = date("Y-m-d H:i:s", $update_datetime);
  83. //显示最新版本
  84. $lastverz = $updatehost . '?a=checkl&v=' . $ver . '&u=' . $hosturl;
  85. $lastverz = $this->http_get($lastverz);
  86. //获取更新记录
  87. $logurl = $updatehost . '?a=chanagelog&v=' . $ver . '&u=' . $hosturl;
  88. $log_info = $this->http_get($logurl);
  89. $log_info = json_decode($log_info, true);
  90. $time = array_column($log_info, 'time');
  91. array_multisort($time, SORT_DESC, $log_info);
  92. if ($lastver !== $ver) {
  93. return $this->asJson([
  94. 'code' => 0,
  95. 'msg' => 'success',
  96. 'data' => array(
  97. 'next_version' => array(
  98. 'version' => $lastver,
  99. 'update_datetime' => $update_datetime,
  100. 'desc' => $cinfo
  101. ),
  102. 'current_version' => $ver,
  103. 'version_list' => $log_info,
  104. )
  105. ]);
  106. } else {
  107. return $this->asJson([
  108. 'code' => 0,
  109. 'msg' => 'success',
  110. 'data' => [
  111. 'current_version' => $ver,
  112. 'version_list' => $log_info,
  113. ]
  114. ]);
  115. }
  116. }
  117. /**
  118. * 自动更新操作
  119. * @return \yii\web\Response
  120. */
  121. public function actionUpdate()
  122. {
  123. $is_platform = false; //
  124. $admin = get_admin();
  125. if (\Yii::$app->isSaas()) {
  126. if ($admin->type == Admin::ADMIN_TYPE_SUPPLIER ) {
  127. //平台权限
  128. $is_platform = true;
  129. } else {
  130. if ($admin->username != 'admin') {
  131. $is_platform = true;
  132. } else {
  133. $is_platform = true;
  134. }
  135. }
  136. }
  137. if ($is_platform === false && (int)$admin->store_id !== 1) {
  138. return $this->asJson([
  139. 'code' => 1,
  140. 'msg' => '您当前的系统不支持在线更新!',
  141. ]);
  142. }
  143. header("Content-type: text/html; charset=utf-8");
  144. $version = 'version.json';
  145. $app_root = str_replace('\\', '/', \Yii::$app->basePath) . '/';
  146. $json_string = file_get_contents($app_root . $version);
  147. $data = json_decode($json_string, true);
  148. $ver = $data['version'];
  149. // TODO: test ver
  150. // $ver = 8.3;
  151. $cache_data = cache()->get('cyy_check_auth');
  152. if ($cache_data['code'] == 1) {
  153. return $this->asJson([
  154. 'code' => 1,
  155. 'msg' => $cache_data['msg'],
  156. ]);
  157. }
  158. if ($cache_data['data']['is_can'] == 0) {
  159. return $this->asJson([
  160. 'code' => 1,
  161. 'msg' => $cache_data['data']['expires_message'],
  162. ]);
  163. }
  164. $key = $cache_data['data']['key'];
  165. $hostUrl = \Yii::$app->getHost();
  166. // TODO: test hostUrl
  167. // $hostUrl = 'qijian.cyyvip.com';
  168. $updateHost = $this->api_root;
  169. // TODO: test key
  170. // $key = 'f25eaeaf5223b9ce';
  171. // $key = $cache_data['data']['key'];
  172. $curl = new Curl();
  173. $curl->get($updateHost, [
  174. 'a' => "update",
  175. 'v' => $ver,
  176. 'u' => $hostUrl,
  177. 'key' => $key,
  178. ]);
  179. $res = json_decode($curl->response, true);
  180. if (!$res)
  181. return $this->asJson([
  182. 'code' => 1,
  183. 'msg' => '更新失败,与云服务器连接失败',
  184. ]);
  185. if ($res['code'] != 0)
  186. return $this->asJson(
  187. [
  188. 'code' => 1,
  189. 'msg' => strip_tags($res['msg'])
  190. ]
  191. );
  192. $temp_dir = \Yii::$app->basePath . "/temp/update/version/{$ver}";
  193. $res = json_decode($curl->response, true);
  194. $this->mkdir($temp_dir);
  195. $src_file = "{$temp_dir}/src.zip";
  196. $db_file = "{$temp_dir}/db.sql";
  197. $pathUrl = $updateHost . '?a=down&f=' . $res['data']['src_file'];
  198. $get_res_src = $this->get_file($pathUrl, "src.zip", $temp_dir);
  199. if (!$get_res_src) {
  200. return $this->asJson([
  201. 'code' => 1,
  202. 'msg' => '缺失更新文件,请等待',
  203. ]);
  204. }
  205. $pathUrl = $updateHost . '?a=down&f=' . $res['data']['db_file'];
  206. $get_res_db = $this->get_file($pathUrl, "db.sql", $temp_dir);
  207. if (!$get_res_db) {
  208. return $this->asJson([
  209. 'code' => 1,
  210. 'msg' => '缺失数据库更新文件,请等待',
  211. ]);
  212. }
  213. $t = \Yii::$app->db->beginTransaction();
  214. try {
  215. $sql = file_get_contents($db_file);
  216. if ($sql) {
  217. \Yii::$app->db->createCommand($sql)->execute();
  218. }
  219. $zip = Zip::open($src_file);
  220. $zip->extract(\Yii::$app->basePath);
  221. $zip->close();
  222. unlink($src_file);
  223. unlink($db_file);
  224. $version = 'version.json';
  225. $version_info = array();
  226. $version_info['version'] = $res['data']['target_version'];
  227. $json_string = json_encode($version_info);
  228. $app_root = str_replace('\\', '/', \Yii::$app->basePath) . '/';
  229. file_put_contents($app_root . $version, $json_string);
  230. $curl->get($updateHost, [
  231. 'a' => "callback_update",
  232. 'v' => $ver,
  233. 'u' => $hostUrl,
  234. 'key' => $key,
  235. ]);
  236. $t->commit();
  237. if (\RUN_MODE == 'wokerman') {
  238. cache()->set('wokerman_update', 1);
  239. }
  240. try {
  241. if (class_exists('\app\utils\UpdateAfter') && method_exists(\app\utils\UpdateAfter::class, 'handle')) {
  242. \app\utils\UpdateAfter::handle();
  243. }
  244. } catch (\Throwable $ex) {
  245. debug_log($ex->getMessage());
  246. }
  247. return $this->asJson([
  248. 'code' => 0,
  249. 'msg' => '版本更新成功,已更新至v' . $res['data']['target_version'],
  250. ]);
  251. } catch (\Exception $e) {
  252. unlink($src_file);
  253. unlink($db_file);
  254. $t->rollBack();
  255. return $this->asJson([
  256. 'code' => 1,
  257. 'msg' => '更新失败:' . $e->getMessage() .$e->getLine(),
  258. ]);
  259. }
  260. }
  261. /**
  262. * 获取文件
  263. * @param $url
  264. * @param $name
  265. * @param string $folder
  266. * @return bool
  267. */
  268. private function get_file($url, $name, $folder = './')
  269. {
  270. set_time_limit((24 * 60) * 60);
  271. $destination_folder = $folder . '/';
  272. $newfname = $destination_folder . $name;
  273. $file = fopen($url, 'rb');
  274. if ($file) {
  275. $newf = fopen($newfname, 'wb');
  276. if ($newf) {
  277. while (!feof($file)) {
  278. fwrite($newf, fread($file, 1024 * 8), 1024 * 8);
  279. }
  280. }
  281. } else {
  282. return false;
  283. }
  284. if ($file) {
  285. fclose($file);
  286. }
  287. if ($newf) {
  288. fclose($newf);
  289. }
  290. return true;
  291. }
  292. private function mkdir($dir)
  293. {
  294. if (!is_dir($dir)) {
  295. if (!$this->mkdir(dirname($dir))) {
  296. return false;
  297. }
  298. if (!mkdir($dir)) {
  299. return false;
  300. }
  301. }
  302. return true;
  303. }
  304. public static function http_get($url)
  305. {
  306. $oCurl = curl_init();
  307. if (stripos($url, "https://") !== FALSE) {
  308. curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
  309. curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
  310. }
  311. curl_setopt($oCurl, CURLOPT_URL, $url);
  312. curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1);
  313. $sContent = curl_exec($oCurl);
  314. $aStatus = curl_getinfo($oCurl);
  315. curl_close($oCurl);
  316. if (intval($aStatus["http_code"]) == 200) {
  317. return $sContent;
  318. } else {
  319. return false;
  320. }
  321. }
  322. }