Util.php 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  1. <?php
  2. namespace App;
  3. use Exception;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Support\Facades\Redis;
  6. use Illuminate\Support\Facades\Validator;
  7. class Util {
  8. /**
  9. * 根据南美国家(两位字母缩写)验证电话号码
  10. *
  11. * 以下规则示例(号码为不含国际区号和本地区号的订户号码):
  12. *
  13. * - AR (阿根廷):固定电话 7~8 位;移动电话 10 位
  14. * - BO (玻利维亚):固定电话 7 位;移动电话 8 位
  15. * - BR (巴西):固定电话 8 位(首位 2~8);移动电话 9 位(以 9 开头)
  16. * - CL (智利):固定电话 8 位;移动电话 9 位(以 9 开头)
  17. * - CO (哥伦比亚):固定电话 7 位(首位非 0);移动电话 10 位(以 3 开头)
  18. * - EC (厄瓜多尔):固定电话 7 位;移动电话 9 位(以 9 开头)
  19. * - GY (圭亚那):7 位数字
  20. * - PY (巴拉圭):固定电话 7 位;移动电话 9 位(以 9 开头)
  21. * - PE (秘鲁):固定电话 7 位;移动电话 9 位(以 9 开头)
  22. * - SR (苏里南):7 位数字
  23. * - UY (乌拉圭):固定电话 7 位;移动电话 8 位
  24. * - VE (委内瑞拉):固定电话 7 位;移动电话 10 位(以 4 开头)
  25. *
  26. * @param string $country 两位国家代码(如 "AR", "BR", "CL", 等)
  27. * @param string $number 纯数字的电话号码(不含区号及区号分隔符)
  28. * @return bool 返回是否符合该国规则
  29. * @throws Exception 当提供不支持的国家代码时
  30. */
  31. function validateSouthAmericanPhone($country, $number) {
  32. // 定义各国的正则表达式规则
  33. $rules = [
  34. 'AR' => '/^(?:\d{7,8}|\d{10})$/', // 阿根廷:固定电话 7~8 位或移动电话 10 位
  35. 'BO' => '/^(?:\d{7}|\d{8})$/', // 玻利维亚:固定 7 位或移动 8 位
  36. 'BR' => '/^(?:[2-8]\d{7}|9\d{8})$/', // 巴西:固定 8 位(首位 2-8)或移动 9 位(以 9 开头)
  37. 'CL' => '/^(?:\d{8}|9\d{8})$/', // 智利:固定 8 位或移动 9 位(以 9 开头)
  38. 'CO' => '/^(?:[1-9]\d{6}|3\d{9})$/', // 哥伦比亚:固定 7 位(首位非 0)或移动 10 位(以 3 开头)
  39. 'EC' => '/^(?:\d{7}|9\d{8})$/', // 厄瓜多尔:固定 7 位或移动 9 位(以 9 开头)
  40. 'GY' => '/^\d{7}$/', // 圭亚那:7 位数字
  41. 'PY' => '/^(?:\d{7}|9\d{8})$/', // 巴拉圭:固定 7 位或移动 9 位(以 9 开头)
  42. 'PE' => '/^(?:\d{7}|9\d{8})$/', // 秘鲁:固定 7 位或移动 9 位(以 9 开头)
  43. 'SR' => '/^\d{7}$/', // 苏里南:7 位数字
  44. 'UY' => '/^(?:\d{7}|\d{8})$/', // 乌拉圭:固定 7 位或移动 8 位
  45. 'VE' => '/^(?:\d{7}|4\d{9})$/', // 委内瑞拉:固定 7 位或移动 10 位(以 4 开头)
  46. ];
  47. $country = strtoupper($country);
  48. if (!isset($rules[$country])) {
  49. throw new Exception("不支持的国家代码: {$country}");
  50. }
  51. // 清除号码中的空格和连字符
  52. $number = preg_replace('/[\s-]+/', '', $number);
  53. return (bool) preg_match($rules[$country], $number);
  54. }
  55. public static function sanitize($value): string
  56. {
  57. return empty($value) ? "" : preg_replace('/[^\d]/', '', $value);
  58. }
  59. public static function cleanEmptyString($value): string
  60. {
  61. return preg_replace('/[\n\r\t\v\0]/', '', $value);
  62. }
  63. public static function validatePhone($phone) {
  64. // 正则表达式:允许空格、加号、括号、连字符、点号等符号
  65. $pattern = '/^\+?(\d{1,3})?[-.\s()]?\(?\d{1,4}\)?[-.\s()]?\d{1,4}[-.\s()]?\d{1,9}$/';
  66. return preg_match($pattern, $phone) === 1;
  67. }
  68. public static function validateEmail( $EmailAddress): bool
  69. {
  70. $validator = Validator::make(
  71. ['email' => $EmailAddress],
  72. ['email' => 'required|email']
  73. );
  74. if ($validator->fails()) {
  75. self::WriteLog('emailfail',$validator->fails());
  76. return false;
  77. }
  78. return true;
  79. }
  80. public static function validateCpf( $value): bool
  81. {
  82. $c = self::sanitize($value);
  83. if (mb_strlen($c) != 11 || preg_match("/^{$c[0]}{11}$/", $c)) {
  84. return false;
  85. }
  86. for (
  87. $s = 10, $n = 0, $i = 0; $s >= 2; $n += $c[$i++] * $s--
  88. ) {
  89. }
  90. if ($c[9] != ((($n %= 11) < 2) ? 0 : 11 - $n)) {
  91. return false;
  92. }
  93. for (
  94. $s = 11, $n = 0, $i = 0; $s >= 2; $n += $c[$i++] * $s--
  95. ) {
  96. }
  97. if ($c[10] != ((($n %= 11) < 2) ? 0 : 11 - $n)) {
  98. return false;
  99. }
  100. return true;
  101. }
  102. public static $KIND_ID_DZPK= 917; //德州扑克public static public static $
  103. public static $KIND_ID_TEXAS= 918; //新德州扑克public static public static $
  104. public static $KIND_ID_BCBM=2009; //奔驰宝马public static public static $
  105. public static $KIND_ID_BRTP= 2010; //百人TPpublic static public static $
  106. public static $KIND_ID_BRAB= 2012; //百人ABpublic static public static $
  107. public static $KIND_ID_BRDZ= 2013; //百人德州public static public static $
  108. public static $KIND_ID_BRBYZB=2014; //龙虎斗public static public static $
  109. public static $KIND_ID_LHD=6021; //龙虎斗public static public static $
  110. public static $KIND_ID_FAKERABBIT= 3010; //罗马 拉霸public static public static $
  111. public static $KIND_ID_LBROMAN= 3010; //罗马 拉霸public static public static $
  112. public static $KIND_ID_LBFRUIT= 3011; //水果 拉霸public static public static $
  113. public static $KIND_ID_FRUITSLOTS= 3013; //水果机BBBpublic static public static $
  114. public static $KIND_ID_FRUIT9X= 3014; //9线水果 拉霸public static public static $
  115. public static $KIND_ID_SGYYL= 3015; //水果摇摇乐public static public static $
  116. public static $KIND_ID_FOOTBALL= 3016; //足球拉霸public static public static $
  117. public static $KIND_ID_OLYMPUS= 3017; //消除拉霸public static public static $
  118. public static $KIND_ID_TREASURE= 3018; //消除拉霸public static public static $
  119. public static $KIND_ID_RAIO= 3019; //闪电public static public static $
  120. public static $KIND_ID_HALLOWEEN= 3020; //万圣节public static public static $
  121. public static $KIND_ID_HIVE= 3021; //蜂巢public static public static $
  122. public static $KIND_ID_GRANDWHEEL= 3022; //巨轮public static public static $
  123. public static $KIND_ID_ATHENA= 3067; //雅典娜
  124. public static $KIND_ID_CACHETA= 4000; //cachetapublic static public static $
  125. public static $KIND_ID_TRUCO= 4010; //trucopublic static public static $
  126. public static $KIND_ID_CRASH= 4020; //爆点public static public static $
  127. public static $KIND_ID_MINES= 4021; //扫雷public static public static $
  128. public static $KIND_ID_AVIATOR= 4028; //扫雷public static public static $
  129. public static $KIND_ID_AVIATOR2= 4029; //扫雷public static public static $
  130. public static $KIND_ID_JOKER5x1= 5002; //MasterJokerpublic static public static $
  131. public static $KIND_ID_TIGER= 5006; //MasterJokerpublic static public static $
  132. public static $KIND_ID_JOKER3x3= 8001; //SuperJokerpublic static public static $
  133. public static function getClientVer(){
  134. $cv=7;
  135. if(isset($_REQUEST['cv'])){
  136. $cvstr=explode('.',$_REQUEST['cv']);
  137. $cv=(int)array_pop($cvstr);
  138. }
  139. return $cv;
  140. }
  141. public static function getPackConfigs(){
  142. $ios1='https://apps.apple.com/br/app/id6448916752?l=pt-br';
  143. $ios2='https://apps.apple.com/br/app/id6449389054?l=pt-br';
  144. $configs=[
  145. // ['bundleid'=>"com.ouro777.online",'channel'=>100,'ios'=>$ios1,'name'=>'slotsouro_olmp','online'=>false,'sms'=>'OURO'],
  146. ];
  147. if(!Redis::exists('allpacks')) {
  148. $allpacks = DB::table('QPPlatformDB.dbo.ChannelPackageName')->select('PackageName', 'Channel', 'StoreName','Remarks')->get()->toArray();
  149. foreach ($allpacks as $pack){
  150. $configs[]=[
  151. 'bundleid'=>$pack->PackageName,
  152. 'channel'=>$pack->Channel,
  153. 'ios'=>$ios1,
  154. 'name'=>$pack->Remarks,
  155. 'online'=>false,
  156. 'sms'=>$pack->StoreName,
  157. ];
  158. }
  159. Redis::setex('allpacks',600,json_encode($configs));
  160. }else{
  161. $configs=json_decode(Redis::get('allpacks'),true);
  162. }
  163. return $configs;
  164. }
  165. /**
  166. * 获取客户端真实 IP 地址
  167. *
  168. * @return string
  169. */
  170. public static function getClientIp(): string
  171. {
  172. $ip = '';
  173. // 1. Cloudflare 等 CDN 转发的原始 IP
  174. if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
  175. $ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
  176. } // 2. 代理服务器传递的真实 IP(可能有多个,用逗号分隔)
  177. elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  178. $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  179. $ip = trim($ips[0]); // 取第一个非空 IP
  180. } // 3. 部分代理使用的头
  181. elseif (!empty($_SERVER['HTTP_X_REAL_IP'])) {
  182. $ip = $_SERVER['HTTP_X_REAL_IP'];
  183. } // 4. 最后回退到远程地址
  184. elseif (!empty($_SERVER['REMOTE_ADDR'])) {
  185. $ip = $_SERVER['REMOTE_ADDR'];
  186. }
  187. // 校验合法性
  188. if (!filter_var($ip, FILTER_VALIDATE_IP)) {
  189. $ip = '0.0.0.0';
  190. }
  191. return $ip;
  192. }
  193. public static function getPackageByURL($ihaveparam=null){
  194. $configs=self::getPackConfigs();
  195. $packInfos=[];
  196. foreach ($configs as $pack){
  197. $packInfos[$pack['bundleid']]=$pack;
  198. $packInfos[$pack['channel']]=$pack;
  199. }
  200. //直接返回
  201. if(isset($ihaveparam)&&isset($packInfos[$ihaveparam]))return $packInfos[$ihaveparam];
  202. $packInfo=$packInfos[100];
  203. if(isset($_REQUEST['Channel'])){
  204. $packInfo=$packInfos[$_REQUEST['Channel']];
  205. if(isset($packInfo))return $packInfo;
  206. }
  207. if(isset($_REQUEST['channel'])){
  208. $packInfo=$packInfos[$_REQUEST['channel']];
  209. if(isset($packInfo))return $packInfo;
  210. }
  211. if(isset($_REQUEST['ChannelNumber'])){
  212. $packInfo=$packInfos[$_REQUEST['ChannelNumber']];
  213. if(isset($packInfo))return $packInfo;
  214. }
  215. $packageName=null;
  216. if(isset($_REQUEST['PackageName']))$packageName=$_REQUEST['PackageName'];
  217. if(!isset($packageName)&&isset($_REQUEST['bundleid']))$packageName=$_REQUEST['bundleid'];
  218. if(isset($packageName)){
  219. if(isset($packInfos[$packageName])){
  220. $packInfo=$packInfos[$packageName];
  221. }
  222. }
  223. return $packInfo;
  224. }
  225. public static function arraySort( $arr, $key, $sort = SORT_ASC ) {
  226. $newArr = array();
  227. foreach ( $arr as $k => $v ) {
  228. $v=(array)$v;
  229. $newArr[$k] = $v[$key];
  230. }
  231. array_multisort( $newArr, $sort, $arr );
  232. return $arr;
  233. }
  234. public static function removePunctuationAndNumbers($string) {
  235. // 使用正则表达式替换所有标点符号和数字
  236. $result = preg_replace('/[[:punct:]\d]/', '', $string);
  237. return $result;
  238. }
  239. public static function removePunctuation($string) {
  240. // 使用正则表达式替换所有标点符号和数字
  241. $result = preg_replace('/[[:punct:]]/', '', $string);
  242. return $result;
  243. }
  244. /**
  245. * 过滤上传特殊表情符号的
  246. * @param $str
  247. * @return mixed
  248. */
  249. public static function filter_emoji($str)
  250. {
  251. preg_match_all('/[\x{4e00}-\x{9fff}\d\w\s[:punct:]]+/u',$str,$result);
  252. return join('',$result[0]);
  253. }
  254. /**
  255. * 过滤掉字符串中的表情字符
  256. *
  257. * @param string $text 输入字符串
  258. * @return string 过滤后的字符串
  259. */
  260. public static function filterEmoji($text)
  261. {
  262. // 定义匹配表情字符的正则表达式模式
  263. $emojiPattern = '/[\x{1F600}-\x{1F64F}|' . // 表情符号
  264. '\x{1F300}-\x{1F5FF}|' . // 符号&图标
  265. '\x{1F680}-\x{1F6FF}|' . // 运输&地图符号
  266. '\x{1F700}-\x{1F77F}|' . // 额外的符号
  267. '\x{1F780}-\x{1F7FF}|' . // 额外的符号
  268. '\x{1F800}-\x{1F8FF}|' . // 额外的符号
  269. '\x{1F900}-\x{1F9FF}|' . // 额外的符号
  270. '\x{1FA00}-\x{1FA6F}|' . // 额外的符号
  271. '\x{1FA70}-\x{1FAFF}|' . // 额外的符号
  272. '\x{2600}-\x{26FF}|' . // 杂项符号
  273. '\x{2700}-\x{27BF}|' . // 丁头
  274. '\x{2B50}|' . // 星号
  275. '\x{1F004}|' . // 麻将牌
  276. '\x{1F0CF}|' . // 扑克牌
  277. '\x{1F18E}|' . // 白色圈圈
  278. '\x{1F191}-\x{1F251}|' . // 按键符号
  279. '\x{2B06}-\x{2B07}|' . // 箭头
  280. '\x{2934}-\x{2935}|' . // 箭头
  281. '\x{2B05}-\x{2B07}|' . // 箭头
  282. '\x{3297}|' . // 杂项符号
  283. '\x{3299}]|\x{3030}|\x{00A9}|\x{00AE}|\x{2122}/u';
  284. // 使用正则表达式替换匹配到的表情字符为空字符串
  285. return preg_replace($emojiPattern, '', $text);
  286. }
  287. public static function filterSpecialChar($str)
  288. {
  289. // 要替换的数学字符
  290. $math_chars = [
  291. '𝐀', '𝐁', '𝐂', '𝐃', '𝐄', '𝐅', '𝐆', '𝐇', '𝐈', '𝐉', '𝐊', '𝐋', '𝐌',
  292. '𝐍', '𝐎', '𝐏', '𝐐', '𝐑', '𝐒', '𝐓', '𝐔', '𝐕', '𝐖', '𝐗', '𝐘', '𝐙',
  293. '𝐚', '𝐛', '𝐜', '𝐝', '𝐞', '𝐟', '𝐠', '𝐡', '𝐢', '𝐣', '𝐤', '𝐥', '𝐦',
  294. '𝐧', '𝐨', '𝐩', '𝐪', '𝐫', '𝐬', '𝐭', '𝐮', '𝐯', '𝐰', '𝐱', '𝐲', '𝐳',
  295. '𝓐', '𝓑', '𝓒', '𝓓', '𝓔', '𝓕', '𝓖', '𝓗', '𝓘', '𝓙', '𝓚', '𝓛', '𝓜',
  296. '𝓝', '𝓞', '𝓟', '𝓠', '𝓡', '𝓢', '𝓣', '𝓤', '𝓥', '𝓦', '𝓧', '𝓨', '𝓩',
  297. '𝓪', '𝓫', '𝓬', '𝓭', '𝓮', '𝓯', '𝓰', '𝓱', '𝓲', '𝓳', '𝓴', '𝓵', '𝓶',
  298. '𝓷', '𝓸', '𝓹', '𝓺', '𝓻', '𝓼', '𝓽', '𝓾', '𝓿', '𝔀', '𝔁', '𝔂', '𝔃',
  299. '𝔄', '𝔅', '', '𝔇', '𝔈', '𝔉', '𝔊', '', '', '𝔍', '𝔎', '𝔏', '𝔐', '𝔑', '𝔒', '𝔓',
  300. '𝔔', '', '𝔖', '𝔗', '𝔘', '𝔙', '𝔚', '𝔛', '𝔜', '',
  301. '𝔞', '𝔟', '𝔠', '𝔡', '𝔢', '𝔣', '𝔤', '𝔥', '𝔦', '𝔧', '𝔨', '𝔩', '𝔪',
  302. '𝔫', '𝔬', '𝔭', '𝔮', '𝔯', '𝔰', '𝔱', '𝔲', '𝔳', '𝔴', '𝔵', '𝔶', '𝔷',
  303. '𝕬', '𝕭', '𝕮', '𝕯', '𝕰', '𝕱', '𝕲', '𝕳', '𝕴', '𝕵', '𝕶', '𝕷', '𝕸',
  304. '𝕹', '𝕺', '𝕻', '𝕼', '𝕽', '𝕾', '𝕿', '𝖀', '𝖁', '𝖂', '𝖃', '𝖄', '𝖅',
  305. '𝖆', '𝖇', '𝖈', '𝖉', '𝖊', '𝖋', '𝖌', '𝖍', '𝖎', '𝖏', '𝖐', '𝖑', '𝖒',
  306. '𝖓', '𝖔', '𝖕', '𝖖', '𝖗', '𝖘', '𝖙', '𝖚', '𝖛', '𝖜', '𝖝', '𝖞', '𝖟',
  307. '𝘈', '𝘉', '𝘊', '𝘋', '𝘌', '𝘍', '𝘎', '𝘏', '𝘐', '𝘑', '𝘒', '𝘓', '𝘔',
  308. '𝘕', '𝘖', '𝘗', '𝘘', '𝘙', '𝘚', '𝘛', '𝘜', '𝘝', '𝘞', '𝘟', '𝘠', '𝘡',
  309. '𝘢', '𝘣', '𝘤', '𝘥', '𝘦', '𝘧', '𝘨', '𝘩', '𝘪', '𝘫', '𝘬', '𝘭', '𝘮',
  310. '𝘯', '𝘰', '𝘱', '𝘲', '𝘳', '𝘴', '𝘵', '𝘶', '𝘷', '𝘸', '𝘹', '𝘺', '𝘻',
  311. '𝙰', '𝙱', '𝙲', '𝙳', '𝙴', '𝙵', '𝙶', '𝙷', '𝙸', '𝙹', '𝙺', '𝙻', '𝙼',
  312. '𝙽', '𝙾', '𝙿', '𝚀', '𝚁', '𝚂', '𝚃', '𝚄', '𝚅', '𝚆', '𝚇', '𝚈', '𝚉',
  313. '𝚊', '𝚋', '𝚌', '𝚍', '𝚎', '𝚏', '𝚐', '𝚑', '𝚒', '𝚓', '𝚔', '𝚕', '𝚖',
  314. '𝚗', '𝚘', '𝚙', '𝚚', '𝚛', '𝚜', '𝚝', '𝚞', '𝚟', '𝚠', '𝚡', '𝚢', '𝚣'
  315. ];
  316. // 希望替换成的普通拉丁字符
  317. $latin_chars = array_merge(
  318. range('A', 'Z'), range('a', 'z'),
  319. range('A', 'Z'), range('a', 'z'),
  320. range('A', 'Z'), range('a', 'z'),
  321. range('A', 'Z'), range('a', 'z'),
  322. range('A', 'Z'), range('a', 'z'),
  323. range('A', 'Z'), range('a', 'z'),
  324. range('A', 'Z'), range('a', 'z'),
  325. range('A', 'Z'), range('a', 'z'),
  326. range('A', 'Z'), range('a', 'z'),
  327. range('A', 'Z'), range('a', 'z'),
  328. range('A', 'Z'), range('a', 'z')
  329. );
  330. return str_replace($math_chars, $latin_chars, $str);
  331. }
  332. public static function filterNickName( $nickname ) {
  333. $nickname = urldecode( urldecode( $nickname ) );
  334. $nickname = str_replace( "\\'s", '', $nickname );
  335. $nickname = str_replace( "\\'", '', $nickname );
  336. $nickname = str_replace( '\"s', '', $nickname );
  337. $nickname = str_replace( '\"', '', $nickname );
  338. $nickname = str_replace( '\\n', '', $nickname );
  339. $nickname = str_replace( '"', '', $nickname );
  340. $nickname = str_replace( "'", '', $nickname );
  341. $nickname = str_replace( "|", '', $nickname );
  342. $nickname = str_replace( '|', '', $nickname );
  343. $nickname = Util::filterSpecialChar( $nickname );
  344. $nickname = Util::killBadChar( $nickname );
  345. $nickname = Util::filterEmoji( $nickname );
  346. return trim( $nickname );
  347. }
  348. public static function getMobile() {
  349. $ua = @$_SERVER['HTTP_USER_AGENT'];
  350. if ( !$ua )
  351. return false;
  352. $data = array();
  353. $ua = strtolower( $ua );
  354. $android = strstr( $ua, 'android' );
  355. $data['android'] = $android !== false;
  356. //$wphone = strstr($ua, 'phone');
  357. //$data['wphone'] = $wphone !== false;
  358. $ipad = strstr( $ua, 'ipad' );
  359. $data['ipad'] = $ipad !== false;
  360. $iphone = strstr( $ua, 'iphone' );
  361. $data['iphone'] = $data['ipad'] ? false : $iphone !== false;
  362. Util::SmallLog( 'ua', $ua );
  363. return $data;
  364. }
  365. public static function getDeviceType(): string
  366. {
  367. // 获取 UA(统一转为小写)
  368. $ua = strtolower($_SERVER['HTTP_USER_AGENT'] ?? '');
  369. if (strpos($ua, 'iphone') !== false || strpos($ua, 'ipad') !== false || strpos($ua, 'ipod') !== false) {
  370. return 'ios';
  371. }
  372. // 默认返回 Android(包括 Android 和 其他)
  373. return 'android';
  374. }
  375. public static function jsonp( $data, $callback = 'callback' ) {
  376. @header( 'Content-Type: application/json' );
  377. @header( "Expires:-1" );
  378. @header( "Cache-Control:no-cache" );
  379. @header( "Pragma:no-cache" );
  380. if ( isset( $_REQUEST[$callback] ) ) {
  381. header( "Access-Control-Allow-Origin:*" );
  382. echo $_REQUEST[$callback] . '(' . json_encode( $data, JSON_UNESCAPED_UNICODE ) . ')';
  383. } else echo json_encode( $data, JSON_UNESCAPED_UNICODE );
  384. exit;
  385. }
  386. public static function randOrderID() {
  387. return date( 'YmdHis' ) . rand( 10000, 99999 );
  388. }
  389. public static function isMobile() {
  390. $userAgent = @$_SERVER['HTTP_USER_AGENT'] ?: '';
  391. if ( !$userAgent )
  392. return false;
  393. $result = ( preg_match( '/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino|ipad/i', $userAgent ) || preg_match( '/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i', substr( $userAgent, 0, 4 ) ) );
  394. return $result ? 1 : 0;
  395. }
  396. public static function p3p() {
  397. header( 'P3P: CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"' );
  398. }
  399. public static function fbredirect( $url ) {
  400. echo "<script type=\"text/javascript\">\ntop.location.href = \"$url\";\n</script>";
  401. exit;
  402. }
  403. public static function getNowUrl() {
  404. $nowurl = $_SERVER['REQUEST_URI'] ? $_SERVER['REQUEST_URI'] : ( $_SERVER['PHP_SELF'] ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'] );
  405. $nowurl = ROOTURL . $nowurl;
  406. return $nowurl;
  407. }
  408. public static function killBadChar( $str ) {
  409. preg_match_all( '/[0-9a-zA-Z \x{4e00}-\x{9fff}]+/u', $str, $matches );
  410. $str = join( '', $matches[0] );
  411. return trim( $str );
  412. }
  413. public static function der2pem( $der_data ) {
  414. $pem = chunk_split( $der_data, 64, "\n" );
  415. $pem = "-----BEGIN PUBLIC KEY-----\n" . $pem . "-----END PUBLIC KEY-----\n";
  416. return $pem;
  417. }
  418. public static function appleValidateReceipt( $receipt, $isSandbox = true ) {
  419. $endpoint = $isSandbox ? 'https://sandbox.itunes.apple.com/verifyReceipt' : 'https://buy.itunes.apple.com/verifyReceipt';
  420. $postData = json_encode( array( 'receipt-data' => $receipt ) );
  421. $ch = curl_init( $endpoint );
  422. curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 0 );
  423. curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 );
  424. curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
  425. curl_setopt( $ch, CURLOPT_POST, true );
  426. curl_setopt( $ch, CURLOPT_POSTFIELDS, $postData );
  427. $response = curl_exec( $ch );
  428. $errno = curl_errno( $ch );
  429. $errmsg = curl_error( $ch );
  430. curl_close( $ch );
  431. if ( $errno != 0 )
  432. throw new Exception ( $errmsg, $errno );
  433. $data = json_decode( $response, true );
  434. if ( !is_array( $data ) )
  435. throw new Exception ( 'Invalid response data' );
  436. if ( !isset( $data ['status'] ) || $data['status'] != 0 ) {
  437. if ( !empty( $data['status'] ) && $data['status'] == "21007" && !$isSandbox )
  438. return Util::appleValidateReceipt( $receipt, true );
  439. Util::WriteLog( 'appstore_err', 'appleValidateReceipt error!' . $endpoint );
  440. Util::SmallLog( 'appstore_err', $data );
  441. throw new Exception ( 'Invalid receipt' );
  442. }
  443. return $data ['receipt'];
  444. }
  445. public static function encode36( $num ) {
  446. $str = "";
  447. $typelen = 36;
  448. $k = str_split( "ABCDEFGHIJKLMN123456789OPQRSTUVWXYZ0", 1 );
  449. $num += 10000000;
  450. while ( $num > 0 ) {
  451. $char = $num % $typelen;
  452. $str = $k [$char] . $str;
  453. $num = ( $num - $char ) / $typelen;
  454. }
  455. return $str;
  456. }
  457. public static function decode36( $str ) {
  458. $str = strtoupper( $str );
  459. $typelen = 36;
  460. $k = "ABCDEFGHIJKLMN123456789OPQRSTUVWXYZ0";
  461. $num = 0;
  462. for ( $i = 0; $i < strlen( $str ); ++$i ) {
  463. $num = $num * $typelen + strpos( $k, substr( $str, $i, 1 ) );
  464. }
  465. return $num -= 10000000;
  466. }
  467. public static function validate_email( $email ) {
  468. if ( !preg_match( '/([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)/', $email ) )
  469. unset( $email );
  470. return @$email;
  471. }
  472. public static function objectToArray($object)
  473. {
  474. // 处理stdClass对象
  475. if ($object instanceof \stdClass) {
  476. $object = (array) $object;
  477. }
  478. // 处理数组
  479. if (is_array($object)) {
  480. foreach ($object as $key => $value) {
  481. $object[$key] = self::objectToArray($value);
  482. }
  483. }
  484. return $object;
  485. }
  486. //object to array
  487. public static function getKeyValue( $obj, $key, $delKey = true ) {
  488. $list = array();
  489. foreach ( $obj as $info ) {
  490. $info = get_object_vars( $info );
  491. $id = $info[$key];
  492. if ( $delKey )
  493. unset( $info[$key] );
  494. $list[$id] = $info;
  495. }
  496. return $list;
  497. }
  498. //is utf8
  499. public static function is_utf8( $string ) {
  500. return preg_match( '%^(?:
  501. [\x09\x0A\x0D\x20-\x7E] # ASCII
  502. | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
  503. | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
  504. | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
  505. | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
  506. | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
  507. | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
  508. | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
  509. )*$%xs', $string );
  510. }
  511. //安全encode
  512. public static function safeEncoding( $string, $outEncoding = 'UTF-8' ) {
  513. $string = Util::safeEncoding3( $string );
  514. if ( Util::is_utf8( $string ) )
  515. return $string;
  516. $encoding = "UTF-8";
  517. $encoding = mb_detect_encoding( $string, array( 'ASCII', 'GB2312', 'CP936', 'BIG5' ) );
  518. if ( strtoupper( $encoding ) == strtoupper( $outEncoding ) ) {
  519. return $string;
  520. } else {
  521. return mb_convert_encoding( $string, $outEncoding, $encoding );
  522. }
  523. }
  524. //安全encode
  525. public static function safeEncoding3( $string, $outEncoding = 'UTF-8' ) {
  526. $encoding = "UTF-8";
  527. for ( $i = 0; $i < strlen( $string ); $i++ ) {
  528. if ( ord( $string[$i] ) < 128 )
  529. continue;
  530. if ( ( ord( $string[$i] ) & 224 ) == 224 ) {
  531. //第一个字节判断通过
  532. $char = $string[++$i];
  533. if ( ( ord( $char ) & 128 ) == 128 ) {
  534. //第二个字节判断通过
  535. $char = $string[++$i];
  536. if ( ( ord( $char ) & 128 ) == 128 ) {
  537. $encoding = "UTF-8";
  538. break;
  539. }
  540. }
  541. }
  542. if ( ( ord( $string[$i] ) & 192 ) == 192 ) {
  543. //第一个字节判断通过
  544. $char = $string[++$i];
  545. if ( ( ord( $char ) & 128 ) == 128 ) {
  546. // 第二个字节判断通过
  547. $encoding = "GB2312";
  548. break;
  549. }
  550. }
  551. }
  552. if ( strtoupper( $encoding ) == strtoupper( $outEncoding ) )
  553. return $string;
  554. else
  555. return mb_convert_encoding( $string, $outEncoding, $encoding );
  556. return iconv( $encoding, $outEncoding, $string );
  557. }
  558. //取浏览器语言
  559. public static function determineLang() {
  560. $lang = substr( @$_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 5 ); //只取前4位,这样只判断最优先的语言。如果取前5位,可能出现en,zh的情况,影响判断。
  561. if ( preg_match( "/zh/i", $lang ) )
  562. return "zh_CN";
  563. else return 'en_US';
  564. }
  565. //过滤语言
  566. public static function getLocale( $lang ) {
  567. $locale = '';
  568. $shortLangEN = array( 'en', 'US', 'UK', "en_US", 'en_UK', 'en_GB', 'en_us' );
  569. $shortLangTW = array( 'zh', 'TW', 'HK', "zh_TW", 'zh_HK', "jp", 'ja_JP', 'ko_KR', "th", "TH", 'th_TH', 'zh_tw' );
  570. $shortLangCN = array( 'zh_CN', 'CN', 'zh_cn' );
  571. if ( in_array( $lang, $shortLangEN ) ) {
  572. $locale = "en_us";
  573. } else if ( in_array( $lang, $shortLangTW ) ) {
  574. $locale = "zh_tw";
  575. } else if ( in_array( $lang, $shortLangCN ) ) {
  576. $locale = "zh_cn";
  577. } else {
  578. $locale = "en_us";
  579. }
  580. return $locale;
  581. }
  582. //urlencode
  583. public static function encode_url_substr_UTF8( $str, $lenlimit ) {
  584. $mblen = mb_strlen( $str, "UTF8" );
  585. $realencodelen = 0;
  586. $outstr = '';
  587. for ( $i = 0; $i < $mblen; $i++ ) {
  588. $char = mb_substr( $str, $i, 1, 'UTF8' );
  589. if ( strlen( $char ) > 1 ) {
  590. $addlen = strlen( $char ) * 3;
  591. } else {
  592. $addlen = 1;
  593. }
  594. if ( $realencodelen + $addlen < $lenlimit ) {
  595. $outstr .= $char;
  596. $realencodelen += $addlen;
  597. }
  598. }
  599. return $outstr;
  600. }
  601. //转意数据
  602. public static function saddslashes( $string ) {
  603. if ( is_array( $string ) ) {
  604. foreach ( $string as $key => $val ) {
  605. $string[$key] = Util::saddslashes( $val );
  606. }
  607. } else {
  608. $string = addslashes( $string );
  609. }
  610. return $string;
  611. }
  612. //日志
  613. public static function WriteLog( $key, $data ) {
  614. $ymd = date( "Ymd" );
  615. $date = date( 'Y-m-d H:i:s' );
  616. $file = storage_path( 'logs' ) . "/{$ymd}_{$key}.log";
  617. $ip = IpLocation::getRealIp();
  618. $agent=@$_SERVER['HTTP_USER_AGENT']??"";
  619. $locale=@$_SERVER['HTTP_ACCEPT_LANGUAGE']??"";
  620. $ref = @$_SERVER['HTTP_REFERER'];
  621. $url = @$_SERVER['REQUEST_URI'];
  622. $host = @$_SERVER['HTTP_HOST'];
  623. if ( !is_string( $data ) )
  624. $data = json_encode( $data, JSON_UNESCAPED_UNICODE );
  625. $uid = isset( $GLOBALS['user_id'] ) ? $GLOBALS['user_id'] : 0;
  626. // $params = array( 'POST' => $_POST );
  627. $params = empty( $_REQUEST ) ? '' : json_encode( $_REQUEST, JSON_UNESCAPED_UNICODE );
  628. $content = "date: {$date}\n";
  629. $content .= "ip: {$ip}({$uid}) agent:".$agent." locale:".$locale."\n";
  630. if ( !empty( $ref ) )
  631. $content .= "referer: {$ref}\n";
  632. if ( !empty( $url ) )
  633. $content .= "request: {$host}{$url}\n";
  634. if ( !empty( $params ) )
  635. $content .= "params: {$params}\n";
  636. if ( !empty( $data ) )
  637. $content .= "content: {$data}\n";
  638. $content .= "\n";
  639. try {
  640. error_log($content, 3, $file);
  641. }catch ( \Exception $e ) {
  642. error_log($e->getMessage(), 3, storage_path( 'logs' ) . "/util_error.log");
  643. error_log($content, 3, storage_path( 'logs' ) . "/util_error.log");
  644. }
  645. }
  646. //写简单日志
  647. public static function SmallLog( $key, $content ) {
  648. $ymd = date( "Ymd" );
  649. $date = date( 'Y-m-d H:i:s' );
  650. $file = storage_path( 'logs' ) . "/{$ymd}_{$key}.log";
  651. $ip = IpLocation::getIP();
  652. if ( !is_string( $content ) )
  653. $content = json_encode( $content, JSON_UNESCAPED_UNICODE );
  654. $uid = isset( $GLOBALS['user_id'] ) ? $GLOBALS['user_id'] : 0;
  655. $content = "date:{$date}\tip:{$ip}({$uid})\tcontent:{$content}\n";
  656. error_log( $content, 3, $file );
  657. }
  658. public static function SmallLog2( $key, $content ) {
  659. $ymd = date( "Ymd" );
  660. $date = date( 'Y-m-d H:i:s' );
  661. $file = storage_path( 'logs' ) . "/{$ymd}_{$key}.log";
  662. if ( !is_string( $content ) )
  663. $content = json_encode( $content, JSON_UNESCAPED_UNICODE );
  664. $content = "date:{$date}\t {$content}\n";
  665. error_log( $content, 3, $file );
  666. }
  667. //验证昵称
  668. public static function check_nickname( $username, $isNick = false ) {
  669. $guestexp = '\xA1\xA1|\xAC\xA3|^Guest|^\xD3\xCE\xBF\xCD|\xB9\x43\xAB\xC8';
  670. $len = strlen( $username );
  671. if ( $len > 20 || $len < 1 || preg_match( "/^c:\\con\\con|[%,\|\*\"\<\>\&\`\']|$guestexp/is", $username ) ) {
  672. return FALSE;
  673. } else if ( preg_match( '/^(?!_|\s\')[A-Za-z0-9_\x80-\xff\s\']+$/', $username ) ) {
  674. return TRUE;
  675. }
  676. return FALSE;
  677. }
  678. //验证用户名
  679. public static function check_username( $username ) {
  680. $guestexp = '\xA1\xA1|\xAC\xA3|^Guest|^\xD3\xCE\xBF\xCD|\xB9\x43\xAB\xC8';
  681. $len = strlen( $username );
  682. if ( $len > 20 || $len < 3 || preg_match( "/\s+|^c:\\con\\con|[%,\|\*\"\s\<\>\&]|$guestexp/is", $username ) || !preg_match( "/^[0-9@A-Z_a-z]*$/", $username ) ) {
  683. return FALSE;
  684. } else if ( strstr( ' ', $username ) ) {
  685. return FALSE;
  686. } else {
  687. return TRUE;
  688. }
  689. }
  690. //发送手机验证码
  691. public static function sendSMS($phone, $text) {
  692. $ch = curl_init();
  693. $post_data = array(
  694. "account" => SMSAccount,
  695. "password" => SMSPassword,
  696. "destmobile" => $phone,
  697. "msgText" => $text,
  698. "sendDateTime" => ""
  699. );
  700. curl_setopt($ch, CURLOPT_HEADER, false);
  701. curl_setopt($ch, CURLOPT_POST, true);
  702. curl_setopt($ch,CURLOPT_BINARYTRANSFER,true);
  703. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  704. $post_data = http_build_query($post_data);
  705. curl_setopt($ch, CURLOPT_POSTFIELDS,$post_data);
  706. curl_setopt($ch, CURLOPT_URL, 'http://www.jianzhou.sh.cn/JianzhouSMSWSServer/http/sendBatchMessage');
  707. $reponse = curl_exec($ch);
  708. curl_close($ch);
  709. return $reponse;
  710. }
  711. public static function validate_mobile($mobile) {
  712. if (!is_bool(strpos($mobile, '+'))) return false;
  713. if (!is_bool(strpos($mobile, ' '))) return false;
  714. if (!is_bool(strpos($mobile, '('))) return false;
  715. return is_numeric($mobile) && strlen($mobile) == 11;
  716. }
  717. //验证email
  718. public static function check_emailformat( $email ) {
  719. return strlen( $email ) > 6 && preg_match( '/^[\w\-\.]+@[\w\-\.]+(\.\w+)+$/', $email );
  720. }
  721. //curl
  722. public static function curl( $url, $timeout = 0 ) {
  723. if ( !strstr( $url, 'http' ) ) {
  724. return '';
  725. }
  726. $ch = curl_init();
  727. curl_setopt( $ch, CURLOPT_URL, $url );
  728. curl_setopt( $ch, CURLOPT_FAILONERROR, false );
  729. curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
  730. if ( $timeout > 0 ) {
  731. curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout );
  732. curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
  733. }
  734. if ( strlen( $url ) > 5 && strtolower( substr( $url, 0, 5 ) ) == "https" ) {
  735. curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
  736. curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
  737. }
  738. $reponse = curl_exec( $ch );
  739. if ( curl_errno( $ch ) ) {
  740. throw new Exception( curl_error( $ch ), 0 );
  741. } else {
  742. $httpStatusCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
  743. if ( 200 !== $httpStatusCode ) {
  744. throw new Exception( $reponse, $httpStatusCode );
  745. }
  746. }
  747. curl_close( $ch );
  748. return $reponse;
  749. }
  750. //生成密码
  751. public static function password( $user_password, $user_salt ) {
  752. return md5( md5( $user_password ) . strval( $user_salt ) );
  753. }
  754. //生成sessionKey
  755. public static function makePkey( $uid, $timestamp, $locale, $ismobile = 0, $gss = 0, $appID = 1, $bundleid = '' ) {
  756. $pkey = array( 'u' => $uid, 't' => $timestamp, 'l' => $locale, 'm' => $ismobile, 'g' => $gss, 'a' => $appID, 'b' => $bundleid );
  757. $pkey = Util::up_encode( $pkey );
  758. return $pkey;
  759. }
  760. //加密
  761. public static function up_encode( $str ) {
  762. if ( is_array( $str ) || is_object( $str ) )
  763. $str = json_encode( $str );
  764. $cr = new Crypt3Des ( Crypt3DesKey, Crypt3DesIV );
  765. $str = $cr->encrypt( $str );
  766. $str = str_replace( '+', '-', $str );
  767. $str = str_replace( '/', '.', $str );
  768. $str = str_replace( '=', '!', $str );
  769. return $str;
  770. }
  771. //解密
  772. public static function up_decode( $str ) {
  773. if ( !$str )
  774. return $str;
  775. $str = urldecode( $str );
  776. $str = trim( $str );
  777. $cr = new Crypt3Des ( Crypt3DesKey, Crypt3DesIV );
  778. $str = str_replace( '-', '+', $str );
  779. $str = str_replace( '.', '/', $str );
  780. $str = str_replace( '!', '=', $str );
  781. $str = $cr->decrypt( $str );
  782. $couldbeA = json_decode( $str, true );
  783. if ( is_array( $couldbeA ) )
  784. return $couldbeA;
  785. return false;
  786. }
  787. public static function getCDNFile( $file ) {
  788. if ( Util::startsWith( $file, 'client/' ) )
  789. return CDNSERVER . $file;
  790. if ( Util::startsWith( $file, 'upload/' ) )
  791. return CDNRESOURCE . $file;
  792. if ( Util::startsWith( $file, 'images/' ) )
  793. return CDNRESOURCE . $file;
  794. return CDNSERVER . $file;
  795. }
  796. public static function getTaobaoData( $ip ) {
  797. try {
  798. $data = self::curl( "http://ip.taobao.com/service/getIpInfo.php?ip=$ip", 2 );
  799. } catch ( Exception $e ) {
  800. $data = null;
  801. }
  802. if ( !empty( $data ) && Util::startsWith( $data, '{' ) ) {
  803. $data = json_decode( $data, true );
  804. if ( $data['code'] == 0 ) {
  805. $city = array( 'country' => @$data['data']['country'], 'region' => @$data['data']['region'], 'city' => @$data['data']['city'], 'county' => @$data['data']['county'], 'source' => 'taobao' );
  806. return $city;
  807. }
  808. }
  809. return false;
  810. }
  811. public static function getTaobaoData2( $ip ) {
  812. try {
  813. $data = self::curl( "http://ip.taobao.com/service/getIpInfo2.php?ip=$ip", 2 );
  814. } catch ( Exception $e ) {
  815. $data = null;
  816. }
  817. if ( !empty( $data ) && Util::startsWith( $data, '{' ) ) {
  818. $data = json_decode( $data, true );
  819. if ( $data['code'] == 0 ) {
  820. $city = array( 'country' => @$data['data']['country'], 'region' => @$data['data']['region'], 'city' => @$data['data']['city'], 'county' => @$data['data']['county'], 'source' => 'taobao2' );
  821. return $city;
  822. }
  823. }
  824. return false;
  825. }
  826. public static function getBaiduData( $ip ) {
  827. try {
  828. $data = self::curl( "http://api.map.baidu.com/location/ip?ak=F454f8a5efe5e577997931cc01de3974&ip=$ip", 2 );
  829. } catch ( Exception $e ) {
  830. $data = null;
  831. }
  832. if ( !empty( $data ) && Util::startsWith( $data, '{' ) ) {
  833. $data = json_decode( $data, true );
  834. if ( !empty( $data['content']['address_detail'] ) ) {
  835. $data = $data['content']['address_detail'];
  836. $city = array( 'country' => '', 'region' => @$data['province'], 'city' => @$data['city'], 'county' => @$data['district'], 'source' => 'baidu' );
  837. return $city;
  838. }
  839. }
  840. return false;
  841. }
  842. public static function getSinaData( $ip ) {
  843. try {
  844. $data = self::curl( "http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip=$ip", 2 );
  845. } catch ( Exception $e ) {
  846. $data = null;
  847. }
  848. if ( !empty( $data ) ) {
  849. $data = str_replace( 'var remote_ip_info = {', '{', $data );
  850. $data = str_replace( '};', '}', $data );
  851. }
  852. if ( !empty( $data ) && Util::startsWith( $data, '{' ) ) {
  853. $data = json_decode( $data, true );
  854. if ( $data && $data['ret'] == 1 ) {
  855. $city = array( 'country' => @$data['country'], 'region' => @$data['province'], 'city' => @$data['city'], 'county' => @$data['district'], 'source' => 'sina' );
  856. return $city;
  857. }
  858. }
  859. return false;
  860. }
  861. public static function getIpipData( $ip ) {
  862. try {
  863. $data = self::curl( "http://freeapi.ipip.net/$ip", 2 );
  864. } catch ( Exception $e ) {
  865. $data = null;
  866. }
  867. if ( !empty( $data ) && Util::startsWith( $data, '[' ) ) {
  868. $data = json_decode( $data, true );
  869. if ( $data ) {
  870. $city = array( 'country' => @$data[0], 'region' => @$data[1], 'city' => @$data[2], 'county' => @$data[3], 'source' => 'ipip' );
  871. return $city;
  872. }
  873. }
  874. return false;
  875. }
  876. public static function randIp2Address( $ip ) {
  877. $rand = rand( 1, 3 );
  878. switch ( $rand ) {
  879. case 1:
  880. return self::getTaobaoData( $ip );
  881. case 2:
  882. return self::getTaobaoData2( $ip );
  883. case 3:
  884. return self::getBaiduData( $ip );
  885. }
  886. return self::getTaobaoData( $ip );
  887. }
  888. public static function getIp2Address( $ip ) {
  889. $city = self::randIp2Address( $ip );
  890. if ( empty( $city ) )
  891. $city = self::getBaiduData( $ip );
  892. if ( empty( $city ) )
  893. $city = self::getTaobaoData( $ip );
  894. if ( empty( $city ) )
  895. $city = self::getTaobaoData2( $ip );
  896. if ( empty( $city ) )
  897. $city = self::getSinaData( $ip );
  898. if ( empty( $city ) )
  899. $city = self::getIpipData( $ip );
  900. return $city;
  901. }
  902. public static function getIp2AddressFullName( $ip ) {
  903. $city = Util::getIp2Address( $ip );
  904. if ( empty( $city['region'] ) )
  905. return '';
  906. $data = array();
  907. $data['province'] = $city['region'];
  908. $data['city'] = $city['city'];
  909. $data['area'] = $city['county'];
  910. if ( !empty( $city['region'] ) && !empty( $city['city'] ) && !empty( $city['county'] ) && !empty( $city['country'] ) )
  911. $data['city'] = $city['country'];
  912. if ( !empty( $city['city'] ) && !empty( $city['county'] ) && !empty( $city['region'] ) )
  913. $data['city'] = $city['region'];
  914. if ( $data['province'] == $data['city'] && $data['city'] == $data['area'] )
  915. return trim( $data['province'] );
  916. if ( $data['province'] == $data['city'] )
  917. return trim( $data['city'] . ' ' . $data['area'] );
  918. return trim( $data['province'] . ' ' . $data['city'] . ' ' . $data['area'] );
  919. }
  920. public static function imageResize( $src_file, $dst_file, $new_width = 798, $new_height = 450, $opType = 1, $quality = 90 ) {
  921. ini_set( 'memory_limit', '1024M' );
  922. // 图像类型
  923. // $type = exif_imagetype( $src_file );
  924. list( $objWidth, $objHeight, $type ) = getimagesize( $src_file );
  925. $support_type = array( IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_GIF, IMAGETYPE_BMP );
  926. if ( !in_array( $type, $support_type, true ) ) {
  927. return false;
  928. }
  929. //Load image
  930. switch ( $type ) {
  931. case IMAGETYPE_JPEG :
  932. $src_img = imagecreatefromjpeg( $src_file );
  933. break;
  934. case IMAGETYPE_PNG :
  935. $src_img = imagecreatefrompng( $src_file );
  936. break;
  937. case IMAGETYPE_GIF :
  938. $src_img = imagecreatefromgif( $src_file );
  939. break;
  940. default:
  941. $src_img = imagecreatefromjpeg( $src_file );
  942. break;
  943. }
  944. $w = imagesx( $src_img );
  945. $h = imagesy( $src_img );
  946. if ( $new_width / $w > $new_height / $h ) {
  947. $opType = 1;
  948. } else {
  949. $opType = 2;
  950. }
  951. //固定高度,宽度自适应
  952. if ( $opType == 1 ) {
  953. $new_width = $new_height * $w / $h;
  954. }
  955. if ( $opType == 2 ) {
  956. //固定宽度,高度自适应
  957. $new_height = $new_width * $h / $w;
  958. }
  959. //TODO 根据高宽比自适应调节
  960. $ratio_w = 1.0 * $new_width / $w;
  961. $ratio_h = 1.0 * $new_height / $h;
  962. $ratio = 1.0;
  963. // 生成的图像的高宽比原来的都小,或都大 ,原则是 取大比例放大,取大比例缩小(缩小的比例就比较小了)
  964. //原图比较小不处理
  965. if ( $ratio_w > 1 && $ratio_h > 1 ) {
  966. $inter_img = imagecreatetruecolor( $w, $h );
  967. imagecopy( $inter_img, $src_img, 0, 0, 0, 0, $w, $h );
  968. // 生成一个以最大边长度为大小的是目标图像$ratio比例的临时图像
  969. // 定义一个新的图像
  970. $new_img = imagecreatetruecolor( $w, $h );
  971. imagecopyresampled( $new_img, $inter_img, 0, 0, 0, 0, $w, $h, $w, $h );
  972. } elseif ( $ratio_w < 1 && $ratio_h < 1 ) {
  973. if ( $ratio_w < $ratio_h ) {
  974. $ratio = $ratio_h; // 情况一,宽度的比例比高度方向的小,按照高度的比例标准来裁剪或放大
  975. } else {
  976. $ratio = $ratio_w;
  977. }
  978. // 定义一个中间的临时图像,该图像的宽高比 正好满足目标要求
  979. $inter_w = (int)( $new_width / $ratio );
  980. $inter_h = (int)( $new_height / $ratio );
  981. $inter_img = imagecreatetruecolor( $inter_w, $inter_h );
  982. imagecopy( $inter_img, $src_img, 0, 0, 0, 0, $inter_w, $inter_h );
  983. // 生成一个以最大边长度为大小的是目标图像$ratio比例的临时图像
  984. // 定义一个新的图像
  985. $new_img = imagecreatetruecolor( $new_width, $new_height );
  986. imagecopyresampled( $new_img, $inter_img, 0, 0, 0, 0, $new_width, $new_height, $inter_w, $inter_h );
  987. } else {
  988. // 2 目标图像 的一个边大于原图,一个边小于原图 ,先放大平普图像,然后裁剪
  989. $ratio = $ratio_h > $ratio_w ? $ratio_h : $ratio_w; //取比例大的那个值
  990. // 定义一个中间的大图像,该图像的高或宽和目标图像相等,然后对原图放大
  991. $inter_w = (int)( $w * $ratio );
  992. $inter_h = (int)( $h * $ratio );
  993. $inter_img = imagecreatetruecolor( $inter_w, $inter_h );
  994. //将原图缩放比例后裁剪
  995. imagecopyresampled( $inter_img, $src_img, 0, 0, 0, 0, $inter_w, $inter_h, $w, $h );
  996. // 定义一个新的图像
  997. $new_img = imagecreatetruecolor( $new_width, $new_height );
  998. imagecopy( $new_img, $inter_img, 0, 0, 0, 0, $new_width, $new_height );
  999. }
  1000. switch ( $type ) {
  1001. case IMAGETYPE_JPEG :
  1002. imagejpeg( $new_img, $dst_file, $quality ); // 存储图像
  1003. break;
  1004. case IMAGETYPE_PNG :
  1005. imagejpeg( $new_img, $dst_file, $quality );
  1006. break;
  1007. default:
  1008. imagejpeg( $new_img, $dst_file, $quality );
  1009. break;
  1010. }
  1011. return $dst_file;
  1012. }
  1013. public static function chargeTel( $tel, $money = 10, $key, $openid, $orderId ) {
  1014. $sign = md5( $openid . $key . $tel . $money . $orderId );
  1015. $api = "http://op.juhe.cn/ofpay/mobile/onlineorder?key=$key&phoneno=$tel&cardnum=$money&orderid=$orderId&sign=$sign";
  1016. $data = file_get_contents( $api );
  1017. return json_decode( $data, true );
  1018. }
  1019. //POST请求
  1020. public static function curlPost($url, $data = null) {
  1021. $curl = curl_init();
  1022. curl_setopt($curl, CURLOPT_URL, $url);
  1023. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
  1024. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
  1025. if (!empty($data)){
  1026. curl_setopt($curl, CURLOPT_POST, 1);
  1027. curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  1028. }
  1029. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  1030. $output = curl_exec($curl);
  1031. curl_close($curl);
  1032. return $output;
  1033. }
  1034. public static function curlPost2($url, $data, $post = true, $header = array()) {
  1035. $ch = curl_init();
  1036. curl_setopt($ch, CURLOPT_URL, $url);
  1037. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  1038. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  1039. if ($post) {
  1040. if ($header) {
  1041. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  1042. }
  1043. curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  1044. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  1045. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  1046. curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
  1047. }
  1048. curl_setopt($ch, CURLOPT_TIMEOUT,30); //超时
  1049. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  1050. $response = curl_exec($ch);
  1051. curl_close($ch);
  1052. return $response;
  1053. }
  1054. public static function list_to_tree($list, $pk='id',$pid = 'parent_id',$child = '_child',$root=0) {
  1055. $tree = array();
  1056. if(is_array($list)) {
  1057. $refer = array();
  1058. foreach ($list as $key => $data) {
  1059. $refer[$data[$pk]] =& $list[$key];
  1060. }
  1061. foreach ($list as $key => $data) {
  1062. $parentId = $data[$pid];
  1063. if ($root == $parentId) {
  1064. $tree[] =& $list[$key];
  1065. }else{
  1066. if (isset($refer[$parentId])) {
  1067. $parent =& $refer[$parentId];
  1068. $parent[$child][] =& $list[$key];
  1069. }
  1070. }
  1071. }
  1072. }
  1073. return $tree;
  1074. }
  1075. public static function getGameType ($tid) {
  1076. switch($tid) {
  1077. case 1: return '拼罗松轮状('.$tid.')';
  1078. case 2: return '拼罗松通比('.$tid.')';
  1079. case 3: return '拼罗松黑桃A坐庄('.$tid.')';
  1080. case 50: return '斗牛经典抢庄('.$tid.')';
  1081. case 51: return '斗牛经典轮庄('.$tid.')';
  1082. case 52: return '斗牛经典定庄('.$tid.')';
  1083. case 53: return '斗牛经典焖牌('.$tid.')';
  1084. case 54: return '斗牛经典通比('.$tid.')';
  1085. case 55: return '斗牛疯狂抢庄('.$tid.')';
  1086. case 56: return '斗牛疯狂轮庄('.$tid.')';
  1087. case 57: return '斗牛疯狂定庄('.$tid.')';
  1088. case 58: return '斗牛疯狂焖牌('.$tid.')';
  1089. case 59: return '斗牛疯狂通比('.$tid.')';
  1090. case 60: return '斗牛随机庄家('.$tid.')';
  1091. case 70: return '经典拼罗松('.$tid.')';
  1092. case 68: return '扎金花('.$tid.')';
  1093. case 81: return '嵊州十三水轮庄('.$tid.')';
  1094. case 82: return '嵊州十三水通比('.$tid.')';
  1095. case 100: return '清墩('.$tid.')';
  1096. }
  1097. return $tid;
  1098. }
  1099. public static function postXmlCurl( $url, $xml, $cert, $key, $ca ) {
  1100. $ch = curl_init();
  1101. //设置超时
  1102. curl_setopt( $ch, CURLOPT_TIMEOUT, 30 );
  1103. curl_setopt( $ch, CURLOPT_URL, $url );
  1104. curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
  1105. curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );//严格校验
  1106. curl_setopt( $ch, CURLOPT_SSLCERT, $cert );//加入证书
  1107. curl_setopt( $ch, CURLOPT_SSLKEY, $key );//加入证书
  1108. curl_setopt( $ch, CURLOPT_CAINFO, $ca );//加入证书
  1109. //设置header
  1110. curl_setopt( $ch, CURLOPT_HEADER, FALSE );
  1111. //要求结果为字符串且输出到屏幕上
  1112. curl_setopt( $ch, CURLOPT_RETURNTRANSFER, TRUE );
  1113. //post提交方式
  1114. curl_setopt( $ch, CURLOPT_POST, TRUE );
  1115. curl_setopt( $ch, CURLOPT_POSTFIELDS, $xml );
  1116. //运行curl
  1117. $data = curl_exec( $ch );
  1118. //返回结果
  1119. if ( $data ) {
  1120. curl_close( $ch );
  1121. return self::xmlToArr( $data );
  1122. } else {
  1123. $error = curl_error( $ch );
  1124. curl_close( $ch );
  1125. return $error;
  1126. }
  1127. }
  1128. public static function getNonceStr( $length = 16 ) {
  1129. $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
  1130. $str = "";
  1131. for ( $i = 0; $i < $length; $i++ ) {
  1132. $str .= substr( $chars, mt_rand( 0, strlen( $chars ) - 1 ), 1 );
  1133. }
  1134. return $str;
  1135. }
  1136. public static function generateRandomString($length = 8) {
  1137. // 扩展字符集合,包括小写字母、大写字母和数字
  1138. $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  1139. $charactersLength = strlen($characters);
  1140. $randomString = '';
  1141. // 生成随机字符串
  1142. for ($i = 0; $i < $length; $i++) {
  1143. $randomString .= $characters[random_int(0, $charactersLength - 1)];
  1144. }
  1145. return $randomString;
  1146. }
  1147. /**
  1148. * 生成sign
  1149. * @param array $data
  1150. * @param string $key
  1151. * @return string
  1152. */
  1153. public static function getSign( $data, $skey ) {
  1154. ksort( $data );
  1155. $str = '';
  1156. foreach ( $data as $key => $val ) {
  1157. $str .= $str ? '&' . $key . '=' . $val : $key . '=' . $val;
  1158. }
  1159. $str .= '&key=' . $skey;
  1160. $data['sign'] = strtoupper( md5( $str ) );
  1161. return $data;
  1162. }
  1163. /**
  1164. * 输出xml字符
  1165. * @param array $data
  1166. */
  1167. public static function toXml( $data ) {
  1168. $xml = "<xml>";
  1169. foreach ( $data as $key => $val ) {
  1170. if ( is_numeric( $val ) ) {
  1171. $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
  1172. } else {
  1173. $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
  1174. }
  1175. }
  1176. $xml .= "</xml>";
  1177. return $xml;
  1178. }
  1179. public static function getUnixTimestampMillis() {
  1180. // Get the current time in seconds and microseconds
  1181. $microtime = microtime(true);
  1182. // Convert to milliseconds
  1183. $millis = $microtime * 1000;
  1184. // Return as an integer (to remove decimal points)
  1185. return (int)$millis;
  1186. }
  1187. }