common.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. <?php
  2. // 应用公共文件
  3. use app\model\user\User;
  4. use Fastknife\Service\BlockPuzzleCaptchaService;
  5. use Fastknife\Service\ClickWordCaptchaService;
  6. use qiniu\exceptions\AuthException;
  7. use qiniu\services\CacheService;
  8. use qiniu\services\UploadService;
  9. use think\exception\ValidateException;
  10. use think\facade\Log;
  11. if (!function_exists('filter_str')) {
  12. /**
  13. * 过滤字符串敏感字符
  14. * @param $str
  15. * @return array|mixed|string|string[]|null
  16. * @throws Exception
  17. */
  18. function filter_str($str)
  19. {
  20. $param_filter_data = sys_config('param_filter_data');
  21. $param_filter_type = sys_config('param_filter_type', 3);
  22. $rules = preg_split('/\r\n|\r|\n/', base64_decode($param_filter_data));
  23. if ($param_filter_data) {
  24. switch ($param_filter_type) {
  25. case 1://防火墙关闭
  26. return $str;
  27. case 2://报错
  28. foreach ($rules as $rule) {
  29. if (preg_match($rule, $str)) {
  30. throw new \Exception('您的参数存在非要请求,已被拦截');
  31. }
  32. }
  33. break;
  34. case 3://过滤
  35. if (filter_var($str, FILTER_VALIDATE_URL)) {
  36. $url = parse_url($str);
  37. if (!isset($url['scheme'])) return $str;
  38. $host = $url['scheme'] . '://' . $url['host'];
  39. $str = $host . preg_replace($rules, '', str_replace($host, '', $str));
  40. } else {
  41. $str = preg_replace($rules, '', $str);
  42. }
  43. return $str;
  44. }
  45. }
  46. return $str;
  47. }
  48. }
  49. if (!function_exists('response_log_write')) {
  50. /**
  51. * 日志写入
  52. * @param array $data
  53. * @param string $type
  54. */
  55. function response_log_write(array $data, string $type = \think\Log::ERROR)
  56. {
  57. try {
  58. $id = 0;
  59. foreach (['adminId', 'kefuId', 'uid', 'supplierId'] as $value) {
  60. if (method_exists(request(), $value)) {
  61. $id = request()->{$value}();
  62. }
  63. }
  64. //日志内容
  65. $log = [
  66. $id, //管理员ID
  67. request()->ip(), //客户ip
  68. ceil(microtime() - (request()->time(true) * 1000)), //耗时(毫秒)
  69. request()->method(true), //请求类型
  70. str_replace("/", "", request()->rootUrl()), //应用
  71. request()->baseUrl(), //路由
  72. json_encode(request()->param(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),//请求参数
  73. json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), //报错数据
  74. ];
  75. Log::write(implode("|", $log), $type);
  76. } catch (\Throwable $e) {
  77. }
  78. }
  79. }
  80. if (!function_exists('not_empty_check')) {
  81. /**
  82. * 非空验证
  83. * @param $param
  84. * @return bool
  85. */
  86. function not_empty_check($param)
  87. {
  88. if (is_array($param)) {
  89. return !(count($param) <= 0);
  90. } else {
  91. if ($param == '') {
  92. return false;
  93. }
  94. if ($param == null) {
  95. return false;
  96. }
  97. return true;
  98. }
  99. }
  100. }
  101. if (!function_exists('do_request')) {
  102. /**
  103. * CURL 请求接口
  104. * @param string $url 请求地址
  105. * @param array $data 请求参数
  106. * @param array $header 请求头
  107. * @param bool $post true:post请求 false:get请求
  108. * @param bool $json post请求时 请求数据打包方式是否为json
  109. * @param int $format 数据打包为json格式时打包的格式值 来自json_encode
  110. * @param bool $form post请求时 请求数据是否为表单 同时为false时为http提交 优先级高于json
  111. * @return bool|false|string
  112. */
  113. function do_request($url, $query, $data, $header = null, $post = true, $json = false, $format = 0, $form = false)
  114. {
  115. $curl = curl_init();
  116. $url .= ('?' . http_build_query($query));
  117. curl_setopt($curl, CURLOPT_URL, $url);
  118. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  119. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  120. if ($post) {
  121. curl_setopt($curl, CURLOPT_POST, 1);
  122. if (!$json && !$form) {
  123. curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
  124. } else if ($json && !$form) {
  125. curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data, $format));
  126. } else {
  127. curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  128. }
  129. }
  130. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  131. if ($header) {
  132. curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
  133. curl_setopt($curl, CURLOPT_HEADER, 0);
  134. }
  135. $result = curl_exec($curl);
  136. if (curl_errno($curl)) {
  137. return json_encode(['status' => curl_errno($curl), 'msg' => '请求失败']);
  138. }
  139. curl_close($curl);
  140. return $result;
  141. }
  142. }
  143. if (!function_exists('path_to_url')) {
  144. /**
  145. * 路径转url路径
  146. * @param $path
  147. * @return string
  148. */
  149. function path_to_url($path)
  150. {
  151. return trim(str_replace(DS, '/', $path), '.');
  152. }
  153. }
  154. if (!function_exists('get_group_user')) {
  155. //所有下级
  156. function get_group_user($id, $init = true, $members = null)
  157. {
  158. if ($init) {
  159. $us = User::column('spread_uid', 'uid');
  160. $members = [];
  161. foreach ($us as $k => $v) {
  162. if ($v > 0)
  163. $members[$v][] = $k;
  164. }
  165. $id = [$id];
  166. }
  167. $arr = array();
  168. foreach ($id as $v) {
  169. $child = $members[$v] ?? [];
  170. $arr = array_merge($arr, $child);
  171. }
  172. if (count($arr)) {
  173. return array_merge($arr, get_group_user($arr, false, $members));
  174. } else {
  175. return $arr;
  176. }
  177. }
  178. }
  179. if (!function_exists('sys_config')) {
  180. /**
  181. * 获取系统单个配置
  182. * @param string $name
  183. * @param mixed $default
  184. * @param bool $cache
  185. * @return string|array
  186. */
  187. function sys_config(string $name, $default = '', bool $cache = false)
  188. {
  189. if (empty($name))
  190. return $default;
  191. $config = app('sysConfig')->get($name, $default, $cache);
  192. if (is_string($config)) $config = trim($config);
  193. if ($config === '' || $config === false) {
  194. return $default;
  195. } else {
  196. return $config;
  197. }
  198. }
  199. }
  200. if (!function_exists('store_config')) {
  201. /**
  202. * 获取系统单个配置
  203. * @param string $name
  204. * @param int $store_id
  205. * @param mixed $default
  206. * @param bool $cache
  207. * @return string
  208. */
  209. function store_config(string $name, int $store_id, $default = '', bool $cache = false)
  210. {
  211. if (empty($name))
  212. return $default;
  213. $config = app('sysConfig')->setStore($store_id)->get($name, $default, $cache);
  214. if (is_string($config)) $config = trim($config);
  215. if ($config === '' || $config === false) {
  216. return $default;
  217. } else {
  218. return $config;
  219. }
  220. }
  221. }
  222. if (!function_exists('check_phone')) {
  223. /**
  224. * 手机号验证
  225. * @param $phone
  226. * @return false|int
  227. */
  228. function check_phone($phone)
  229. {
  230. return preg_match("/^1[3456789]\d{9}$/", $phone);
  231. }
  232. }
  233. if (!function_exists('check_mail')) {
  234. /**
  235. * 邮箱验证
  236. * @param $mail
  237. * @return false|int
  238. */
  239. function check_mail($mail)
  240. {
  241. if (filter_var($mail, FILTER_VALIDATE_EMAIL)) {
  242. return true;
  243. } else {
  244. return false;
  245. }
  246. }
  247. }
  248. if (!function_exists('aj_captcha_check_one')) {
  249. /**
  250. * 验证滑块1次验证
  251. * @param string $token
  252. * @param string $pointJson
  253. * @return bool
  254. */
  255. function aj_captcha_check_one(string $captchaType, string $token, string $pointJson)
  256. {
  257. aj_get_serevice($captchaType)->check($token, $pointJson);
  258. return true;
  259. }
  260. }
  261. if (!function_exists('aj_captcha_check_two')) {
  262. /**
  263. * 验证滑块2次验证
  264. * @param string $token
  265. * @param string $pointJson
  266. * @return bool
  267. */
  268. function aj_captcha_check_two(string $captchaType, string $captchaVerification)
  269. {
  270. aj_get_serevice($captchaType)->verificationByEncryptCode($captchaVerification);
  271. return true;
  272. }
  273. }
  274. if (!function_exists('aj_captcha_create')) {
  275. /**
  276. * 创建验证码
  277. * @return array
  278. */
  279. function aj_captcha_create(string $captchaType)
  280. {
  281. return aj_get_serevice($captchaType)->get();
  282. }
  283. }
  284. if (!function_exists('aj_get_serevice')) {
  285. /**
  286. * @param string $captchaType
  287. * @return ClickWordCaptchaService|BlockPuzzleCaptchaService
  288. */
  289. function aj_get_serevice(string $captchaType)
  290. {
  291. $config = \think\facade\Config::get('ajcaptcha');
  292. switch ($captchaType) {
  293. case "clickWord":
  294. $service = new ClickWordCaptchaService($config);
  295. break;
  296. case "blockPuzzle":
  297. $service = new BlockPuzzleCaptchaService($config);
  298. break;
  299. default:
  300. throw new ValidateException('captchaType参数不正确!');
  301. }
  302. return $service;
  303. }
  304. }
  305. if (!function_exists('sort_list_tier')) {
  306. /**
  307. * 分级排序
  308. * @param $data
  309. * @param int $pid
  310. * @param string $field
  311. * @param string $pk
  312. * @param string $html
  313. * @param int $level
  314. * @param bool $clear
  315. * @return array
  316. */
  317. function sort_list_tier($data, $pid = 0, $field = 'pid', $pk = 'id', $html = '|-----', $level = 1, $clear = true)
  318. {
  319. static $list = [];
  320. if ($clear) $list = [];
  321. foreach ($data as $k => $res) {
  322. if ($res[$field] == $pid) {
  323. $res['html'] = str_repeat($html, $level);
  324. $list[] = $res;
  325. unset($data[$k]);
  326. sort_list_tier($data, $res[$pk], $field, $pk, $html, $level + 1, false);
  327. }
  328. }
  329. return $list;
  330. }
  331. }
  332. if (!function_exists('get_tree_children')) {
  333. /**
  334. * 获取树状结构子集
  335. */
  336. function get_tree_children($data, $id = 0, $field = 'id', $pid = 'pid', $init = true)
  337. {
  338. static $children;
  339. if ($init) {
  340. $children = [];
  341. foreach ($data as $v) {
  342. $children[$v[$pid]][] = $v;
  343. }
  344. }
  345. $arr = ($children[$id] ?? []);
  346. foreach ($arr as &$v) {
  347. $v['children'] = get_tree_children($data, $v[$field], $field, $pid, false);
  348. }
  349. return $arr;
  350. }
  351. }
  352. if (!function_exists('set_file_url')) {
  353. /**
  354. * @param $file
  355. * @return mixed|string
  356. */
  357. function set_file_url($file)
  358. {
  359. if (!is_array($file)) {
  360. $file = [$file];
  361. }
  362. foreach ($file as &$v) {
  363. if (strpos($v, '://') === false) {
  364. $v = rtrim(sys_config('site_url', ''), '/') . '/' . ltrim($v, '/');
  365. }
  366. }
  367. return $file;
  368. }
  369. }
  370. if (!function_exists('check_link')) {
  371. /**
  372. * @param $file
  373. * @return mixed|string
  374. */
  375. function check_link($url)
  376. {
  377. $ch = curl_init();
  378. try {
  379. curl_setopt($ch, CURLOPT_URL, $url);
  380. curl_setopt($ch, CURLOPT_HEADER, 1);
  381. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  382. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
  383. $contents = curl_exec($ch);
  384. if (preg_match("/404/", $contents)) return false;
  385. if (preg_match("/403/", $contents)) return false;
  386. return true;
  387. } catch (\Exception $e) {
  388. return false;
  389. }
  390. }
  391. }
  392. if (!function_exists('filter_emoji')) {
  393. // 过滤掉emoji表情
  394. function filter_emoji($str)
  395. {
  396. return preg_replace_callback( //执行一个正则表达式搜索并且使用一个回调进行替换
  397. '/./u',
  398. function (array $match) {
  399. return strlen($match[0]) >= 4 ? '' : $match[0];
  400. },
  401. $str);
  402. }
  403. }
  404. if (!function_exists('getFileHeaders')) {
  405. /**
  406. * 获取文件大小头部信息
  407. * @param string $url
  408. * @param $isData
  409. * @return array
  410. */
  411. function getFileHeaders(string $url, $isData = true)
  412. {
  413. stream_context_set_default(['ssl' => ['verify_peer' => false, 'verify_peer_name' => false]]);
  414. $header['size'] = 0;
  415. $header['type'] = 'image/jpeg';
  416. if (!$isData) {
  417. return $header;
  418. }
  419. try {
  420. $headerArray = get_headers(str_replace('\\', '/', $url), true);
  421. if (!isset($headerArray['Content-Length'])) {
  422. $header['size'] = 0;
  423. } else {
  424. if (is_array($headerArray['Content-Length']) && count($headerArray['Content-Length']) == 2) {
  425. $header['size'] = $headerArray['Content-Length'][1];
  426. } else {
  427. $header['size'] = $headerArray['Content-Length'] ?? 0;
  428. }
  429. }
  430. if (!isset($headerArray['Content-Type'])) {
  431. $header['type'] = 'image/jpeg';
  432. } else {
  433. if (is_array($headerArray['Content-Type']) && count($headerArray['Content-Type']) == 2) {
  434. $header['type'] = $headerArray['Content-Type'][1];
  435. } else {
  436. $header['type'] = $headerArray['Content-Type'] ?? 'image/jpeg';
  437. }
  438. }
  439. } catch (\Exception $e) {
  440. }
  441. return $header;
  442. }
  443. }
  444. if (!function_exists('formatFileSize')) {
  445. /**
  446. * 格式化文件大小
  447. * @param $size
  448. * @return mixed|string|null
  449. */
  450. function formatFileSize($size)
  451. {
  452. if (!$size) {
  453. return '0KB';
  454. }
  455. try {
  456. $toKb = 1024;
  457. $toMb = $toKb * 1024;
  458. $toGb = $toMb * 1024;
  459. if ($size >= $toGb) {
  460. return round($size / $toGb, 2) . 'GB';
  461. } elseif ($size >= $toMb) {
  462. return round($size / $toMb, 2) . 'MB';
  463. } elseif ($size >= $toKb) {
  464. return round($size / $toKb, 2) . 'KB';
  465. } else {
  466. return $size . 'B';
  467. }
  468. } catch (Exception $e) {
  469. return '0KB';
  470. }
  471. }
  472. }
  473. if (!function_exists('get_image_thumb')) {
  474. /**
  475. * 获取缩略图
  476. * @param $filePath
  477. * @param string $type all|big|mid|small
  478. * @param bool $is_remote_down
  479. * @return mixed|string|string[]
  480. */
  481. function get_image_thumb($filePath, string $type = 'all', bool $is_remote_down = false)
  482. {
  483. if (!$filePath || !is_string($filePath) || strpos($filePath, '?') !== false) return $filePath;
  484. try {
  485. $arr = explode('.', $filePath);
  486. $ext_name = trim($arr[count($arr) - 1]);
  487. if (!in_array($ext_name, ['png', 'jpg', 'jpeg'])) {
  488. return $filePath;
  489. }
  490. $upload = UploadService::getOssInit($filePath, $is_remote_down);
  491. $data = $upload->thumb('', $type);
  492. $image = $type == 'all' ? $data : $data[$type] ?? $filePath;
  493. } catch (\Throwable $e) {
  494. $image = $filePath;
  495. // throw new ValidateException($e->getMessage());
  496. Log::error('获取缩略图失败,原因:' . $e->getMessage() . '----' . $e->getFile() . '----' . $e->getLine() . '----' . $filePath);
  497. }
  498. $data = parse_url($image);
  499. if (!isset($data['host']) && (substr($image, 0, 2) == './' || substr($image, 0, 1) == '/')) {//不是完整地址
  500. $image = sys_config('site_url') . $image;
  501. }
  502. //请求是https 图片是http 需要改变图片地址
  503. if (strpos(request()->domain(), 'https:') !== false && strpos($image, 'https:') === false) {
  504. $image = str_replace('http:', 'https:', $image);
  505. }
  506. return $image;
  507. }
  508. }
  509. if (!function_exists('get_thumb_water')) {
  510. /**
  511. * 处理数组获取缩略图、水印
  512. * @param $list
  513. * @param string $type
  514. * @param array|string[] $field 1、['image','images'] type 取值参数:type 2、['small'=>'image','mid'=>'images'] type 取field数组的key
  515. * @param bool $is_remote_down
  516. * @return array|mixed|string|string[]
  517. */
  518. function get_thumb_water($list, string $type = 'small', array $field = ['image'], bool $is_remote_down = false)
  519. {
  520. if (!$list || !$field) return $list;
  521. $baseType = $type;
  522. $data = $list;
  523. if (is_string($list)) {
  524. $field = [$type => 'image'];
  525. $data = ['image' => $list];
  526. }
  527. if (is_array($data)) {
  528. foreach ($field as $type => $key) {
  529. if (is_integer($type)) {//索引数组,默认type
  530. $type = $baseType;
  531. }
  532. //一维数组
  533. if (isset($data[$key])) {
  534. if (is_array($data[$key])) {
  535. $path_data = [];
  536. foreach ($data[$key] as $k => $path) {
  537. $path_data[] = get_image_thumb($path, $type, $is_remote_down);
  538. }
  539. $data[$key] = $path_data;
  540. } else {
  541. $data[$key] = get_image_thumb($data[$key], $type, $is_remote_down);
  542. }
  543. } else {
  544. foreach ($data as &$item) {
  545. if (!isset($item[$key]))
  546. continue;
  547. if (is_array($item[$key])) {
  548. $path_data = [];
  549. foreach ($item[$key] as $k => $path) {
  550. $path_data[] = get_image_thumb($path, $type, $is_remote_down);
  551. }
  552. $item[$key] = $path_data;
  553. } else {
  554. $item[$key] = get_image_thumb($item[$key], $type, $is_remote_down);
  555. }
  556. }
  557. }
  558. }
  559. }
  560. return is_string($list) ? ($data['image'] ?? '') : $data;
  561. }
  562. }
  563. if (!function_exists('make_path')) {
  564. /**
  565. * 上传路径转化,默认路径
  566. * @param $path
  567. * @param int $type
  568. * @param bool $force
  569. * @return string
  570. * @throws Exception
  571. */
  572. function make_path($path, int $type = 2, bool $force = false)
  573. {
  574. $path = DS . ltrim(rtrim($path));
  575. switch ($type) {
  576. case 1:
  577. $path .= DS . date('Y');
  578. break;
  579. case 2:
  580. $path .= DS . date('Y') . DS . date('m');
  581. break;
  582. case 3:
  583. $path .= DS . date('Y') . DS . date('m') . DS . date('d');
  584. break;
  585. }
  586. try {
  587. if (is_dir(app()->getRootPath() . 'public' . DS . 'uploads' . $path) == true || mkdir(app()->getRootPath() . 'public' . DS . 'uploads' . $path, 0777, true) == true) {
  588. return trim(str_replace(DS, '/', $path), '.');
  589. } else return '';
  590. } catch (Exception $e) {
  591. if ($force)
  592. throw new Exception($e->getMessage());
  593. return '无法创建文件夹,请检查您的上传目录权限:' . app()->getRootPath() . 'public' . DS . 'uploads' . DS . 'attach' . DS;
  594. }
  595. }
  596. }
  597. if (!function_exists('verify_domain')) {
  598. /**
  599. * @param $url
  600. * @return false|string
  601. */
  602. function verify_domain($url)
  603. {
  604. if (!$url) return false;
  605. if (strpos($url, 'http') === false) return false;
  606. return rtrim($url, '/');
  607. }
  608. }
  609. if (!function_exists('password')) {
  610. /**
  611. * @param $string
  612. * @param null $salt
  613. * @return array
  614. * @throws Exception
  615. */
  616. function password($string, $salt = null)
  617. {
  618. if (!$salt)
  619. $salt = bin2hex(random_bytes(6));
  620. return [md5(md5($string) . $salt), $salt];
  621. }
  622. }
  623. if (!function_exists('parseName')) {
  624. /**
  625. * 字符串命名风格转换
  626. * type 0 将 Java 风格转换为 C 的风格 1 将 C 风格转换为 Java 的风格
  627. * @access public
  628. * @param string $name 字符串
  629. * @param integer $type 转换类型
  630. * @param bool $ucfirst 首字母是否大写(驼峰规则)
  631. * @return string
  632. */
  633. function parseName($name, $type = 0, $ucfirst = true)
  634. {
  635. if ($type) {
  636. $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) {
  637. return strtoupper($match[1]);
  638. }, $name ?? '');
  639. return $ucfirst ? ucfirst($name) : lcfirst($name);
  640. }
  641. return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
  642. }
  643. }
  644. if (!function_exists('check_card')) {
  645. function check_card($idCard)
  646. {
  647. // 去除空格
  648. $idCard = trim($idCard);
  649. // 18位身份证号码正则表达式
  650. $pattern = '/^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[0-9Xx]$/';
  651. if (!preg_match($pattern, $idCard)) {
  652. return false;
  653. }
  654. // 校验码验证
  655. $weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
  656. $checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
  657. $sum = 0;
  658. for ($i = 0; $i < 17; $i++) {
  659. $sum += intval($idCard[$i]) * $weights[$i];
  660. }
  661. $checkCodeIndex = $sum % 11;
  662. $expectedCheckCode = $checkCodes[$checkCodeIndex];
  663. return strtoupper($idCard[17]) === $expectedCheckCode;
  664. }
  665. }
  666. if (!function_exists('check_password')) {
  667. function check_password($value)
  668. {
  669. // 正则表达式:至少6位,最多18位,包含大小写字母、数字和特殊字符
  670. $pattern = '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).{6,18}$/';
  671. return preg_match($pattern, $value) === 1;
  672. }
  673. }
  674. if (!function_exists('check_trade_password')) {
  675. function check_trade_password($value)
  676. {
  677. return preg_match('/^\d{6}$/', $value) === 1;
  678. }
  679. }
  680. if (!function_exists('check_sms_captcha')) {
  681. function check_sms_captcha($phone, $type, $code)
  682. {
  683. $verifyCode = CacheService::get('code_' . $phone . '_' . $type);
  684. if (!$verifyCode)
  685. throw new AuthException('请先获取验证码');
  686. $verifyError = (int)CacheService::get('code_error_' . $phone . '_' . $type, 0);
  687. if ($verifyError >= 10) {
  688. throw new AuthException('错误次数过多,请稍后再试');
  689. }
  690. $verifyCode = substr($verifyCode, 0, 6);
  691. if ($verifyCode != $code) {
  692. CacheService::set('code_error_' . $phone . '_' . $type, $verifyError + 1, 180);
  693. throw new AuthException('验证码错误');
  694. }
  695. CacheService::delete('code_' . $phone . '_' . $type);
  696. CacheService::delete('code_error_' . $phone . '_' . $type);
  697. }
  698. }
  699. if (!function_exists('random_string')) {
  700. function random_string($length)
  701. {
  702. mt_rand();
  703. $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  704. $randomString = '';
  705. for ($i = 0; $i < $length; $i++) {
  706. $index = rand(0, strlen($characters) - 1);
  707. $randomString .= $characters[$index];
  708. }
  709. return $randomString;
  710. }
  711. }
  712. if (!function_exists('create_account')) {
  713. function create_account()
  714. {
  715. do {
  716. $randomString = 'qn_' . random_string(16) . '_' . random_string(4);
  717. } while (User::where('account', $randomString)->find());
  718. return $randomString;
  719. }
  720. }
  721. if (!function_exists('curl_file_exist')) {
  722. function curl_file_exist($url)
  723. {
  724. $ch = curl_init($url);
  725. curl_setopt($ch, CURLOPT_NOBODY, true); // 不需要返回体
  726. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向
  727. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回结果而不是直接输出
  728. curl_exec($ch);
  729. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  730. curl_close($ch);
  731. return $httpCode == 200;
  732. }
  733. }