src/Controller/Telegram/DeliveryBotController.php line 147

Open in your IDE?
  1. <?php
  2. namespace Slivki\Controller\Telegram;
  3. use Slivki\Dao\User\UserOrderDaoInterface;
  4. use Slivki\Entity\BotChatSession;
  5. use Slivki\Entity\FoodOfferExtension;
  6. use Slivki\Entity\FoodOrder;
  7. use Slivki\Entity\GeoLocation;
  8. use Slivki\Exception\User\InvalidPasswordException;
  9. use Slivki\Services\BelTransSat\RouteBuilderBelTransSatService;
  10. use Slivki\Services\DeliveryService;
  11. use Slivki\Services\Sms\Contract\SmsSenderInterface;
  12. use Slivki\Util\Telegram\CourierBot;
  13. use Slivki\Validator\User\PasswordValidator;
  14. use Symfony\Component\HttpKernel\KernelInterface;
  15. use Symfony\Component\Routing\Annotation\Route;
  16. use Slivki\Entity\Director;
  17. use Slivki\Entity\User;
  18. use Slivki\Util\CommonUtil;
  19. use Slivki\Util\Logger;
  20. use Slivki\Util\Telegram\DeliveryBot;
  21. use Symfony\Component\HttpFoundation\Request;
  22. use Symfony\Component\HttpFoundation\Response;
  23. class DeliveryBotController extends TelegramBotController
  24. {
  25.     private DeliveryService $deliveryService;
  26.     private UserOrderDaoInterface $userOrderDao;
  27.     private PasswordValidator $passwordValidator;
  28.     public function __construct(KernelInterface $kernelUserOrderDaoInterface $userOrderDaoPasswordValidator $passwordValidator)
  29.     {
  30.         parent::__construct($kernel);
  31.         $this->userOrderDao $userOrderDao;
  32.         $this->passwordValidator $passwordValidator;
  33.     }
  34.     /** @Route("/tg/delivery/bot/hook") */
  35.     public function webHookAction(
  36.         Request $request,
  37.         DeliveryService $deliveryService,
  38.         RouteBuilderBelTransSatService $routeBuilderBelTransSatService,
  39.         SmsSenderInterface $smsSender
  40.     ): Response {
  41.         $this->deliveryService $deliveryService;
  42.         $logger Logger::instance('DeliveryBot');
  43.         $logger->info('hook');
  44.         $data json_decode($request->getContent());
  45.         $logger->info($request->getContent());
  46.         if (property_exists($data'message')) {
  47.             $this->handleMessage($request$data);
  48.         } else if (property_exists($data'callback_query')) {
  49.             $this->handleCallback($routeBuilderBelTransSatService$smsSender$data$request->getHost());
  50.         }
  51.         return new Response();
  52.     }
  53.     public function handleMessage(Request $request$data) {
  54.         if (!property_exists($data->message'text')) {
  55.             return;
  56.         }
  57.         $message $data->message->text;
  58.         $chatID $data->message->chat->id;
  59.         $this->log('chatID ' $chatID);
  60.         $logger Logger::instance('DeliveryBot');
  61.         $logger->info('handleMessage');
  62.         $logger->info($message);
  63.         $response null;
  64.         $replyMarkup false;
  65.         $entityManager $this->getDoctrine()->getManager();
  66.         $bot = new DeliveryBot($entityManager);
  67.         switch ($message) {
  68.             case '/start':
  69.                 $response "Здравствуйте! Необходима авторизация. Введите email партнерского аккаунта на slivki.by";
  70.                 $bot->writeSession($chatIDDeliveryBot::STATE_INIT);
  71.                 break;
  72.             default:
  73.                 $logger->info($message);
  74.                 $session $bot->getSession($chatID);
  75.                 if (CommonUtil::isBeginsWith($message'/')) {
  76.                     $exploded explode(' '$message);
  77.                     if ($exploded[0] == '/email') {
  78.                         $message $exploded[1];
  79.                         $session->setLastPage(DeliveryBot::STATE_INIT);
  80.                     }
  81.                     $exploded explode(' '$message);
  82.                     if ($exploded[0] == '/password') {
  83.                         $message $exploded[1];
  84.                         $session->setLastPage(DeliveryBot::STATE_PASSWORD);
  85.                     }
  86.                 }
  87.                 if (!$session) {
  88.                     break;
  89.                 }
  90.                 switch ($session->getLastPage()) {
  91.                     case DeliveryBot::STATE_INIT:
  92.                         $email trim(mb_strtolower($message));
  93.                         /*$emailConstraint = new \Symfony\Component\Validator\Constraints\Email();
  94.                         $error = $this->get('validator')->validate($email, $emailConstraint);
  95.                         $this->log(print_r($error, true));
  96.                         if ($error->count() > 0) {
  97.                             $response = 'Введите корректный email';
  98.                             break;
  99.                         }*/
  100.                         $director $entityManager->getRepository(Director::class)->findOneByEmail($email);
  101.                         $user $entityManager->getRepository(User::class)->findOneByEmail($email);
  102.                         if (!$director || !$user) {
  103.                             $response 'Пользователь не найден. Введите корректный email';
  104.                             break;
  105.                         }
  106.                         $response 'Введите пароль';
  107.                         $bot->writeSession($chatIDDeliveryBot::STATE_PASSWORD$email);
  108.                         break;
  109.                     case DeliveryBot::STATE_PASSWORD:
  110.                         $email $session->getData();
  111.                         $user $entityManager->getRepository(User::class)->findOneByEmail($email);
  112.                         try {
  113.                             $this->passwordValidator->validate($user$message);
  114.                         } catch (InvalidPasswordException $exception) {
  115.                             $response 'Неправильный пароль';
  116.                             break;
  117.                         }
  118.                         $response 'Успешно авторизовано, ожидайте заказы.';
  119.                         $director $entityManager->getRepository(Director::class)->findOneByEmail($email);
  120.                         $session->setUserID($director->getID());
  121.                         $entityManager->flush();
  122.                         $this->writeSession($chatIDDeliveryBot::STATE_AUTHENTICATED);
  123.                         break;
  124.                     case DeliveryBot::STATE_AUTHENTICATED:
  125.                         $response 'шо?';
  126.                 }
  127.         }
  128.         $this->log('RESPONSE');
  129.         $this->log($response);
  130.         if ($response != null) {
  131.             $bot->sendMessage($chatID$response$replyMarkup);
  132.         }
  133.     }
  134.     public function handleCallback(
  135.         RouteBuilderBelTransSatService $routeBuilderBelTransSatService,
  136.         SmsSenderInterface $smsSender,
  137.         $data,
  138.         string $domain
  139.     ) {
  140.         $chatID $data->callback_query->from->id;
  141.         $orderID null;
  142.         $message null;
  143.         $status FoodOrder::DELIVERY_STATUS_INIT;
  144.         $entityManager $this->getDoctrine()->getManager();
  145.         $bot = new DeliveryBot($entityManager);
  146.         if (CommonUtil::isBeginsWith($data->callback_query->data'accept')) {
  147.             $orderID = (int)str_replace("accept="''$data->callback_query->data);
  148.             $status FoodOrder::DELIVERY_STATUS_ACCEPTED;
  149.             $message 'Заказ принят';
  150.             $phoneNumberInOrder $this->userOrderDao->findPhoneNumberInOrderByOfferOrderId($orderID) ?: $this->getUser()->getPhone();
  151.             $smsSender->send(
  152.                 $this->convertPhoneNumber($phoneNumberInOrder),
  153.                 'Ваш заказ принят. Благодарим вас за выбор!',
  154.                 $domain,
  155.             );
  156.         } else if (CommonUtil::isBeginsWith($data->callback_query->data'decline')) {
  157.             $orderID = (int)str_replace("decline="''$data->callback_query->data);
  158.             $status FoodOrder::DELIVERY_STATUS_DECLINED;
  159.             $message 'Заказ отклонен';
  160.             $bot->sendApiRequest('editMessageReplyMarkup', [
  161.                 'chat_id' => $chatID,
  162.                 'message_id' => $data->callback_query->message->message_id,
  163.                 'reply_markup' => null,
  164.             ]);
  165.         } else if (CommonUtil::isBeginsWith($data->callback_query->data'cooking_time')) {
  166.             $parameters = [];
  167.             parse_str($data->callback_query->data$parameters);
  168.             //Dima, hello
  169.             $orderId = (int)$parameters['order_id'];
  170.             $cookingTime = (int)$parameters['cooking_time'];
  171.             $bot->sendApiRequest('editMessageReplyMarkup', [
  172.                 'chat_id' => $chatID,
  173.                 'message_id' => $data->callback_query->message->message_id,
  174.                 'reply_markup' => null,
  175.             ]);
  176.             return;
  177.         }
  178.         if (!$orderID) {
  179.             return;
  180.         }
  181.         $order $entityManager->find(FoodOrder::class, $orderID);
  182.         if (!$order) {
  183.             return;
  184.         }
  185.         $logger Logger::instance(\sprintf('DeliveryBotCallback %d',  $orderID));
  186.         $logger->info(\sprintf('status: %d'$status));
  187.         $order->setDeliveryStatus($status);
  188.         $entityManager->flush();
  189.         if ($status === FoodOrder::DELIVERY_STATUS_ACCEPTED) {
  190.             try {
  191.                 $routeBuilderBelTransSatService->build($order);
  192.             } catch (\Exception $e) {
  193.                 $logger->error($e->getMessage());
  194.             }
  195.         }
  196.         $bot->sendMessage($chatID$message);
  197.         $courierBot = new CourierBot($entityManager);
  198.         $chatSessions $entityManager->getRepository(BotChatSession::class)->findBy(['botID' => CourierBot::BOT_ID]);
  199.         if (!$chatSessions || count($chatSessions) == 0) {
  200.             $logger->info('no chat session for courier bot');
  201.             return;
  202.         }
  203.         if ($order->getDeliveryStatus() == FoodOrder::DELIVERY_STATUS_ACCEPTED) {
  204.             $message $this->getCourierBotMessage($order);
  205.         } else {
  206.             $message 'ВНИМАНИЕ! ЗАКАЗ ОТКЛОНЕН! №' $orderID;
  207.         }
  208.         foreach ($chatSessions as $chatSession) {
  209.             $logger->info(\sprintf('send message to %d'$chatSession->getChatID()));
  210.             $result $courierBot->sendMessage($chatSession->getChatID(), $message);
  211.             $logger->info($result);
  212.         }
  213.     }
  214.     private function getCourierBotMessage(FoodOrder $foodOrder):string {
  215.         $message 'Служба доставки ';
  216.         $directors $foodOrder->getOffer()->getDirectors();
  217.         if ($directors->count() > 0) {
  218.             $message .= $directors->first()->getName();
  219.         }
  220.         $message .= "\n";
  221.         $locations $foodOrder->getOffer()->getGeoLocations();
  222.         if ($locations->count() > 0) {
  223.             /** @var GeoLocation $location */
  224.             $location $locations->first();
  225.             $message .= 'Ресторан: ' $location->getStreet() . ' ' $location->getHouse() . ' ' $location->getLabel() . "\n";
  226.         }
  227.         $message .= 'Заказ №' $foodOrder->getID() . "\nДоставка: ";
  228.         $address $foodOrder->getDeliveryAddress();
  229.         $message .= $address->getStreet()->getCity() . ' ' $address->getStreet()->getName() . ' ';
  230.         $message .= $address->getHouse() . ' ' $address->getBlock();
  231.         if ($address->getAppartment()) {
  232.             $message .= ', квартира ' $address->getAppartment();
  233.         }
  234.         if ($address->getEntrance()) {
  235.             $message .= ', подъезд ' $address->getEntrance();
  236.         }
  237.         if ($address->getFloor()) {
  238.             $message .= ', этаж ' $address->getFloor();
  239.         }
  240.         if ($address->getDoorphone()) {
  241.             $message .= ', домофон ' $address->getDoorphone();
  242.         }
  243.         $message .= "\nСтоимость доставки " $foodOrder->getDeliveryCost() . ' руб';
  244.         $message .= "\nВремя доставки " $this->deliveryService->getOrderDate($foodOrder->getDeliveryTime()) . "\n";
  245.         $partnerTotal 0;
  246.         foreach ($foodOrder->getOfferOrderDetails() as $detail) {
  247.             /** @var FoodOfferExtension $offerExtension */
  248.             $offerExtension $detail->getOfferExtension();
  249.             $price $detail->getPurchasePrice();
  250.             $partnerTotal += $detail->getItemsCount() * $price;
  251.             $message .= $offerExtension->getName() . ' ('  $offerExtension->getShortDescription()  . ') ' $price ' руб * '  $detail->getItemsCount() . "шт. \n";
  252.         }
  253.         $partnerTotal += $foodOrder->getDeliveryCost();
  254.         switch ($foodOrder->getPaymentType()) {
  255.             case 1:
  256.                 $message .= "\nОплачено " $partnerTotal ' руб';
  257.                 break;
  258.             case 2:
  259.                 if ($address->isPickup()) {
  260.                     $message .= "\nОплата наличными на месте " $partnerTotal ' руб';
  261.                 } else {
  262.                     $message .= "\nОплата наличными курьеру " $partnerTotal ' руб';
  263.                 }
  264.                 break;
  265.             case 3:
  266.                 if ($address->isPickup()) {
  267.                     $message .= "\nОплата картой на месте " $partnerTotal ' руб';
  268.                 } else {
  269.                     $message .= "\nОплата картой курьеру " $partnerTotal ' руб';
  270.                 }
  271.         }
  272.         $message .= "\nКлиент: " $address->getName() . ', номер телефона ' $address->getPhone();
  273.         if ($foodOrder->getChangeAmount()) {
  274.             $message .= "\nСдача с: " $foodOrder->getChangeAmount() . ' руб';
  275.         }
  276.         if ($foodOrder->getComment()) {
  277.             $message .= "\nКомментарий: " $foodOrder->getComment();
  278.         }
  279.         return $message;
  280.     }
  281.     private function convertPhoneNumber(string $phoneNumber): string
  282.     {
  283.         return \str_replace(['+''('')''-'' '], ''$phoneNumber);
  284.     }
  285. }