Обсуждение Статьи Чат-бот-магазин часть 4

← К списку тем

← Начало обсуждения в комментариях статьи

Вопрос 1
Метод - обработчик можно ставить в любое место, но если у вас это будет логически связанное место с другими подобными методами, легче потом искать.

Таймер появляется если от Телеграм ушел на вебхук запрос, то должна быть какая-то реакция-результат от обработчика - вот он и ждет. Например какой-то текст, картинка или промежуточный sendChatAction ("печатает текст" или "отправляет фото" ...).

Также на каждое нажатие inline-кнопки обязательно нужно реагировать отправляя answerCallbackQuery - то есть уведомить Телеграм, что запрос от inline-кнопки пришел, в противном случае Телеграм будет слать повторные запросы, по своему расписанию (через 2 сек, 1 мин, 5 мин, 30 мин ...) пока не получит answerCallbackQuery, это даже если вы уже по своему сценарию все сделали и продолжаете работу, то фоном эти запросы все равно будут приходить.

Вопрос 2
Вместе с сообщением можно отправить только один набор объектов в reply_markup:
1. InlineKeyboardMarkup
2. ReplyKeyboardMarkup
3. ReplyKeyboardRemove
4. ForceReply.

В типовом приложении из статьи при старте отправляется набор объектов inline-кнопок с сылками на категории товаров. Добавить в сообщение еще один набор объектов не получиться, но вы можете отправить перед этим сообщение например с текстом "..." и приложить необходимый набор объектов с клавиатурой.

    private function startBot($chat_id, $data)<br />
    {<br />
<br />
        // ...<br />
<br />
        $buttons_first[] = [<br />
            $this->buildKeyboardButton("Кабинет"),<br />
            $this->buildKeyboardButton("Помощь"),<br />
        ];<br />
        // отправляем первый набор кнопок<br />
        $this->sendMessage($chat_id, "...", $buttons_first, true);<br />
<br />
        // отправляем привет<br />
        $this->sendMessage($chat_id, $text, $buttons);<br />
    }

И для этого надо обновить метод sendMessage

    private function sendMessage($user_id, $text, $buttons = NULL, $type = false)<br />
    {<br />
        // готовим массив данных<br />
        $data_send = [<br />
            'chat_id' => $user_id,<br />
            'text' => $text,<br />
            'parse_mode' => 'html'<br />
        ];<br />
        // если переданны кнопки то добавляем их к сообщению<br />
        if (!is_null($buttons) && is_array($buttons)) {<br />
            $data_send['reply_markup'] = !$type ? $this->buildInlineKeyBoard($buttons) : $this->buildKeyBoard($buttons);<br />
        }<br />
        // отправляем текстовое сообщение<br />
        return $this->botApiQuery("sendMessage", $data_send);<br />
    }

iMakeBots 27.06.2019 в 08:47

Авторизуйтесь через Telegram, чтобы ответить.
Откройте бот @SiteAuthBot, нажмите кнопку Старт/Start. Следуйте инструкциям бота.


