= 224) { $bits = 3; $count++; //第一个字节大于192小于224的,它与它之后的1个字节组成一个UTF-8字符 } elseif ($c >= 192) { $count++; $bits = 2; //否则第一个字节本身就是一个英文字符(包括数字和一小部分标点符号) } else { $bits = 1; $count += 0.5; } } $slen = $slen + $bits; $i = $i + $bits; } return substr($string, 0, $slen) . $ext; } //返回中文字数(二个字母会当一个汉字) static function getWordNum($string, $code = 'utf-8') { $i = 0; //开始字节数 $count = 0; //开始字数 if ($code == 'utf-8') { //utf-8编码 while (isset($string[$i]) && ord($string[$i]) != 0) { //还没有到结尾 $b = ord($string[$i]); //第一个字节大于224的,它与它之后的2个字节一起组成一个UTF-8字符 if ($b >= 224) { $i += 3; $count++; //第一个字节大于192小于224的,它与它之后的1个字节组成一个UTF-8字符 } elseif ($b >= 192) { $i += 2; $count++; //否则第一个字节本身就是一个英文字符(包括数字和一小部分标点符号) } else { $i += 1; $count += 0.5; } } return ceil($count); } //gkb编码 while (isset($string[$i]) && ord($string[$i]) != 0) { $b = ord($string[$i]); //第一个字节ASCII码>129的,它与它之后的1个字节一起组成一个gbk字符。 if ($b > 129) { $i += 2; $count++; //第一个字节ASCII码<=129的,一个字节组成一个gbk字符。 } else { $i++; $count += 0.5; } } return ceil($count); } //取汉字拼音首字母 //https://github.com/overtrue/pinyin public static function py($string) { if (empty($string)) { return ''; } //如果包含中文 if (preg_match('/[\x{4e00}-\x{9fa5}]/u', $string) > 0) { $pinyin = new Pinyin(); $string = $pinyin->abbr($string, PINYIN_KEEP_ENGLISH); } return strtolower($string); } //取随机数 static function charsShuffle($length) { $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $key = ''; for ($i = 0; $i < $length; $i++) { $pos = mt_rand(0, strlen($str) - 1); $key .= $str[$pos]; } return $key; } //取随机数(小写) static function charsShuffleLowerCase($length) { $str = 'abcdefghijklmnopqrstuvwxyz0123456789'; $key = ''; for ($i = 0; $i < $length; $i++) { $pos = mt_rand(0, strlen($str) - 1); $key .= $str[$pos]; } return $key; } //随机取数字 static function getRandNum($num) { $shuffle = str_shuffle('1234567890'); $number = substr($shuffle, 0, $num); return $number; } // $string: 明文 或 密文 // $operation:DECODE表示解密,其它表示加密 // $key: 密匙 // $expiry:密文有效期 public function authcode($string, $operation = 'DECODE', $expiry = 0) { // 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙 $ckey_length = 4; // 密匙 $key = md5(self::KEY); // 密匙a会参与加解密 $keya = md5(substr($key, 0, 16)); // 密匙b会用来做数据完整性验证 $keyb = md5(substr($key, 16, 16)); // 密匙c用于变化生成的密文 $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : ''; // 参与运算的密匙 $cryptkey = $keya . md5($keya . $keyc); $key_length = strlen($cryptkey); // 明文,前10位用来保存时间戳,解密时验证数据有效性,10到26位用来保存$keyb(密匙b),解密时会通过这个密匙验证数据完整性 // 如果是解码的话,会从第$ckey_length位开始,因为密文前$ckey_length位保存 动态密匙,以保证解密正确 $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string; $string_length = strlen($string); $result = ''; $box = range(0, 255); $rndkey = array(); // 产生密匙簿 for ($i = 0; $i <= 255; $i++) { $rndkey[$i] = ord($cryptkey[$i % $key_length]); } // 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度 for ($j = $i = 0; $i < 256; $i++) { $j = ($j + $box[$i] + $rndkey[$i]) % 256; $tmp = $box[$i]; $box[$i] = $box[$j]; $box[$j] = $tmp; } // 核心加解密部分 for ($a = $j = $i = 0; $i < $string_length; $i++) { $a = ($a + 1) % 256; $j = ($j + $box[$a]) % 256; $tmp = $box[$a]; $box[$a] = $box[$j]; $box[$j] = $tmp; // 从密匙簿得出密匙进行异或,再转成字符 $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256])); } if ($operation == 'DECODE') { // substr($result, 0, 10) == 0 验证数据有效性 // substr($result, 0, 10) - time() > 0 验证数据有效性 // substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性 // 验证数据有效性,请看未加密明文的格式 if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) { return substr($result, 26); } else { return ''; } } else { // 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因 // 因为加密后的密文可能是一些特殊字符,复制过程可能会丢失,所以用base64编码 return $keyc . str_replace('=', '', base64_encode($result)); } } /** * 返回8位随机字符,重复概率较低 */ public static function getRandStr($id = null) { $chars = "0123456789abcdefghijklmnopqrstuvwxyz"; $res = ""; for ($i = 0; $i < 8; $i++) { $res .= $chars[mt_rand(0, strlen($chars) - 1)]; } $rand = empty($id) ? $res : $res . $id; return $rand; } public static function randIP() { $arr_1 = array("218", "218", "66", "66", "218", "218", "60", "60", "202", "204", "66", "66", "66", "59", "61", "60", "222", "221", "66", "59", "60", "60", "66", "218", "218", "62", "63", "64", "66", "66", "122", "211"); $randarr = mt_rand(0, count($arr_1)); $ip1id = $arr_1[$randarr]; $ip2id = round(rand(600000, 2550000) / 10000); $ip3id = round(rand(600000, 2550000) / 10000); $ip4id = round(rand(600000, 2550000) / 10000); return $ip1id . "." . $ip2id . "." . $ip3id . "." . $ip4id; } //写日志 public static function log($content, $file) { $content .= "\r\n"; $fh = fopen($file, 'ab'); //打开,追加模式 fwrite($fh, $content); fclose($fh); } //减法 public static function calcSub($a, $b) { return ($a * 1000 - $b * 1000) / 1000; } //加法 public static function calcAdd($a, $b) { return ($a * 1000 + $b * 1000) / 1000; } public static function ride($a, $b) { } /** * 生成商家提现需要使用的订单号 */ public static function generateMerchantCashOrderNo($sjId) { return "C" . date('ymdHis') . $sjId . mt_rand(10000, 99999); } //生成用户需要使用的订单号 ssh 2019.4.20 public static function generateOrderNo($sjId, $userId) { $userId = empty($userId) ? rand(12013120, 12536120) : $userId; if (strlen($userId) < 8) { exit('用户ID少于8位数'); } $no = date('ymdHis') . $sjId . $userId . mt_rand(10000, 99999); if (strlen($no) > 32) { exit('订单位数大于32位'); } return $no; } //微信32位的场景ID ssh 2019.9.4 public static function generateSceneId($sjId) { $no = 'S' . date('YmdHis') . $sjId . mt_rand(100000, 999999); if (strlen($no) > 32) { $no = substr($no, 0, 32); } return $no; } //将加密窜转成可以在http上传输的字符 public static function urlSafeB64Encode($string) { $data = base64_encode($string); $data = str_replace(array('+', '/', '='), array('-', '_', ''), $data); return $data; } //将url上传输的字符解密 public static function urlSafeBase64Decode($string) { $data = str_replace(array('-', '_'), array('+', '/'), $string); $mod4 = strlen($data) % 4; if ($mod4) { $data .= substr('====', $mod4); } return base64_decode($data); } //中文二边保留,中间用*号代替 ssh 2019.8.13 public static function replaceXH($name) { //获取字符串长度 $strlen = mb_strlen($name, 'utf-8'); //如果字符创长度小于2,不做任何处理 if ($strlen < 2) { return $name; } else { //mb_substr — 获取字符串的部分 $firstStr = mb_substr($name, 0, 1, 'utf-8'); $lastStr = mb_substr($name, -1, 1, 'utf-8'); //str_repeat — 重复一个字符串 return $strlen == 2 ? $firstStr . str_repeat('*', mb_strlen($name, 'utf-8') - 1) : $firstStr . str_repeat("*", $strlen - 2) . $lastStr; } } //生成唯一的文件名称 ssh 2020.1.7 public static function uniqueFileName() { //参考 https://www.cnblogs.com/yjf512/p/9057229.html //https://www.cnblogs.com/roluce/p/6026081.html return md5(uniqid(mt_rand(), true)); } //生成短的随机名称,基于当前时间微秒数 ssh 2020.4.13 public static function shortUniqueId($id) { //示例:05e946fc1008bc return uniqid($id); } //参数格式化,错误提示查看友好 ssh 2021.01.04 public static function paramsFriend($params) { $str = "["; if (!empty($params) && is_array($params)) { foreach ($params as $name => $item) { $item = is_array($item) ? json_encode($item) : $item; $str .= "\n{$name}=>{$item}"; } } $str .= "\n]"; return $str; } }