setName('spider:tc') ->setDescription('同程订单拉取器') ->setDefinition( new InputDefinition(array( new InputOption('sn', 'sn', InputOption::VALUE_REQUIRED), new InputOption('os', 'os', InputOption::VALUE_REQUIRED), new InputOption('day', 'day', InputOption::VALUE_REQUIRED) )) ); } protected function users($routeType) { // if (count($this->_users) > 0) return $this->_users; $users = Admins::where('status', 1)->where('is_order', 1)->where('route_type', $routeType)->select(); $us = []; foreach ($users as $u) { $ru = Redis::get('CRM:USER:ONLINE:' . $u->id); if (empty($ru)) continue; $_u = new stdClass(); $_u->username = $u->id; $us[] = $_u; }; $this->_users = $us; return $this->_users; } protected $_redis_pool = []; protected function poolUser($status = 0, $categoryDesc = '') { $routeType = AdminController::ROUTE_LISTS[mb_substr($categoryDesc, 0, 2)] ?? 10; $status .= $routeType; if (empty($this->_redis_pool[$status])) { $this->_redis_pool[$status] = Redis::hGetAll('CRM:Pool:' . $status); $users = $this->users($routeType); $_users = []; if (empty($this->_redis_pool[$status])) { foreach ($users as $user) { $_users[$user->username] = 0; Redis::hSet('CRM:Pool:' . $status, $user->username, 0); } $this->_redis_pool[$status] = $_users; } else { asort($this->_redis_pool[$status]); $key_users = array_keys($this->_redis_pool[$status]); $username = $key_users[0]; $max = $this->_redis_pool[$status][$username]; $_users = []; foreach ($users as $user) { $_users[] = $user->username; if (!in_array($user->username, $key_users)) { $this->_redis_pool[$status][$username] = $max; Redis::hSet('CRM:Pool:' . $status, $user->username, $max); } } foreach ($this->_redis_pool[$status] as $username => $val) { if (!in_array($username, $_users)) { unset($this->_redis_pool[$status][$username]); Redis::hDel('CRM:Pool:' . $status, $username); } } } } $username = null; try { $pool = $this->_redis_pool[$status]; if (empty($pool)) $pool = []; asort($pool); $keys = array_keys($pool); // if(!!config('app.debug', true)) return 1; if (empty($keys)) { Log::error(dirname(__FILE__) . __LINE__ . '没有可以分配的用户'); throw new \Exception('没有可以分配的用户'); } $username = $keys[0]; $this->_redis_pool[$status][$username] += 1; Redis::hIncrBy('CRM:Pool:' . $status, $username, 1); } catch (\Exception $e) { Log::error(dirname(__FILE__) . __LINE__ . '没有可以分配的用户', (array)json_encode($e)); throw new \Exception('没有可以分配的用户'); } return $username; } /** @var InputInterface $output */ protected $output; /** * @param InputInterface $input * @param OutputInterface $output * @return int */ protected function execute(InputInterface $input, OutputInterface $output): int { // $name = $input->getArgument('name'); $this->output = $output; $output->writeln('START spider:tc:'.date('Y-m-d H:i:s')); $os = $input->getOption('os'); $orderid = $input->getOption('sn'); $d = $input->getOption('day'); if (empty($d)) { $d = 40; } if ($orderid) { $this->reloadStatus($orderid, $os, $output); return 1; } // echo "状态1\n"; // $this->poolUser(1); // echo "状态2\n"; // $this->poolUser(2); // echo "状态3\n"; // $this->poolUser(3); // echo "状态4\n"; // $this->poolUser(4); // echo "状态5\n"; // $this->poolUser(5); // return 1; // $this->checks($output); // $output->writeln('CHECK spider:dy'); // $day = new Douyin(); // print_r($day->get(1)); // return 1; // sleep(5); // $time = strtotime(date('Y-m-d')); // for ($i = 0; $i <= $d; $i++) { // $day = $time - $i * 24 * 3600; // $start = date('Y-m-d', $day); // $end = date('Y-m-d 23:59:59', $day); // $this->orders($start, $end, false); // // $this->_kuaishouOrder($start, $end, false); // } // 8点20 开始分配订单 date_default_timezone_set('Asia/Shanghai'); $startTime = strtotime(date('Y-m-d 09:10')); if (time() > $startTime) { $start = date('Y-m-d 00:00:00', strtotime("-{$d} days")); $output->writeln('END spider:tc:start:'.$start); $end = date('Y-m-d 23:59:59'); $this->orders($start, $end, false); } if (date('H') >= 1 && date('H') <= 7) { $this->reload($output); } $output->writeln('END spider:tc:'.date('Y-m-d H:i:s')); return self::SUCCESS; } private function orders($start = null, $end = null, $order_id = false) { foreach (Orders::OSS as $k => $os) { $pages = 10; $page = 1; while (true) { if ($page > $pages) break; $list = []; switch ($k) { case 6: case 8: try { $dou = new Tongcheng($k); $list = $dou->get($page, $start, $end, ''); $pages = $dou->totalPage; } catch (\Exception $e) { Log::info('同程订单拉取失败:' . dirname(__FILE__) . __LINE__ . $e); } break; default: # code... break; } foreach ($list as $order) { $item = Orders::where('sn', $order->sn)->find(); if (empty($item)) { if ($order->orderStatus == 400) { continue; } $order->is_zhibo = 2; $oldMobile = orders::where("os", $order->os)->where("mobile", $order->mobile) ->where("create_time", '>=', time() - 24 * 3600 * 3)->find(); if (!empty($oldMobile)) { $admin_id = $oldMobile->admin_id; } else { // $admin_id = $this->poolUser($order->orderStatus, $order->category_desc); try { $admin_id = \app\server\Orders::poolUser($order->orderStatus, $order->product_id); } catch (\Exception $exception) { Log::info(sprintf('tc create order fail:%s, order_id:%s', $exception->getMessage(), $order->sn)); continue; } } if (empty($admin_id)) return null; $order->admin_id = $admin_id; $order->give_time = time(); //判断是否需要发短信 200-待使用,205-预约中(抖音),210-已预约(抖音),310-已履约(抖音),300-已完成 if (in_array($order->order_status, [200, 205, 210, 310, 300]) ) { $this->sms($admin_id, $order); } $work = \app\server\Orders::getLiveRoomWork($order->create_at, $order->product_id); if ($work) { $order->live_room_work_id = $work->id; } //新获得一个用户的,提示管理员有新的订单 Redis::incrBy('CRM:USER:ONLINE:NEW:' . $admin_id, 1); $item = new Orders(); } if ($order->travel_date && empty($order->travel_end)) { $days = $this->_days($order); if ($days) { $order->travel_end = date('Y-m-d 00:00:00', strtotime($order->travel_date) + $days * 24 * 3600); } } $item->os = $order->os; $item->mobile = $order->mobile; if ($item->order_status !== 2 && $order->order_status == 2) { Redis::incrBy('CRM:USER:WRITE:OFF:' . $item->admin_id, 1); } $back = $item->save($order->toArray()); if ($back) { $this->_finance(0, $item->id, $item->asset_price); } } // 数据小于50, 结束 if (empty($list)) { break; } $page++; } } } private function reload($output) { $back = Redis::set('SpiderMt:reload:dy:lock', time(), 'EX', 3600 * 8, 'NX'); if (!$back) return; $orders = Orders::where('create_at', '<=', (time() - 15 * 24 * 3600) * 1000)->where('os', 6)->wherein('status', [1, 2, 3])->select(); foreach ($orders as $order) { $this->reloadStatus($order->sn, $order->os, $output); } } /** * @param $admin_id * @param $order * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function sms($admin_id, $order) { $user = Admins::cache(true)->where('id', $admin_id)->find(); $templateId = 261607; if ((!config('app.debug', true) || config('app.debug', true) === 'false') && (time() * 1000 - $order->create_at) / 1000 < 2 * 24 * 3600) { print_r([$order->mobile, $templateId, ['title' => $order->product_name, 'mobile' => $user->mobile]]); $has = Blacks::where('mobile', $order->mobile)->find(); if (empty($has) && !empty($order->mobile)) { SMS::juhe_sms_send($order->mobile, $templateId, ['title' => $order->product_name, 'mobile' => $user->mobile]); } else { sleep(10); } } else { print_r([$order->mobile, $templateId, ['title' => $order->product_name, 'mobile' => $user->mobile]]); } } private function reloadStatus($orderid, $os, $output) { $w[] = ['sn', '=', $orderid]; if ($os) $w[] = ['os', '=', $os]; $item = Orders::where($w)->find(); if (empty($item)) { $output->writeln('没有找到订单'); } $m = new Tongcheng($os); $it = $m->get(1, null, null, $item->sn); if ($it) { $back = $item->save($it[0]); if ($back) { $this->_finance(0, $item->id, $item->asset_price); } } else { $output->writeln('没有拉取到数据:' . $orderid); } } private function _days($order) { if (stripos($order->product_name, '一日') !== false) { return 1; } preg_match('/(\d)天/', $order->product_name, $all); if (!empty($all) && intval($all[1]) > 0) { return $all[1]; } return 0; } private function zhibo($title, $os = 0) { if ($os == 3) { return 2; } if ( strlen($title) - 3 == strripos($title, "!") || strlen($title) - 1 == strripos($title, "!") ) { return 1; } elseif (strlen($title) - 3 == strripos($title, "甄")) { return 2; } return 0; } private function _finance($type = 1, $order_id = 0, $price = 0) { // $fa = Finances::where('order_id', $order_id)->where('type', $type)->find(); $back = Redis::set('CRM:ORDER:LOCK:' . $order_id, time(), 'EX', 6, 'NX'); if (!$back) return; $total = Finances::where('order_id', $order_id)->sum('total'); //总的关于这个订单的金额 //如果总金额大于提交上来的核销金额,那就是退费的 //如果提交上来的金额小于总金额,那就是核销的 if ($total > $price) { $type = 2; $fee = -($total - $price); } elseif ($total < $price) { $type = 1; $fee = $price - $total; } else { return; } Finances::create([ 'order_id' => $order_id, 'type' => $type, 'total' => $fee, 'status' => 1 ]); return; // if(empty($fa)) { // if($type == 2) { // $has = Finances::where('order_id', $order_id)->where('type', 1)->find(); // if(empty($has)) return; // } // Finances::create([ // 'order_id' => $order_id, // 'type' => $type, // 'total' => $price, // 'status' => 1 // ]); // } } }