Ответы

  • Здравствуйте, спасибо большое за ваши ответы, возвращаясь к первому вопросу
    <br />
                if(!$orderRaw['status']) {<br />
                    // готовим кнопку для перехода в Яндекс.Деньги<br />
                    $url = $this-&gt;getUrl($total, $user_id, $orderRaw['id']);<br />
                    $buttons[] = [ $this-&gt;buildInlineKeyBoardButton('Оплатить через Яндекс.Деньги', '', $url),<br />
    				$this-&gt;buildInlineKeyBoardButton('При отправлении Наличными', 'getNal_' . $orderRaw['id']),<br />
    				$this-&gt;buildInlineKeyBoardButton('При отправлении Сканирование QR-Кода Яндекс.Деньги', 'getQrYandex_' . $orderRaw['id']),<br />
    				];<br />
                } else {<br />
                    // если заказ оплачен то уведомляем<br />
                    $text .= &quot;n&lt;b&gt;Заказ оплачен&lt;/b&gt;n&quot;;<br />
                }<br />
    
    Нашел я в index.php
    <br />
    private function getText($data)<br />
        {<br />
            if ($this-&gt;getType($data) == &quot;callback_query&quot;) {<br />
                return $data['callback_query']['data'];<br />
            }<br />
            return $data['message']['text'];<br />
        }<br />
    
    Скопировал кусок, вставил в обработчик, результат тот же, абсолютно. таймер висит и все.
    <br />
          public function getNal($data)<br />
        {<br />
            // Получаем id заказа через данные от кнопки<br />
            $param = explode(&quot;_&quot;, $data['data']);<br />
            $order_id = $param[1];<br />
            if ($this-&gt;getNal($data) == &quot;callback_query&quot;) {<br />
                return $data['callback_query']['data'];<br />
            }<br />
            // Далее логика - например записать в бд<br />
            // что этот заказ будет оплачен наличными,<br />
            // выслать инструкцию ...<br />
        }<br />
    <br />
        public function getQrYandex($data)<br />
        {<br />
            // Получаем id заказа через данные от кнопки<br />
            $param = explode(&quot;_&quot;, $data['data']);<br />
            $order_id = $param[1];<br />
            if ($this-&gt;getQrYandex($data) == &quot;callback_query&quot;) {<br />
                return $data['callback_query']['data'];<br />
     }<br />
            // Далее логика - например записать в бд<br />
            // что этот заказ будет оплачен наличными,<br />
            // выслать инструкцию ...<br />
        }<br />
    
    Есть какое, то решение этой проблемы? С примером текстового сообщения который можно заменить после клика на кнопку оплата наличными, типа "Спасибо" и тд.

    Касательно второго вопроса:

        <br />
    private function startBot($chat_id, $data)<br />
        {<br />
    <br />
            // ...<br />
    <br />
            $buttons_first[] = [<br />
                $this-&gt;buildKeyboardButton(&quot;Кабинет&quot;),<br />
                $this-&gt;buildKeyboardButton(&quot;Помощь&quot;),<br />
            ];<br />
            // отправляем первый набор кнопок<br />
            $this-&gt;sendMessage($chat_id, &quot;...&quot;, $buttons_first, true);<br />
    <br />
            // отправляем привет<br />
            $this-&gt;sendMessage($chat_id, $text, $buttons);<br />
        }<br />
    
    Все супер, все работает, шикарно, спасибо большое, но вот такой вопрос, а как продублировать кнопки во второй ряд?
    Я их продублировал, но видно 2 кнопки, за место 4-х. $buttons_twice не выводятся, как быть?
    <br />
        private function startBot($chat_id, $data)<br />
        {<br />
    <br />
            // ...<br />
    <br />
            $buttons_first[] = [<br />
                $this-&gt;buildKeyboardButton(&quot;Кабинет&quot;),<br />
                $this-&gt;buildKeyboardButton(&quot;Помощь&quot;),<br />
            ];<br />
            $buttons_twice[] = [<br />
                $this-&gt;buildKeyboardButton(&quot;Кабинет&quot;),<br />
                $this-&gt;buildKeyboardButton(&quot;Помощь&quot;),<br />
            ];<br />
            // отправляем первый набор кнопок<br />
            $this-&gt;sendMessage($chat_id, &quot;...&quot;, $buttons_first, $buttons_twice, true);<br />
    <br />
            // отправляем привет<br />
            $this-&gt;sendMessage($chat_id, $text, $buttons);<br />
        }<br />
    
    Вытекающий из кнопок клавиатуры вопрос, как прикрутить к кнопкам функции?
    Нашел статью
    https://habr.com/ru/company/netologyru/blog/326174/
    , взял от туда код кнопок

    <br />
    }elseif ($text == &quot;Картинка&quot;) {<br />
                $url = &quot;https://68.media.tumblr.com/6d830b4f2c455f9cb6cd4ebe5011d2b8/tumblr_oj49kevkUz1v4bb1no1_500.jpg&quot;;<br />
                $telegram-&gt;sendPhoto([ 'chat_id' =&gt; $chat_id, 'photo' =&gt; $url, 'caption' =&gt; &quot;Описание.&quot; ]);<br />
            }elseif ($text == &quot;Гифка&quot;) {<br />
                $url = &quot;https://68.media.tumblr.com/bd08f2aa85a6eb8b7a9f4b07c0807d71/tumblr_ofrc94sG1e1sjmm5ao1_400.gif&quot;;<br />
                $telegram-&gt;sendDocument([ 'chat_id' =&gt; $chat_id, 'document' =&gt; $url, 'caption' =&gt; &quot;Описание.&quot; ]);<br />
    
    A M 27.06.2019 в 23:40
    • Вопрос 1
      <br />
      public function getNal($data)<br />
          {<br />
              // Получаем id заказа через данные от кнопки<br />
              $param = explode(&quot;_&quot;, $data['data']);<br />
              $order_id = $param[1];<br />
      <br />
              // 1. Вы пытаетесь вызвать рекурсию getNal в getNal == бесконечность в вашем варианте<br />
              // 2. $data это массив, и $this-&gt;getNal($data) == &quot;callback_query&quot; вернет false, <br />
              // поэтому это условие никогда не сработает<br />
              // 3. В $data['callback_query']['data'] нет такого ключа в $data<br />
              // в $data уже лежит объект ['callback_query'] <br />
              // Если вам нужно значение из элемента data то оно у нас уже в $param в виде массива<br />
      <br />
              // if ($this-&gt;getNal($data) == &quot;callback_query&quot;) {<br />
              //    return $data['callback_query']['data'];<br />
              // }<br />
              <br />
              // Для теста вы можете просто вызвать Уведомление<br />
              // answerCallbackQuery это позволяет<br />
              $this-&gt;notice($data['id'], &quot;Обработка inline-кнопки getNal&quot;, true);<br />
          }<br />
      <br />
          public function getQrYandex($data)<br />
          {<br />
             $this-&gt;notice($data['id'], &quot;Обработка inline-кнопки getQrYandex&quot;, true);<br />
          }

      Вопрос 2
      Для вывода порядно клавиатуру, также как и inline-кнопки, нужно просто добавить массив объектов следующим элементом массива клавиатуры. Посмотрите какие параметры принимает метод sendMessage, в нем на входе только 1 набор клавиатуры, не пытайтесь направить в него $buttons_twice.

      private function startBot($chat_id, $data)<br />
          {<br />
              // ...<br />
              $buttons_first = [<br />
                  [<br />
                      $this-&gt;buildKeyboardButton(&quot;Кабинет&quot;),<br />
                      $this-&gt;buildKeyboardButton(&quot;Помощь&quot;),<br />
                  ],<br />
                  [<br />
                      $this-&gt;buildKeyboardButton(&quot;Кабинет 1&quot;),<br />
                      $this-&gt;buildKeyboardButton(&quot;Помощь 1&quot;),<br />
                  ],<br />
              ];<br />
      <br />
              // или <br />
      <br />
              // $buttons_first[0] = [<br />
              //     $this->buildKeyboardButton("Кабинет"),<br />
              //      $this->buildKeyboardButton("Помощь"),<br />
              //  ];<br />
              //  $buttons_first[1] = [<br />
              //      $this->buildKeyboardButton("Кабинет 1"),<br />
              //      $this->buildKeyboardButton("Помощь 1"),<br />
              //  ];<br />
      <br />
              // отправляем первый набор кнопок<br />
              $this-&gt;sendMessage($chat_id, &quot;...&quot;, $buttons_first, true);<br />
              // ...<br />
          }

      Обработать команды из клавиатуры, можно в методе router
      private function router($data) {<br />
          // ...<br />
          // если это пришел старт бота<br />
          if ($text == "/start") {<br />
              $this->startBot($chat_id, $data);<br />
          } elseif ($text == "Кабинет") {<br />
              // либо вывести информацию здесь, либо вызвать метод который отработает по сценарию<br />
              $this->sendMessage($chat_id, "Выводим кабинет");<br />
              // $this->showCabinet($chat_id, $data); <br />
          // выводим страницу только админу<br />
          } elseif ($text == "/admin" && $this->isAdmin($chat_id)) {<br />
          // ...<br />
      }<br />
      

      Метод showCabinet для примера выше
      private function showCabinet($chat_id, $data) {<br />
          $this->sendMessage($chat_id, "Выводим кабинет");<br />
      }
      iMakeBots 28.06.2019 в 09:11
  • Вставил в начало
    между
    if (array_key_exists(&quot;text&quot;, $data['message'])) {
    A M 27.06.2019 в 23:59
    • Если вы вставили чужой код, то у вас однозначно не сработает. В том примере, что вы привели выше - скорее всего используют какую-то библиотеку, и в переменной $telegram лежит объект для работы с Телеграм АПИ.

      Соответственно этих переменных в приложении из статьи не объявляли и будет ошибка.
      iMakeBots 28.06.2019 в 09:30
  • Результата соответственно нет. Можно вас попросить написать 2 рабочих с ботом магазина примера (шаблона)? Один с отправкой пользователю документа после нажатия на кнопку, а второй пример с переходом в другой чат после нажатия на кнопку пользователем? Заранее спасибо
    A M 28.06.2019 в 00:00
    • // ...<br />
      $buttons[] = [<br />
          $this-&gt;buildInlineKeyBoardButton('Другой чат', '', 'https://t.me/imakebots'),<br />
          $this-&gt;buildInlineKeyBoardButton('Документ', 'sendDocToUser_0')<br />
      ];<br />
      $this-&gt;sendMessage($chat_id, 'Выберите действие', $buttons);<br />
      // ...

      private function sendDocToUser($data) {<br />
          // отсылаем уведомление<br />
          $this-&gt;notice($data['id']);<br />
          // отсылаем документ<br />
          $this-&gt;botApiQuery('sendDocument', [<br />
              'chat_id' =&gt; $this-&gt;getChatId($data),<br />
              'document' =&gt; 'http://www.pdf995.com/samples/pdf.pdf'<br />
          ]);<br />
      }<br />
      
      iMakeBots 28.06.2019 в 09:44
      • Спасибо вам в очередной раз за развернутые ответы. я вставил ваш код выше и прописал его к $buttons_first клавиатуре, результатов ноль. Я про эти кнопки писал.
        http://skrinshoter.ru/s/280619/wDfue06F?a
        как видно из скриншота, кнопки не понимают команды, если не сложно можно решение этой проблемы?
        Касательно обработчика для оплаты наличными, спасибо большое таймер пропал, но я имел ввиду немного другое ,
        <br />
        // Статья 4 - Оплата в Телеграмм<br />
        <br />
            /********************************************/<br />
        <br />
                    if(!$orderRaw['status']) {<br />
                        // готовим кнопку для перехода в Яндекс.Деньги<br />
                        $url = $this-&gt;getUrl($total, $user_id, $orderRaw['id']);<br />
                        $buttons[] = [ $this-&gt;buildInlineKeyBoardButton('Оплатить через Яндекс.Деньги', '', $url),<br />
        				$this-&gt;buildInlineKeyBoardButton('Оплата Наличными', 'getNal_' . $orderRaw['id']),<br />
        				$this-&gt;buildInlineKeyBoardButton('При получении  Сканирование QR-Кода Яндекс.Деньги', 'getQrYandex_' . $orderRaw['id']),<br />
        				];<br />
                    } else {<br />
                        // если заказ оплачен то уведомляем<br />
                        $text .= &quot;n&lt;b&gt;Заказ оплачен&lt;/b&gt;n&quot;;<br />
                    }<br />
        <br />
            /********************************************/<br />
        
        сейчас у вас как видно из скриншота появляется всплывающее окошко,
        http://skrinshoter.ru/s/280619/Zt0fYnAP?a
        я имел ввиду что после клика по инлайнкнопкам "Оплата Наличными" и тд., пользователь получает текстовое уведомление в чат по аналогии с вашим способом оплаты по умолчанию через яндекс деньги и текущий заказ после клика на "Оплата Наличными" был закрыт
        // если заказ оплачен то уведомляем<br />
                        $text .= &quot;n&lt;b&gt;Заказ оплачен&lt;/b&gt;n&quot;;
        Сейчас просто всплывает окошко и непонятно, прошел заказ, не прошел заказ, он просто висит на шаге выбора оплаты с кнопками туда/сюда - ни админ, ни пользователь ничего не получают, это так и должно быть?
        A M 28.06.2019 в 21:57
        • Обработку кнопок (для каждой) в приложении из статьи нужно делать в методе
          private function router($data)
          Я приводил пример выше постом для кнопки клавиатуры "Кабинет", вам нужно просто добавить свои условия:
          } elseif ($text == &quot;ℹ️Кнопка 1&quot;) {<br />
          } elseif ($text == &quot;💬Чат с поддержкой&quot;) {
          Фразы в условиях должны быть один в один как на кнопках.

          Да, уведомление я привел как пример, вместо него вы можете делать, что угодно, если вы хотите вывести текстовое сообщение просто его отправьте:

          public function getNal($data)<br />
              {<br />
                 // высылаем уведомление без сообщения, чтобы <br />
                 // Телеграм понял что мы получили команду от кнопки<br />
                 $this-&gt;notice($data['id']);<br />
                 // отправляем сообщение<br />
                 $chat_id = $this-&gt;getChatId($data);<br />
                 $this-&gt;sendMessage($chat_id, &quot;Заказ оплачен&quot;);<br />
              }
          iMakeBots 28.06.2019 в 22:14
          • Здравствуйте, спасибо за ответы. Да, кнопки работают, все стало выводиться, но возникла следующая ситуация. cм код с пастербин (я решил не засорять вам ресурс лишним кодом, буду на пастербин выкладывать) и скриншоты
            Если все оставить как в вашем случае ничего не меняя
            private function sendDocToUser($data) {<br />
                // отсылаем уведомление<br />
                $this-&gt;notice($data['id']);<br />
                // отсылаем документ<br />
                $this-&gt;botApiQuery('sendDocument', [<br />
                    'chat_id' =&gt; $this-&gt;getChatId($data),<br />
                    'document' =&gt; 'http://www.pdf995.com/samples/pdf.pdf'<br />
                ]);<br />
            }
            то все выводиться нормально
            http://skrinshoter.ru/s/290619/EOfeyAIw?a
            , но если подставить свои данные
            https://pastebin.com/yE2jR7L9
            https://pastebin.com/xLZ7c5wa
            то уже отображается по другому
            http://skrinshoter.ru/s/290619/1qRO2KuS?a
            также ссылки на документ автоматически стали выводиться при создании заказа сами по себе
            http://skrinshoter.ru/s/290619/5mMHyNyl?a
            как решить эти моменты? и как сделать переход в другой чат по клику на кнопку (сейчас он присылает ссылку на чат, если нажать кнопку).

            и опять вопрос насчет метода оплаты
            // Статья 4 - Оплата в Телеграмм<br />
            <br />
                /********************************************/<br />
            <br />
                        if(!$orderRaw['status']) {<br />
                            // готовим кнопку для перехода в Яндекс.Деньги<br />
                            $url = $this-&gt;getUrl($total, $user_id, $orderRaw['id']);<br />
                            $buttons[] = [ $this-&gt;buildInlineKeyBoardButton('Оплатить через Яндекс.Деньги', '', $url),<br />
            				$this-&gt;buildInlineKeyBoardButton('Оплата Наличными', 'getNal_' . $orderRaw['id']),<br />
            				$this-&gt;buildInlineKeyBoardButton('При получении  Сканирование QR-Кода Яндекс.Деньги', 'getQrYandex_' . $orderRaw['id']),<br />
            				];<br />
                        } else {<br />
                            // если заказ оплачен то уведомляем<br />
                            $text .= &quot;n&lt;b&gt;Заказ оплачен&lt;/b&gt;n&quot;;<br />
                        }<br />
            <br />
                /********************************************/
            Спасибо, тоже все работает, но момент вот такой, как реализовать информирование админа (любое, простейшее) хоть в сам телеграм, хоть на почту, хоть еще куда), о том что заказ поступил? Потому что сейчас никаких уведомлений админу не поступает и не понятно есть заказ, нет заказа, существует он вообще. В случае с оплаты через яндекс деньги, реализованной вами по умолчанию, там хотя бы уведомление придет о тому, что поступил платеж на почту, а вообще в целом такие уведомления не приходят, а в случаях если пользователь делая заказ выбрал оплату наличными это очень критично, потому что это довольно казусная ситуация когда человек сидит и чего-то ждет, а о его заказе никто ни слуху ни духу как говориться. можно вариант решения этой незатейливой проблемы? Спасибо.
            A M 29.06.2019 в 20:01
            • Выкладывайте код здесь - это нормально, этот ресурс для этого и сделан, всяко удобнее читать здесь - чем по ссылкам бегать ))

              Обратите внимание на метод, которым я отправляю документ - sendDocument, а вы пытаетесь отправить его текстовым сообщением sendMessage, он вам ссылку текстом и присылает - все правильно отрабатывает.
                  $this-&gt;botApiQuery('sendDocument', [<br />
                      'chat_id' =&gt; $this-&gt;getChatId($data),<br />
                      'document' =&gt; 'http://www.pdf995.com/samples/pdf.pdf'<br />
                  ]);
              ======
              Ссылку по кнопке я приводил пример, посмотрите выше - где документ по кнопке прилетает.
              ======
              Уведомление админа можно, сделать в методе setReady
                  /** Оформляем заказ<br />
                   * @param $data<br />
                   */<br />
                  private function setReady($data)<br />
                  {<br />
                      // ...<br />
                              // удаляем из корзины<br />
                              $delBasket = $this-&gt;pdo-&gt;prepare(&quot;DELETE FROM bot_shop_basket WHERE user_id = :user_id&quot;);<br />
                              $delBasket-&gt;execute(['user_id' =&gt; $user_id]);<br />
              <br />
                              // уведомляем админа<br />
                              $this-&gt;sendMessage($this-&gt;admin, &quot;Новый заказ поступил - №&quot; . $parent_id);<br />
              <br />
                              // переадресовать в личный кабинет<br />
                              $this-&gt;notice($data['id']);<br />
                              $this-&gt;userLc($user_id, $data['message']['message_id']);<br />
                       // ...<br />
                  }
              iMakeBots 29.06.2019 в 20:16
  • Здравствуйте, не подскажете как добавить новые шаги при составлении заказа? Новые поля я уже добавил
    https://pastebin.com/v09tQiB4
    http://skrinshoter.ru/s/280619/Q92pXBLC?a
    И как сделать так чтоб каждая запись, присваивалась своему полю?
    потому что, сейчас написанное пользователем на этапе внесения адреса автоматически дублируется в другие поля
    http://skrinshoter.ru/s/280619/15Wbgunl?a
    а как сделать так чтоб после полей "телефон" и "адрес", можно было добавить к примеру поле "комментарий к заказу" (введите комментарий и тд.) следующим шагом и/или другие поля, свои поля (к примеру, поле1, поле2 и тд.)? Можно какой нибудь шаблон который можно копипастить заменяя "поле1" на свое какое нибудь поле? Спасибо.

            <br />
                        $text_ .= &quot;nТелефон: &quot; . $text;<br />
                        $text_ .= &quot;nnАдрес: &quot;;<br />
                        $text_ .= &quot;nnnНовое поле 1:&quot;;<br />
                        $text_ .= &quot;nnnnНовое поле 2:&quot;;<br />
                        $text_ .= &quot;nnnnnНовое поле 3:&quot;;<br />
                        $text_ .= &quot;nnnnnnНовое поле 4:&quot;;<br />
    
    я так понимаю что в данном случае лишнии n можно убрать? они как отступ выступают или как перенос на новую строку?

    Чтоб в бд добавить данные о платежных системах, достаточно импортировать данные код в таблицу?

    CREATE TABLE IF NOT EXISTS 'данные о платежных системах' (<br />
      'id' int(11) NOT NULL AUTO_INCREMENT,<br />
      'name' varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,<br />
      'getNal_' varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,<br />
    'getQrYandex_' varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,<br />
      PRIMARY KEY ('id')<br />
    ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;<br />
    
    A M 30.06.2019 в 18:39
    • Оформление заказа в приложение из статьи ограничено определенным количеством запросов данных, чтобы его расширить нужно дописывать логику. В том виде в котором логика сейчас выполнена - расширять не удобно, но можно.

      В других приложениях я использую логику в которой данные для оформления заказа берутся из модели, в ней в массиве указаны какие поля запрашивать, формат данных у полей, описание полей, обязательно к заполнению или нет и т.д. - и расширить форму заказа можно просто дополнив этот массив не нарушая работу логики - это даже делается самим клиентом через удобный веб-интерфейс.

      Для того, чтобы добавить обработку новых полей в приложении из статьи, вы можете по аналогии с предыдущими методами добавить свои, алгоритм используйте тот же:

      1. сначала идет запрос на ввод данных Экран "Укажите данные для нового поля 1"
      2. запись в бд пользователю, каким методом нужно обработать следующее сообщение "newField_1",
      3. когда пользователь отправит сообщение роутер проверит наличии записи и перенаправит в нужный метод
      3. метод newField обработает сообщение, запишит в бд заказа
      4. выведет запрос на ввод данных Экран "Укажите данные для нового поля 2"
      5. сменить запись в бд пользователю на "newField_2"
      6. и тд. ...

      Писать готовое решение не буду, для этого потребуется много времени.

      ======
      - Дублируются данные потому что у вас в переменной $text лежат одни и те же данные.
      - Лишние переносы строк, конечно лучше убрать.
      - getNal_ лучше сделайте tinyint(1) по default поставьте 0 (как не наличные), в случае если пользователь укажет за наличные то сменяйте на 1
      iMakeBots 01.07.2019 в 13:59
      • Здравствуйте, спасибо за ответы, в таком случае вы не могли бы меня корректировать если вам не сложно?
        Я правильно понимаю что сначала нужно проделать вот это?
        } elseif (preg_match(&quot;~^step_1_phone$~&quot;, $actionUser)) {<br />
                                // если ждем данные для добавления телефона<br />
                                $this-&gt;savePhoneUser($text, $data);<br />
                            } elseif (preg_match(&quot;~^step_2_adress$~&quot;, $actionUser)) {<br />
                                // если ждем данные для добавления адреса<br />
                                $this-&gt;saveAdressUser($text, $data);<br />
                            } elseif (preg_match(&quot;~^step_3_newfield1$~&quot;, $actionUser)) {<br />
                                // если ждем данные для добавления адреса<br />
                                $this-&gt;savenewfield1User($text, $data);<br />
                            } elseif (preg_match(&quot;~^step_4_newfield2$~&quot;, $actionUser)) {<br />
                                // если ждем данные для добавления адреса<br />
                                $this-&gt;savenewfield2User($text, $data);<br />
                            } elseif (preg_match(&quot;~^step_5_newfield3$~&quot;, $actionUser)) {<br />
                                // если ждем данные для добавления адреса<br />
                                $this-&gt;savenewfield3User($text, $data);<br />
                            } elseif (preg_match(&quot;~^step_6_newfield4$~&quot;, $actionUser)) {<br />
                                // если ждем данные для добавления адреса<br />
                                $this-&gt;savenewfield4User($text, $data);

        Затем 4 раза повторить данный код?
        private function insertnewfield1($user_id, $data)<br />
            {<br />
                $text = &quot;&lt;b&gt;Оформление заказа&lt;/b&gt;nn&quot;;<br />
                // сумма заказа<br />
                $text .= &quot;Сумма заказа: &quot; . $this-&gt;totalSumOrder($user_id) . &quot; рублей&quot;;<br />
                $text_ .= &quot;nТелефон: &quot; . $phone-&gt;fetch()['phone'];<br />
                $text_ .= &quot;nАдрес: &quot; . $adress-&gt;fetch()['adress'];<br />
                // инструкция<br />
                $text .= &quot;nnУкажите свой телефон в формате  79001234567:&quot;;<br />
                // отправляем данные<br />
                $this-&gt;botApiQuery(&quot;editMessageText&quot;, [<br />
                    'chat_id' =&gt; $user_id,<br />
                    'text' =&gt; $text,<br />
                    'message_id' =&gt; $this-&gt;getMessageId($data),<br />
                    'parse_mode' =&gt; 'html',<br />
                ]);<br />
                // глушим уведомление<br />
                $this-&gt;notice($data['id']);<br />
            }<br />
        

        Как быть на этом моменте? Как перейти в следующий шаг newfield1?
        private function saveAdressUser($text, $data)<br />
            {<br />
                $user_id = $this-&gt;getChatId($data);<br />
                // Достаем телефон<br />
                $phone = $this-&gt;pdo-&gt;prepare(&quot;SELECT phone FROM bot_shop_profile WHERE user_id = :user_id&quot;);<br />
                $phone-&gt;execute(['user_id' =&gt; $user_id]);<br />
        <br />
                if ($this-&gt;setActionUser(&quot;step_7_ready&quot;, $user_id)) {<br />
                    if ($this-&gt;setParamUser('adress', $text, $user_id)) {<br />
                        $text_ = &quot;&lt;b&gt;Оформление заказа&lt;/b&gt;nn&quot;;<br />
                        // сумма заказа<br />
                        $text_ .= &quot;Сумма заказа: &quot; . $this-&gt;totalSumOrder($user_id) . &quot; рублей&quot;;<br />
                        // телефон<br />
                        $text_ .= &quot;nТелефон: &quot; . $phone-&gt;fetch()['phone'];<br />
                        $text_ .= &quot;nАдрес для доставки: &quot; . $text;<br />
                        $buttons[][] = $this-&gt;buildInlineKeyBoardButton('✔ Готово', 'setReady_0');<br />
                    } else {<br />
                        $text_ = &quot;Ошибка попробуйте снова /start&quot;;<br />
                    }<br />
                } else {<br />
                    $text_ = &quot;Ошибка попробуйте еще раз&quot;;<br />
                }<br />
                // готовим данные<br />
                $data_send = [<br />
                    'chat_id' =&gt; $user_id,<br />
                    'text' =&gt; $text_,<br />
                    'parse_mode' =&gt; 'html',<br />
                ];<br />
                // если есть кнопки добавляем<br />
                if (is_array($buttons)) {<br />
                    $data_send['reply_markup'] = $this-&gt;buildInlineKeyBoard($buttons);<br />
                }<br />
                // отправляем запрос<br />
                $this-&gt;botApiQuery(&quot;sendMessage&quot;, $data_send);<br />
            }
        Это правильный код?
        private function saveReceiveName($user_id, $data)<br />
        	  {<br />
        		$user_id = $this->getChatId($data);<br />
        		// Достаем телефон<br />
                        $phone = $this->pdo->prepare("SELECT phone FROM bot_shop_profile WHERE user_id = :user_id");<br />
                        $phone->execute(['user_id' => $user_id]);<br />
        		// Достаем адрес<br />
                        $adress = $this->pdo->prepare("SELECT adress FROM bot_shop_profile WHERE user_id = :user_id");<br />
                        $adress->execute(['user_id' => $user_id]);<br />
                        if ($this->setActionUser("step_3_receivename", $user_id)) {<br />
        		    if ($this->setParamUser('receivename', $text, $user_id)) {<br />
        			 $text_ = "<b>Оформление заказа</b>\n\n";<br />
                                 // сумма заказа<br />
                                 $text_ .= "Сумма заказа: " . $this->totalSumOrder($user_id) . " рублей";<br />
                                 // телефон<br />
                                 $text_ .= "\nТелефон отправителя: " . $phone->fetch()['phone'];<br />
        			$text_ .= "\nАдрес отправителя: " . $adress->fetch()['adress'];<br />
        			$text_ .= "\nИмя получателя: " . $text;<br />
        		} else {<br />
                                $text_ = "Ошибка попробуйте снова /start";<br />
                        }<br />
                    } else {<br />
                        $text_ = "Ошибка попробуйте еще раз";<br />
                    }<br />
                } else {<br />
                    $text_ = "Ошибка в веденных данных, попробуйте еще раз.\n\nУкажите имя получателя в формате Имя и Фамилия:";<br />
                }<br />
                $this->botApiQuery("sendMessage", [<br />
                    'chat_id' => $user_id,<br />
                    'text' => $text_,<br />
                    'parse_mode' => 'html',<br />
                ]);<br />
        		// отправляем запрос<br />
                $this->botApiQuery("sendMessage", $data_send);<br />
        	  }
        A M 01.07.2019 в 17:45
        • private function saveAdressUser($text, $data) {<br />
              $user_id = $this-&gt;getChatId($data);<br />
              // Достаем телефон<br />
              $phone = $this-&gt;pdo-&gt;prepare(&quot;SELECT phone FROM bot_shop_profile WHERE user_id = :user_id&quot;);<br />
              $phone-&gt;execute(['user_id' =&gt; $user_id]);<br />
          <br />
              // !!!!!!!!!!!!!!!!!!<br />
              // устанавливаем пользователю следующий шаг ДЛЯ НОВОГО ПОЛЯ 1<br />
              if ($this-&gt;setActionUser(&quot;step_3_newfield1&quot;, $user_id)) {<br />
          <br />
          <br />
              	// если удалось сохранить адрес<br />
                  if ($this-&gt;setParamUser('adress', $text, $user_id)) {<br />
                      // готовим текст сообщения<br />
                      $text_ = &quot;&lt;b&gt;Оформление заказа&lt;/b&gt;nn&quot;;<br />
                      // сумма заказа<br />
                      $text_ .= &quot;Сумма заказа: &quot; . $this-&gt;totalSumOrder($user_id) . &quot; рублей&quot;;<br />
                      // телефон<br />
                      $text_ .= &quot;nТелефон: &quot; . $phone-&gt;fetch()['phone'];<br />
                      $text_ .= &quot;nАдрес для доставки: &quot; . $text;<br />
          <br />
                      // !!!!!!!!!!!!!!!!!!<br />
                      // кнопки здесь не нужны, нужно сделать запрос данных<br />
                      // &gt;&gt; Затем 4 раза повторить данный код?<br />
                      // нет того кода повторять не надо - все запросы нужно делать после проверки предудущих значений<br />
                      // !!!!!!!!!!!!!!!!!!<br />
          <br />
                      $text_ .= &quot;nnУкажите данные для нового поля 1&quot;;<br />
                      // $buttons[][] = $this-&gt;buildInlineKeyBoardButton('✔ Готово', 'setReady_0');<br />
          <br />
          <br />
                  } else {<br />
                      $text_ = &quot;Ошибка попробуйте снова /start&quot;;<br />
              	}<br />
              } else {<br />
                      $text_ = &quot;Ошибка попробуйте еще раз&quot;;<br />
              }<br />
              // готовим данные<br />
              $data_send = [<br />
                  'chat_id' =&gt; $user_id,<br />
                  'text' =&gt; $text_,<br />
                  'parse_mode' =&gt; 'html',<br />
              ];<br />
              // если есть кнопки добавляем<br />
              if (is_array($buttons)) {<br />
                  $data_send['reply_markup'] = $this-&gt;buildInlineKeyBoard($buttons);<br />
              }<br />
              // отправляем запрос<br />
              $this-&gt;botApiQuery(&quot;sendMessage&quot;, $data_send);<br />
          }



          >> Это правильный код?


          private function step_3_newfield1($text, $data) {<br />
              $user_id = $this-&gt;getChatId($data);<br />
              // Достаем данные<br />
              $data = $this-&gt;pdo-&gt;prepare(&quot;SELECT phone, adress FROM bot_shop_profile WHERE user_id = :user_id&quot;);<br />
              $data-&gt;execute(['user_id' =&gt; $user_id]);<br />
              $data_ = $data-&gt;fetch();<br />
          <br />
              if ($this-&gt;setActionUser(&quot;step_4_newfield2&quot;, $user_id)) {<br />
                      if ($this-&gt;setParamUser('receivename', $text, $user_id)) {<br />
                          $text_ = &quot;Оформление заказаnn&quot;;<br />
                          // сумма заказа<br />
                          $text_ .= &quot;Сумма заказа: &quot; . $this-&gt;totalSumOrder($user_id) . &quot; рублей&quot;;<br />
                          // телефон<br />
                          $text_ .= &quot;nТелефон отправителя: &quot; . $data_['phone'];<br />
                          // адрес<br />
                          $text_ .= &quot;nАдрес отправителя: &quot; . $data_['adress'];<br />
                          // присланное значение для поля 1<br />
                          $text_ .= &quot;nИмя получателя: &quot; . $text;<br />
          <br />
                          // запрос данных для поля 2<br />
                          $text_ .= &quot;nnУкажите данные для нового поля 2&quot;;<br />
          <br />
                      } else {<br />
                          $text_ = &quot;Ошибка попробуйте снова /start&quot;;<br />
                  }<br />
              } else {<br />
                  $text_ = &quot;Ошибка попробуйте еще раз&quot;;<br />
              }<br />
              <br />
              $this-&gt;botApiQuery(&quot;sendMessage&quot;, [<br />
                  'chat_id' =&gt; $user_id,<br />
                  'text' =&gt; $text_,<br />
                  'parse_mode' =&gt; 'html',<br />
              ]);<br />
          }
          iMakeBots 02.07.2019 в 08:42
          • Здравствуйте, огромное спасибо. Вы не могли бы посмотреть код (прилично) на ошибки (правильно ли вообще делаю), когда у вас будет свободное время и настроение (не горит), поля добавил бот не стартует. Я просто заметил что вы с утра все время отвечаете, как то неудобно вас отвлекать перед работой или во время работы.
            https://pastebin.com/1eAW77aF
            A M 03.07.2019 в 18:18
            • Для начала очень даже хорошо разобрались, немного видимо запутались в логике - ну это потому что получилось много дублирующего кода, в будущем нужно будет уходить от этого - придет со временем.

              Подправил без тестирования. Скинете весь код бота (через бот обратной связи) - попробую отладить.

              https://pastebin.com/Gz9PCwG0
              iMakeBots 04.07.2019 в 11:41
          • Здравствуйте, отправил вам бота, выложите его для всех если хотите как продолжение статьи
            A M 05.07.2019 в 15:47
            • Протестил, исправил пару ошибок - работает.
              iMakeBots 06.07.2019 в 19:54
            • Здравствуйте, у вас удалось довести бота до рабочей версии? У меня проблема, с ботом при заказе не отображает id или наименование заказа. Если есть возможность, поделится рабочей версией бота, был бы очень благодарен. Телеграмм @desctr
              Алексей Никифорович 28.01.2020 в 20:24
  • Отличный Бот, спасибо!.

    Выложите кто нибудь этого же бота но с уже рабочей функцией ОПЛАТА наликом и уведомлением админа о поступлении заказа.
    спасибо!
    Грачик Абдулошвили 21.04.2020 в 12:46