* @date 2019-11-01 14:42:37 */ declare(strict_types=1); use App\Repositories\Service\CommonService; use App\Repositories\Utils\M3u8CacheRepository; use Hashids\Hashids; /** * 获取分页start offset * @param $amount * @param int $page * @param int $page_size * @return int|mixed */ function get_page_start($amount, $page = 1, $page_size = 20) { if (empty($amount)) { return $page_size; } $page_size = empty($page_size) ? 20 : $page_size; $page_most = ceil($amount / $page_size); if (isset($page)) { $page = intval($page); if ($page > $page_most) { $page = $page_most; } } else { $page = 1; } $page = max(1, $page); // 找出最大值. $start_limit = ($page - 1) * $page_size; return intval($start_limit); } /** * 格式化页码入参 * @param $page * @return int */ function format_page($page) { $page = intval($page); if ($page <= 0) { $page = 1; } if ($page > PHP_INT_MAX) { $page = PHP_INT_MAX; } return $page; } /** * 密码星号加密 * @param string $str 输入的字符串 * @return string */ function pass_encode($str) { $len = strlen($str); if ($len < 1) { return ''; } $new = ''; for ($i = 0; $i < $len; $i++) { $new .= ($i == 0 || $i == $len - 1) ? $str[$i] : '*'; } return $new; } /** * 密码星号解密 * @param string $new 明文密码 * @param string $old 原始密码 * @return mixed */ function pass_decode($new, $old) { return $new == pass_encode($old) ? $old : $new; } /** * 加密手机号 * @param $mobile * @return string */ function encode_mobile($mobile) { $str = ''; if ($mobile) { $len = strlen($mobile); for ($i = 0; $i < $len; $i++) { $str .= ($i < 5 || $i > $len - 4) ? $mobile[$i] : '*'; } } return $str; } /** * 更新OpCache * 生成缓存php文件的地方都需要调用此函数 * @return void */ function opcache_update() { if (function_exists('opcache_reset')) { opcache_reset(); } } /** * 获取相对依赖双斜杠开头的URL地址 * @param $url * @return mixed */ function get_slashes_url($url) { if (preg_match('/^(http|https)\:\/\/(.*?)$/i', $url, $arr_matches)) { return '//' . $arr_matches[2]; } else { return $url; } } /** * json响应成功 * @param mixed $data 数据 * @param string $message 消息 * @return mixed */ function json_success($data, $message = '操作成功') { $handshake = ''; $isValidMg = false; if (class_exists('\Modules\Manage\Services\AuthService')) { $service = make(\Modules\Manage\Services\AuthService::class); // 如果有效后台header,则直接不加密,进行明文通讯. $isValidMg = $service->checkValidMgHeaderHandShake(); } if (!$isValidMg) { $handshake = \App\Constants\CommonConstant::getHandShake(); if (!empty($handshake)) { $inputData = request()->all(); $inputHandShake = $inputData['handshake'] ?? $handshake; $arrMap = \App\Constants\CommonConstant::getHandSnakeKey($inputHandShake); // $arrMap = \App\Constants\CommonConstant::getHandSnakeKey($handshake); $data = hand_encrypt(json_encode($data), $arrMap['key'], ''); $handshake = $inputHandShake; } } $res = [ 'code' => 200, 'message' => $message, 'data' => $data, 'handshake' => $handshake, ]; return response()->json($res); } /** * json响应失败 * @param string $message 消息 * @param int $code 代码 * @return mixed */ function json_fail($message, $code = 500, $data = []) { $handshake = ''; $isValidMg = false; if (class_exists('\Modules\Manage\Services\AuthService')) { $service = make(\Modules\Manage\Services\AuthService::class); // 如果有效后台header,则直接不加密,进行明文通讯. $isValidMg = $service->checkValidMgHeaderHandShake(); } if (!$isValidMg) { $handshake = \App\Constants\CommonConstant::getHandShake(); if (!empty($handshake)) { $inputData = request()->all(); $inputHandShake = $inputData['handshake'] ?? $handshake; $arrMap = \App\Constants\CommonConstant::getHandSnakeKey($inputHandShake); // $arrMap = \App\Constants\CommonConstant::getHandSnakeKey($handshake); if (!empty($data)) { $data = hand_encrypt($data, $arrMap['key'], ''); } else { $data = ''; } $handshake = $inputHandShake; } } $res = [ 'code' => $code, 'message' => $message, 'data' => $data, 'handshake' => $handshake, ]; return response()->json($res); } function json_stock_fail($message, $code = 500) { $res = [ 'code' => $code, 'message' => $message, ]; // return json_encode($res); $result = ''; $handshake = \App\Constants\CommonConstant::getHandShake(); $handshake = 'prod'; if (!empty($handshake)) { $key = \App\Constants\CommonConstant::getStockHandSnakeKey(); $result = hand_encrypt($res, $key, ''); } return $result; } function json_stock_success($data, $message = '成功') { $res = [ 'code' => 200, 'result' => $data, 'message' => $message ]; // return json_encode($res); $result = ''; $handshake = \App\Constants\CommonConstant::getHandShake(); $handshake = 'prod'; if (!empty($handshake)) { $key = \App\Constants\CommonConstant::getStockHandSnakeKey(); $result = hand_encrypt($res, $key, ''); } return $result; } /** * 随机生成指定长度字符串 * @param int $len 长度 * @return string */ function rand_letter($len = 18) { $str = ''; if ($len <= 0) { $len = 18; } $chars = "abcdefhjmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWYXZ"; $clen = strlen($chars); $max = $clen - 1; for ($i = 0; $i < $len; $i++) { $str .= $chars[mt_rand(0, $max)]; } return $str; } /** * 随机生成字符串 * @param int $length 长度 * @param int $numeric 纯数字 * @return string */ function random($length, $numeric = 0) { if (version_compare(PHP_VERSION, '4.2.0', '<')) { mt_srand((double)microtime() * 1000000); } else { mt_srand(); } $seed = base_convert(md5(mt_rand(1, 9) . microtime()), 16, $numeric ? 10 : 35); $seed = $numeric ? (str_replace('0', '', $seed) . '012340567890') : ($seed . 'zZ' . strtoupper($seed)); $hash = ''; $max = strlen($seed) - 1; for ($i = 0; $i < $length; $i++) { $hash .= $seed[mt_rand(0, $max)]; } return $hash; } /** * AES 加密 * @param mixed $content 明文 * @param string $key 密钥 * @param string $iv 向量,必须为数字 * @param string $cipher 算法. * @param int $option 标记的按位或: OPENSSL_RAW_DATA=1 、 OPENSSL_ZERO_PADDING=2. * @return string */ function aes_encrypt($content, $key, $iv = '', $cipher = 'AES-256-CBC', $option = 1) { $ivLength = openssl_cipher_iv_length($cipher); // 向量长度. /*$iv = openssl_random_pseudo_bytes($ivLength); // 根据长度生成向量.*/ //$option = OPENSSL_RAW_DATA; // 标记的按位或: OPENSSL_RAW_DATA=1 、 OPENSSL_ZERO_PADDING=2. $tag = null; // 使用 AEAD 密码模式(GCM 或 CCM)时传引用的验证标签. $aad = ''; // 附加的验证数据. $tagLength = 16; // 验证 tag 的长度。GCM 模式时,它的范围是 4 到 16. $iv = (string)$iv; return @openssl_encrypt($content, $cipher, $key, $option, $iv); } /** * AES 解密 * @param string $content base64密文 * @param string $key 密钥 * @param string $iv 向量,必须为数字 * @param string $cipher 算法. * @param int $option 标记的按位或: OPENSSL_RAW_DATA=1 、 OPENSSL_ZERO_PADDING=2. * @return string */ function aes_decrypt($content, $key, $iv = '', $cipher = 'AES-256-CBC', $option = 1) { $iv = (string)$iv; return @openssl_decrypt($content, $cipher, $key, $option, $iv); } /** * 通讯握手加密. * @param $content * @param $key * @param string $iv 向量,必须为数字 * @return string */ function hand_encrypt($content, $key, $iv = ''): string { $cipher = 'AES-128-ECB'; if (is_array($content)) { $content = json_encode($content, JSON_UNESCAPED_UNICODE); } return base64_encode(aes_encrypt($content, $key, $iv, $cipher, 1)); } /** * 通信握手解密. * @param $content * @param $key * @param string $iv 向量,必须为数字 * @return false|string */ function hand_decrypt($content, $key, $iv = '') { $cipher = 'AES-128-ECB'; $content = base64_decode($content); return aes_decrypt($content, $key, $iv, $cipher, 1); } /** * 获取Request解密数据. * @return array|mixed */ function getDecodeData() { $isValidMg = false; if (class_exists('\Modules\Manage\Services\AuthService')) { $service = make(\Modules\Manage\Services\AuthService::class); // 如果有效后台header,则直接不加密,进行明文通讯. $isValidMg = $service->checkValidMgHeaderHandShake(); } $inputData = request()->all(); if (!$isValidMg) { // 先拿系统里当前flag. $handshake = \App\Constants\CommonConstant::getHandShake(); if (!empty($handshake)) { $allowShake = \App\Constants\CommonConstant::allowHandShakeKeys(); $inputHandShake = $inputData['handshake'] ?? random(7); if (!array_key_exists($inputHandShake, $allowShake) || empty($inputHandShake)) { throw new \App\Exception\ApiException('在天愿作比翼鸟,在地愿为连理枝'); } // if ($inputHandShake != $handshake) { // throw new \App\Exception\ApiException('在天愿作比翼鸟,在地愿为连理枝'); // } $originData = $inputData['data'] ?? ''; if (!is_string($originData)) { throw new \App\Exception\ApiException('数据格式有误1'); } $arrMap = \App\Constants\CommonConstant::getHandSnakeKey($inputHandShake); try { $data = !empty($originData) ? json_decode(hand_decrypt($originData, $arrMap['key'], ''), true) : []; } catch (\Throwable $exception) { throw new \App\Exception\ApiException('数据格式有误2'); } } else { $data = $inputData['data'] ?? []; } } else { $data = $inputData['data'] ?? []; } return $data; } /** * 过滤数据 * @param $data - 1维数据 * @return array * @tutorial 若数组值不是空长度则保留,反之就清除过滤 */ function action_data($data = array()) { if (!$data) { return $data; } foreach ($data as $k => $v) { if (mb_strlen((string)$v) < 1) { unset($data[$k]); } } return $data; } /** * 加密ID. * @param $id * @param int $length 长度 * @return string */ function hashEncodeId($id, $length = 6) { $hashids = new Hashids(config('hashids.salt', ''), 6); return $hashids->encode($id); } /** * 解密ID. * @param $str * @return string */ function hashDecodeId($str) { $hashids = new Hashids(config('hashids.salt', ''), 6); $arr = $hashids->decode($str); return implode('', $arr); } /** * 权重计算 * * @param $data * @return mixed */ function countWeight($data) { $temp = []; foreach ($data as $v) { if (isset($v->weights)) { for ($i = 0; $i < $v->weights; $i++) { $temp[] = $v;//放大数组 } } else { for ($i = 0; $i < $v['weights']; $i++) { $temp[] = $v;//放大数组 } } } $num = count($temp); //查看网上的有错误,本人已改正 $int = mt_rand(0, $num - 1);//获取一个随机数 $result = $temp[$int]; return $result; //返回一维数组 } /** * 凯撒对称加密核心算法 * @param string $str 字符串源 * @param string $type 类型,encode=加密,decode=解密 * @param string $scale 范围, c=中文, l=字母, n=数字,多种用半角逗号分隔开 * @param int $offset 偏移 * @return string */ function caesar_cipher($str, $type = 'encode', $scale = 'c,l,n', $offset = 3) { if (empty($str)) { return ''; } if (!$offset) { // 无偏移, 直接返回原来的字符串 return $str; } if (empty($scale)) { $scale = 'c,l,n'; } if ($type == 'decode') { // 解密反向偏移 $offset = -$offset; } $func = function ($match, $offset, $start, $end) { $min = ord($start); $max = ord($end); $flag_old = ord($match); $flag = $flag_old + $offset; if ($offset > 0) { if ($flag > $max) { $flag -= ($max - $min) + 1; } } elseif ($offset < 0) { if ($flag < $min) { $flag += ($max - $min) + 1; } } return chr($flag); }; $arr_scale = explode(',', $scale); //允许的范围转换成数组,方便判断 $pattern = '/[\x{4e00}-\x{9fbb}a-zA-Z0-9]/u'; $result = preg_replace_callback( $pattern, function ($matches) use ($offset, $arr_scale, $func) { $str = $match = $matches[0]; if (preg_match('/[\x{4e00}-\x{9fbb}]/u', $match)) { // 汉字 if (in_array('c', $arr_scale)) { $min = intval(hexdec(unpack("H6codes", "一")['codes'])); $max = intval(hexdec(unpack("H6codes", "龻")['codes'])); $arr_hex = unpack("H6codes", $match); $zi_hex = $arr_hex['codes']; $zi_dec = intval(hexdec($zi_hex)); $flag = $zi_dec + $offset; if ($offset > 0) { if ($flag > $max) { $flag -= ($max - $min) + 1; } } elseif ($offset < 0) { if ($flag < $min) { $flag += ($max - $min) + 1; } } $str_hex = dechex($flag); $str = pack("H". strlen($str_hex), $str_hex); } } elseif (preg_match('/[0-9]/', $match)) { // 数字 if (in_array('n', $arr_scale)) { $str = $func($match, $offset, '0', '9'); } } elseif (preg_match('/[a-z]/', $match)) { // 小写字母 if (in_array('l', $arr_scale)) { $str = $func($match, $offset, 'a', 'z'); } } elseif (preg_match('/[A-Z]/', $match)) { // 大写字母 if (in_array('l', $arr_scale)) { $str = $func($match, $offset, 'A', 'Z'); } } return $str; }, $str ); return $result; } /** * 凯撒对称加密 * @param string $str 字符串源 * @param string $scale 范围, c=中文, l=字母, n=数字,多种用半角逗号分隔开 * @param int $offset 偏移 * @return string */ function caesar_encode($str, $scale = 'c,l,n', $offset = 3) { return caesar_cipher($str, 'encode', $scale, $offset); } /** * 凯撒对称解密 * @param string $str 字符串源 * @param string $scale 范围, c=中文, l=字母, n=数字,多种用半角逗号分隔开 * @param int $offset 偏移 * @return string */ function caesar_decode($str, $scale = 'c,l,n', $offset = 3) { return caesar_cipher($str, 'decode', $scale, $offset); } /** * 处理异常时间的问题(如2022-02-31) * * @param $date * @return bool */ function checkmydate($date) { $tempDate = explode('-', $date); return checkdate((int)$tempDate[1], (int)$tempDate[2], (int)$tempDate[0]); } /** * 处理结构体 * * @param $message * @return mixed */ function structureHandle(string $content, string $msgType) { $content = json_decode($content, true); switch ($msgType) { case 'text': $content['text'] = make(CommonService::class)->filterString($content['text']); break; case 'image': case 'file': case 'audio': $content['url'] = M3u8CacheRepository::getImageUrl($content['url']); break; case 'media': $content['url'] = M3u8CacheRepository::getVideoInnerUrl($content['url']); $content['cover'] = M3u8CacheRepository::getImageUrl($content['cover']); } return $content; } /** * 计算两个日期相隔多少年,多少月,多少天 * * @param $startDate * @param $endData * @return array * @throws Exception */ function diffDate($startDate, $endData) { $datetime1 = new \DateTime($startDate); $datetime2 = new \DateTime($endData); $interval = $datetime1->diff($datetime2); $time['y'] = $interval->format('%Y'); $time['m'] = $interval->format('%m'); $time['d'] = $interval->format('%d'); return $time; } /** * 检测支付链接协议 * * @param $payUrl * @return mixed|string */ function checkPayUrl($payUrl) { if (strpos($payUrl, 'alipays://') !== false) { $payUrl = 'https://r.tool.py163.xyz/dk.html?_r_=' . urlencode($payUrl); } return $payUrl; } function truncateText($text, $max_length = 100, $suffix = '...') { if (mb_strlen($text, 'UTF-8') <= $max_length) { return $text; } return mb_substr($text, 0, $max_length, 'UTF-8') . $suffix; }