Utils.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: wangchen
  5. * Date: 2019-05-07
  6. * Time: 15:22
  7. */
  8. namespace App\Libs;
  9. use App\Cache\CacheKeys;
  10. use Hashids;
  11. use App\Exceptions\ApiException;
  12. use PhpAmqpLib\Connection\AMQPStreamConnection;
  13. use PhpAmqpLib\Message\AMQPMessage;
  14. class Utils
  15. {
  16. /**
  17. * 异常报错
  18. * @param $errorData
  19. * @throws ApiException
  20. */
  21. public static function throwError($errorData)
  22. {
  23. // 分解错误码、错误信息
  24. $arr = explode(':', (string)$errorData);
  25. $code = (int)$arr[0];
  26. $msg = (string)$arr[1];
  27. throw new ApiException($code, $msg);
  28. }
  29. /**
  30. * 解码加密id
  31. * @param $idStr
  32. * @return int
  33. */
  34. public static function getDecodeId($idStr)
  35. {
  36. if (!is_numeric($idStr)) {
  37. $idArr = Hashids::decode($idStr);
  38. $id = isset($idArr[0]) ? (int)$idArr[0] : 0;
  39. } else {
  40. $id = $idStr;
  41. }
  42. return $id;
  43. }
  44. /**
  45. * 加密id
  46. * @param $id
  47. * @return mixed
  48. */
  49. public static function getEncodeId($id)
  50. {
  51. return Hashids::encode($id);
  52. }
  53. /**
  54. * 加密批量bid
  55. * @param $bids
  56. * @return array
  57. */
  58. public static function getEncodeIds($bids)
  59. {
  60. return array_map(function ($bid) {
  61. return Hashids::encode($bid);
  62. }, $bids);
  63. }
  64. /**
  65. * 审核状态判断,true为审核状态,false默认
  66. * @param $package
  67. * @param $brand
  68. * @param $codeVersion
  69. * @return bool
  70. */
  71. public static function checkIsAudit($package, $brand, $codeVersion): bool
  72. {
  73. $audit = getProp(config('audit'), $package, []);
  74. if ($audit && $codeVersion === getProp($audit, 'codeVersion') && strtolower($brand) === getProp($audit, 'brand')) {
  75. return true;
  76. }
  77. return false;
  78. }
  79. /**
  80. * 获取redis的key
  81. * @param $keyStr // 例如:wap.rank_page
  82. * @param array $args // 例如:[10, 2000]
  83. *
  84. * Utils::getCacheKey('wap.rank_page', [10, 2000])
  85. * Utils::getCacheKey('promotion.setStatus')
  86. * Utils::getCacheKey('promotion.infos', [2])
  87. *
  88. * @return string
  89. */
  90. public static function getCacheKey($keyStr, $args = [])
  91. {
  92. $stdStr = array_get(CacheKeys::$all, $keyStr, '');
  93. if ($args) {
  94. $stdStr = sprintf($stdStr, ...$args);
  95. }
  96. return $stdStr;
  97. }
  98. /**
  99. * 展示友好数字
  100. * @param $num
  101. * @return string
  102. */
  103. public static function showNiceNumber($num)
  104. {
  105. if ($num >= 10000) {
  106. $num = sprintf('%.1f', round($num / 10000 * 100) / 100) . '万';
  107. } elseif ($num >= 1000) {
  108. $num = sprintf('%.1f', round($num / 1000 * 100) / 100) . '千';
  109. }
  110. return $num;
  111. }
  112. /**
  113. * 根据日期获得这周的周一
  114. * @param $date
  115. * @param int $d
  116. * @param string $format
  117. * @return false|string
  118. */
  119. public static function firstOfWeek($date, $d = 0, $format = 'Ymd')
  120. {
  121. $now = strtotime($date) - $d * 86400; //当时的时间戳
  122. $number = date("w", $now); //当时是周几
  123. $number = $number == 0 ? 7 : $number; //如遇周末,将0换成7
  124. $diff_day = $number - 1; //求到周一差几天
  125. return date($format, $now - ($diff_day * 60 * 60 * 24));
  126. }
  127. /**
  128. * 老原创的签名
  129. * @param $time
  130. * @return string
  131. */
  132. public static function getOldYcSign($time): string
  133. {
  134. $privateKey = env('EXTERNAL_PRIVATE_KEY');
  135. return md5(md5($time . $privateKey) . $privateKey);
  136. }
  137. /**
  138. * @param array $data
  139. * @param array $colHeaders
  140. * @param bool $asString
  141. * @return bool|string
  142. */
  143. public static function toCSV(array $data, array $colHeaders = array(), $asString = false)
  144. {
  145. $stream = $asString ? fopen('php://temp/maxmemory', 'wb+') : fopen('php://output', 'wb');
  146. if (!empty($colHeaders)) {
  147. fputcsv($stream, $colHeaders);
  148. }
  149. foreach ($data as $record) {
  150. fputcsv($stream, $record);
  151. }
  152. if ($asString) {
  153. rewind($stream);
  154. $returnVal = stream_get_contents($stream);
  155. fclose($stream);
  156. return $returnVal;
  157. }
  158. fclose($stream);
  159. return true;
  160. }
  161. /**
  162. * 设备信息
  163. * @return string
  164. */
  165. public static function getDeviceType(): string
  166. {
  167. //全部变成小写字母
  168. $agent = strtolower(getProp($_SERVER, 'HTTP_USER_AGENT'));
  169. $type = 'other';
  170. //分别进行判断
  171. if (strpos($agent, 'iphone') || strpos($agent, 'ipad')) {
  172. $type = 'ios';
  173. }
  174. if (strpos($agent, 'android')) {
  175. $type = 'android';
  176. }
  177. return $type;
  178. }
  179. /**
  180. * 是否在微信内打卡
  181. * @return bool
  182. */
  183. public static function isOpenedInWechat(): bool
  184. {
  185. //全部变成小写字母
  186. $agent = strtolower($_SERVER['HTTP_USER_AGENT']);
  187. //判断
  188. if (strpos($agent, 'micromessenger')) {
  189. return true;
  190. }
  191. return false;
  192. }
  193. /**
  194. * 组装meta数据
  195. * @param $page
  196. * @param $total
  197. * @param int $pageSize
  198. * @return array
  199. */
  200. public static function buildMeta($page, $total, $pageSize = 15): array
  201. {
  202. $lastPage = (int)ceil($total / $pageSize);
  203. return [
  204. 'current_page' => (int)$page,
  205. 'next_page' => ++$page,
  206. 'last_page' => $lastPage ?? 1,
  207. 'per_page' => (int)$pageSize,
  208. 'total' => (int)$total,
  209. 'next_page_url' => '',
  210. 'prev_page_url' => ''
  211. ];
  212. }
  213. /**
  214. * 随机书币
  215. * @param $coin
  216. * @param $num
  217. * @return array|bool
  218. * @throws \Exception
  219. */
  220. public static function getRandomCoin($coin, $num)
  221. {
  222. $result = [];
  223. if ($coin < $num || $coin < 1 || $num < 1) {
  224. return $result;
  225. }
  226. // 计算平均值
  227. $rem = $coin % $num;
  228. $mean = ($coin - $rem) / $num;
  229. // 水平分割
  230. for ($i = 0; $i < $num; $i++) {
  231. $result[$i] = $mean;
  232. }
  233. // 水平分割后将取模多余部分分配给第一个红包
  234. $result[0] += $rem;
  235. // 随机分配金额
  236. for ($i = 0; $i < $num; $i++) {
  237. $r1 = random_int(0, $num - 1);
  238. $r2 = random_int(0, $num - 1);
  239. $per = random_int(1, 99) / 100;
  240. // 随机金额
  241. $mon = $result[$r1] - floor($result[$r1] * $per);
  242. if ($result[$r1] - $mon > 0) {
  243. // 减去随机金额
  244. $result[$r1] -= $mon;
  245. // 添加随机金额
  246. $result[$r2] += $mon;
  247. }
  248. }
  249. return $result;
  250. }
  251. /**
  252. * @param int $length
  253. * @param int $type
  254. * @return string
  255. * @throws \Exception
  256. */
  257. public static function randCode($length = 32, $type = 0): string
  258. {
  259. $arr = [
  260. 1 => '0123456789',
  261. 2 => 'abcdefghijklmnopqrstuvwxyz',
  262. 3 => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
  263. 4 => '~@#$%^&*(){}[]|'
  264. ];
  265. if ($type === 0) {
  266. array_pop($arr);
  267. $string = implode('', $arr);
  268. } elseif ($type === -1) {
  269. $string = implode('', $arr);
  270. } else {
  271. $string = $arr[$type];
  272. }
  273. $count = strlen($string) - 1;
  274. $code = '';
  275. for ($i = 0; $i < $length; $i++) {
  276. $code .= $string[random_int(0, $count)];
  277. }
  278. return $code;
  279. }
  280. /**
  281. * 将数据推送到rabbitMq
  282. * 参考:https://www.vckai.com/xiao-xi-dui-lie-rabbitmq-san-phpde-shi-yong-shi-li
  283. * @param $messageBody
  284. * @param string $queue
  285. * @return bool
  286. */
  287. public static function pushDataToAppSyncMq($messageBody, $queue = 'ycsd_sync'): bool
  288. {
  289. $exchange = $queue; // 交换器
  290. $routing_key = $queue;
  291. try {
  292. $host = env('RABBITMQ_HOST');
  293. $port = env('RABBITMQ_PORT');
  294. $user = env('RABBITMQ_LOGIN');
  295. $passwd = env('RABBITMQ_PASSWORD');
  296. $vhost = env('RABBITMQ_VHOST');
  297. $connection = new AMQPStreamConnection($host, $port, $user, $passwd, $vhost);
  298. // 创建通道
  299. $channel = $connection->channel();
  300. /**
  301. * 创建队列(Queue)
  302. * name: hello // 队列名称
  303. * passive: false // 如果用户仅仅想查询某一个队列是否已存在,如果不存在,不想建立该队列,仍然可以调用queue.declare,
  304. * 只不过需要将参数passive设为true,传给queue.declare,如果该队列已存在,则会返回true;
  305. * 如果不存在,则会返回Error,但是不会创建新的队列。
  306. * durable: true // 是不持久化, true ,表示持久化,会存盘,服务器重启仍然存在,false,非持久化
  307. * exclusive: false // 是否排他,指定该选项为true则队列只对当前连接有效,连接断开后自动删除
  308. * auto_delete: false // 是否自动删除,当最后一个消费者断开连接之后队列是否自动被删除
  309. */
  310. $channel->queue_declare($queue, true, false, false, false);
  311. /**
  312. * 创建交换机(Exchange)
  313. * name: vckai_exchange// 交换机名称
  314. * type: direct // 交换机类型,分别为direct/fanout/topic,参考另外文章的Exchange Type说明。
  315. * passive: false // 如果设置true存在则返回OK,否则就报错。设置false存在返回OK,不存在则自动创建
  316. * durable: false // 是否持久化,设置false是存放到内存中的,RabbitMQ重启后会丢失
  317. * auto_delete: false // 是否自动删除,当最后一个消费者断开连接之后队列是否自动被删除
  318. */
  319. // $channel->exchange_declare('', 'direct', true, false, false);
  320. // 绑定消息交换机和队列
  321. // $channel->queue_bind($queue, $exchange);
  322. /**
  323. * 创建AMQP消息类型
  324. * delivery_mode 消息是否持久化
  325. * AMQPMessage::DELIVERY_MODE_NON_PERSISTENT 不持久化
  326. * AMQPMessage::DELIVERY_MODE_PERSISTENT 持久化
  327. */
  328. $msg = new AMQPMessage($messageBody, ['delivery_mode' => AMQPMessage::DELIVERY_MODE_NON_PERSISTENT]);
  329. /**
  330. * 发送消息
  331. * msg: $msg // AMQP消息内容
  332. * exchange: vckai_exchange // 交换机名称
  333. * queue: hello // 队列名称
  334. */
  335. $channel->basic_publish($msg, '', $routing_key);
  336. /**
  337. * 关闭链接
  338. */
  339. $channel->close();
  340. $connection->close();
  341. } catch (\Exception $e) {
  342. sendNotice('RabbitMq 连接失败 ' . $e->getMessage());
  343. }
  344. return true;
  345. }
  346. }