CommonServer.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. <?php
  2. namespace App\Servers;
  3. use AlibabaCloud\Client\AlibabaCloud;
  4. use AlibabaCloud\Client\Exception\ClientException;
  5. use AlibabaCloud\Sts\Sts;
  6. use App\Models\Config;
  7. use App\Models\ErrorRecord;
  8. use App\Models\Region;
  9. use Illuminate\Support\Facades\Redis;
  10. use OSS\Core\OssException;
  11. use OSS\Credentials\EnvironmentVariableCredentialsProvider;
  12. use OSS\Http\RequestCore_Exception;
  13. use OSS\OssClient;
  14. /**
  15. * 公共服务方法
  16. */
  17. class CommonServer
  18. {
  19. /**
  20. * 错误信息
  21. * @var string
  22. */
  23. private $errorMsg = '';
  24. static private $server = null;
  25. private function __construct()
  26. {
  27. }
  28. /**
  29. * 创建对象
  30. * @return CommonServer
  31. */
  32. static function creatServer()
  33. {
  34. if (empty(self::$server)) self::$server = new CommonServer();
  35. return self::$server;
  36. }
  37. /**
  38. * 创建文件夹
  39. * @param $dir
  40. * @return bool
  41. */
  42. function creatDir($dir)
  43. {
  44. if ($dir == '') return false;
  45. if (!file_exists(public_path($dir))) {
  46. mkdir(public_path($dir), 0777, true);
  47. chmod(public_path($dir), 0777);
  48. }
  49. return true;
  50. }
  51. /**
  52. * redis 滑动窗口节流阀
  53. * @param $key
  54. * @param $num //允许的请求次数
  55. * @param $secs //时间段(秒)
  56. * @return bool
  57. */
  58. function redisThrottler($key ,$num ,$secs){
  59. try {
  60. //获取当前时间戳
  61. $nowTime=time();
  62. //获取队列长度
  63. $length=Redis::lLen($key);
  64. //如果长度没到限制数量就通过
  65. if($length<$num){
  66. //当前请求的时间入队
  67. Redis::lPush($key,$nowTime);
  68. Redis::expire($key,$secs);
  69. return true;
  70. }
  71. //队列满了,取出最早访问的时间
  72. $startTime= Redis::lIndex($key,$length-1);
  73. //计算当前时间和最早一次请求的时间差,如果在规定的时间范围,则不允许通过
  74. if ($nowTime-$startTime <= $secs) {
  75. return false;
  76. } else {
  77. //如果不在规定的时间范围,证明最早的请求过期,就去掉最早期的再把当前的请求入队
  78. Redis::rPop($key);
  79. Redis::lPush($key,$nowTime);
  80. Redis::expire($key,$secs);
  81. }
  82. return true;
  83. }catch (\Exception $e){
  84. var_dump($e->getMessage());
  85. return true;
  86. }
  87. }
  88. /**
  89. * 指定路由加锁
  90. * @param $lock_key
  91. * @param $lock_value
  92. * @param $routeName
  93. * @return bool
  94. */
  95. function lockSpecifyRoutes($lock_key,$lock_value,$routeName){
  96. $routeArr= [
  97. 'withdraw.withdraw',
  98. ];
  99. if(in_array($routeName,$routeArr)){
  100. $lock = RedisDataServer::creatServer()->lockKey($lock_key,$lock_value,1000);
  101. if(!$lock){//拿不到锁
  102. return false;
  103. }
  104. }
  105. return true;
  106. }
  107. /**
  108. * 获取数据库配置信息
  109. * @param $key
  110. * @return mixed
  111. */
  112. function getConfigValue($key)
  113. {
  114. return Config::where('key', $key)->value('value');
  115. }
  116. /**
  117. * 生成订单编号
  118. * @param $prefix
  119. * @return string
  120. */
  121. function createOrderNo($prefix='')
  122. {
  123. return $prefix.date('YmdHi').substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8) . rand(100,999);
  124. }
  125. /**
  126. * 生成唯一码
  127. * @param $key
  128. * @return string
  129. */
  130. function getOnlyCode($key)
  131. {
  132. $total_count = RedisDataServer::creatServer()->getData($key);
  133. if (empty($total_count)){
  134. $total_count = rand(100,300);
  135. // 获取当前时间戳
  136. $now = time();
  137. // 获取今天结束的时间戳
  138. $endOfDay = strtotime("tomorrow") - 1;
  139. // 计算剩余时间(秒)
  140. $secondsLeft = bcsub($endOfDay,$now,1);
  141. RedisDataServer::creatServer()->setData($key,$total_count,'str',$secondsLeft);
  142. }
  143. RedisDataServer::creatServer()->setIncr($key);
  144. return date('md') . $total_count;
  145. }
  146. /**
  147. * @param $str
  148. * @return array|string|string[]|null
  149. */
  150. function utf8_filter($str)
  151. {
  152. $pattern = '/[^\x{4e00}-\x{9fa5}\w]/u';
  153. // 使用正则表达式替换为空字符串
  154. $data = preg_replace($pattern, '', $str);
  155. return $data;
  156. }
  157. /**
  158. * 字符串去标签过滤及空格过滤
  159. * @param $str_name
  160. * @param $default
  161. * @return string
  162. */
  163. function filtrationStr($str_name, $default = '')
  164. {
  165. $str = request()->input($str_name);
  166. if (empty($str)) {
  167. return $default;
  168. };
  169. if (is_string($str)){
  170. $str = strip_tags($str);
  171. $str = trim($str);
  172. }elseif (is_array($str)){
  173. $data = [];
  174. foreach ($str as $value){
  175. $value = strip_tags($value);
  176. $data[] = trim($value);
  177. }
  178. $str = $data;
  179. }else{
  180. $str = json_encode($str);
  181. $str = strip_tags($str);
  182. $str = trim($str);
  183. $str = json_decode($str, true);
  184. }
  185. return $str;
  186. }
  187. /**
  188. * 手机号码验证
  189. * @param $phone
  190. * @return bool
  191. */
  192. function verifyPhone($phone)
  193. {
  194. if (empty($phone)) return false;
  195. if (!preg_match('/^1[3-9]\d{9}$/', $phone)){
  196. return false;
  197. }
  198. return true;
  199. }
  200. // /**
  201. // * 获取阿里云sts临时权限 旧版alibabacloud/sdk包
  202. // */
  203. // function getAliSts()
  204. // {
  205. // $data = RedisDataServer::creatServer()->getData('sts_data');
  206. // if ($data) {
  207. // $data = json_decode($data, true);
  208. // } else {
  209. // $accessKeyId = env('ALI_OSS_ACCESS_ID');
  210. // $accessSecret = env('ALI_OSS_ACCESS_KEY');
  211. // AlibabaCloud::accessKeyClient($accessKeyId, $accessSecret)->regionId('cn-chengdu')->asDefaultClient();
  212. // //设置参数,发起请求。
  213. // try {
  214. // $result = AlibabaCloud::rpc()
  215. // ->product('Sts')
  216. // ->scheme('https') // https | http
  217. // ->version('2015-04-01')
  218. // ->action('AssumeRole')
  219. // ->method('POST')
  220. // ->host('sts.aliyuncs.com')
  221. // ->options([
  222. // 'query' => [
  223. // 'RegionId' => "cn-chengdu",
  224. // 'RoleArn' => "acs:ram::1816998012508375:role/ramosstest",
  225. // 'RoleSessionName' => "js-oss-serve",
  226. // 'DurationSeconds' => 900,
  227. // ],
  228. // ])
  229. // ->request();
  230. // $result = $result->toArray();
  231. // if (empty($result['Credentials'])) {
  232. // return ['code' => 0, 'msg' => '获取token信息失败'];
  233. // }
  234. // $data = $result['Credentials'];
  235. // unset($data['Expiration']);
  236. // RedisDataServer::creatServer()->setData('sts_data', $data, 'json', 800);
  237. // } catch (ClientException $e) {
  238. // return ['code' => 0, 'msg' => $e->getErrorMessage()];
  239. // }
  240. // }
  241. // return ['code' => 1, 'msg' => '获取信息成功', 'data' => $data];
  242. //
  243. // }
  244. /**
  245. * 获取阿里云sts临时权限 alibabacloud/sts包
  246. */
  247. function getAliSts()
  248. {
  249. $data = RedisDataServer::creatServer()->getData('sts_data');
  250. if ($data) {
  251. $data = json_decode($data, true);
  252. } else {
  253. // 配置你的AccessKeyId和AccessKeySecret
  254. $accessKeyId = config('aliyun.oss.access_id');
  255. $accessKeySecret = config('aliyun.oss.access_key');
  256. AlibabaCloud::accessKeyClient($accessKeyId,$accessKeySecret)
  257. ->regionId('cn-chengdu')
  258. ->asDefaultClient();
  259. try {
  260. $request = Sts::v20150401()->assumeRole();
  261. $result = $request
  262. ->withRoleArn("acs:ram::1816998012508375:role/ramosstest")
  263. ->withRoleSessionName("js-oss-serve")
  264. ->request();
  265. $result = $result->toArray();
  266. if (empty($result['Credentials'])) {
  267. return ['code' => 0, 'msg' => '获取token信息失败'];
  268. }
  269. $data = $result['Credentials'];
  270. unset($data['Expiration']);
  271. RedisDataServer::creatServer()->setData('sts_data', $data, 'json', 800);
  272. } catch (ClientException $e) {
  273. return ['code' => 0, 'msg' => $e->getErrorMessage()];
  274. }
  275. }
  276. return ['code' => 1, 'msg' => '获取信息成功', 'data' => $data];
  277. }
  278. /**
  279. * oss上传
  280. */
  281. function uploadAliOss($filePath,$path = 'images')
  282. {
  283. // 配置信息
  284. $accessKeyId = config('aliyun.oss.access_id');
  285. $accessSecret = config('aliyun.oss.access_key');
  286. $endpoint = "oss-cn-chengdu.aliyuncs.com"; // 如 oss-cn-hangzhou.aliyuncs.com
  287. $bucket= config('aliyun.oss.bucket'); // OSS中的存储空间名称
  288. // 初始化
  289. try {
  290. $ossClient = new OssClient($accessKeyId, $accessSecret, $endpoint);
  291. $upload_path = "files" . DIRECTORY_SEPARATOR . $path . DIRECTORY_SEPARATOR . date('Ymd', time()) . DIRECTORY_SEPARATOR;
  292. $extension = pathinfo($filePath, PATHINFO_EXTENSION);
  293. $object = $upload_path . md5(uniqid() . time()) . $extension; // OSS中的文件路径和名称
  294. // 上传文件
  295. $ossClient->uploadFile($bucket, $object, $filePath);
  296. return ['code' => 1, 'msg' => '上传成功','data'=>$object];
  297. } catch (OssException $e) {
  298. return ['code' => 0, 'msg' => $e->getMessage()];
  299. }
  300. }
  301. /**
  302. * 删除oss文件
  303. * @param $filePath
  304. * @return bool
  305. * @throws RequestCore_Exception
  306. */
  307. function delAliOss($filePath)
  308. {
  309. // 配置信息
  310. $accessKeyId = config('aliyun.oss.access_id');
  311. $accessSecret = config('aliyun.oss.access_key');
  312. $endpoint = "oss-cn-chengdu.aliyuncs.com"; // 如 oss-cn-hangzhou.aliyuncs.com
  313. $bucket= config('aliyun.oss.bucket'); // OSS中的存储空间名称
  314. try {
  315. $ossClient = new OssClient($accessKeyId, $accessSecret, $endpoint);
  316. // 删除文件
  317. $ossClient->deleteObject($bucket, urldecode($filePath));
  318. return true;
  319. } catch (OssException $e) {
  320. ErrorRecord::create(['msg' => '阿里云oss删除失败', 'data' => json_encode($filePath,JSON_UNESCAPED_UNICODE)]);
  321. return false;
  322. }
  323. }
  324. /**
  325. * 获取城市名称
  326. * @param $province_id
  327. * @param $city_id
  328. * @param $area_id
  329. * @param $street_id
  330. * @return string
  331. */
  332. function getCityName($province_id = 0, $city_id = 0, $area_id = 0, $street_id = 0)
  333. {
  334. $area_arr = [$province_id, $city_id, $area_id, $street_id];
  335. $area_arr = array_filter($area_arr);
  336. if ($area_arr) {
  337. $region = Region::whereIn('id', $area_arr)->orderBy('id', 'asc')->pluck('name')->toArray();
  338. $city_name = implode(' ', $region);
  339. } else {
  340. $city_name = '';
  341. }
  342. return $city_name;
  343. }
  344. /**
  345. * 获取两个经纬度直接距离
  346. * @param $lat1
  347. * @param $lng1
  348. * @param $lat2
  349. * @param $lng2
  350. * @return float
  351. */
  352. function getDistance($lat1, $lng1, $lat2, $lng2){
  353. $lat1 = ($lat1 * pi() ) / 180;
  354. $lng1 = ($lng1 * pi() ) / 180;
  355. $lat2 = ($lat2 * pi() ) / 180;
  356. $lng2 = ($lng2 * pi() ) / 180;
  357. $calcLongitude = $lng2 - $lng1;
  358. $calcLatitude = $lat2 - $lat1;
  359. $dist = 2 * asin(sqrt(pow(sin($calcLatitude/2),2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude/2),2)));
  360. $dist = $dist * 6378.137;
  361. return round($dist, 2);
  362. }
  363. /**
  364. * 获取真实IP
  365. * @return mixed
  366. */
  367. function getClientIp()
  368. {
  369. $http_x_forwarded_for = request()->header('x-forwarded-for');
  370. if (empty($http_x_forwarded_for)) {
  371. return request()->getClientIp();
  372. } else {
  373. $http_x_forwarded_for = explode(',', $http_x_forwarded_for);
  374. return $http_x_forwarded_for[0];
  375. }
  376. }
  377. /**
  378. * 截取字符串
  379. * @param $string
  380. * @param $limit
  381. * @param $suffix
  382. * @return mixed|string
  383. */
  384. function truncateChineseString($string, $limit = 100, $suffix = '...') {
  385. if (mb_strlen($string, 'UTF-8') <= $limit) {
  386. // 如果字符串长度没有超过限制,直接返回
  387. return $string;
  388. }
  389. // 截取前 $limit 个汉字
  390. $truncated = mb_substr($string, 0, $limit, 'UTF-8');
  391. // 确保截取后的字符串是完整的汉字,不会被截断
  392. // 如果最后一个字符不是汉字,则需要回溯到上一个汉字的位置
  393. // $lastChar = mb_substr($truncated, -1, 1, 'UTF-8');
  394. // if (preg_match('/[^\x{4e00}-\x{9fa5}]/u', $lastChar)) {
  395. // // 最后一个字符不是汉字,回溯到上一个汉字
  396. // $truncated = mb_substr($string, 0, mb_strrpos($truncated, mb_substr($string, 0, mb_strlen($truncated, 'UTF-8') - 1, 'UTF-8'), 'UTF-8'), 'UTF-8');
  397. // }
  398. // 添加省略号
  399. return $truncated . $suffix;
  400. }
  401. /**
  402. * 处理图片压缩
  403. * @param $img
  404. * @param $str
  405. * @return string
  406. */
  407. function setImageCompress($img,$str)
  408. {
  409. //查找链接中?出现的位置
  410. $find = strrpos($img ,'?');
  411. if (!$find){//没有就直接拼接
  412. return $img . '?' . $str;
  413. }else{
  414. $url = substr($img,0,$find);
  415. return $url . '?' . $str;
  416. }
  417. }
  418. /**
  419. * 获取随机字符串
  420. * @param int $length
  421. * @param string $strPol
  422. * @return string|null
  423. */
  424. function getRandChar($length = 6, $strPol = '')
  425. {
  426. if ($length <= 0) $length = 1;
  427. $str = null;
  428. if (empty($strPol)) $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
  429. $max = strlen($strPol) - 1;
  430. for ($i = 0; $i < $length; $i++) {
  431. $str .= $strPol[rand(0, $max)];//rand($min,$max)生成介于min和max两个数之间的一个随机整数
  432. }
  433. return $str;
  434. }
  435. /**
  436. * 截取字符串
  437. * @param $num
  438. * @param $decimals
  439. * @return string
  440. */
  441. function truncateDecimal($num, $decimals = 2) {
  442. $factor = pow(10, $decimals);
  443. $truncated = (int)($num * $factor) / $factor;
  444. return number_format($truncated, $decimals, '.', '');
  445. }
  446. }