Опубликовано 12 комментариев

Telegram bot для WooCommerce. Часть 3.

Продолжаем писать Telegram bot для Woocommerce. В первой и второй части мы сделали каркас плагина, зарегистрировали бота, написали хуки для обработки регистраций чатов и многое другое. В этой части мы создадим метод, который будет отправлять сообщения о новых заказах в Телеграм. Получателями будут все те, кто подписан на нашего бота. Итак продолжим.

Каждый админ или менеджер магазина должен увидеть на странице плагина примерно вот такую картинку

Страница плагина WooCommerce Telegram
Страница плагина WooCommerce Telegram

Здесь мы видим токен и видим наш персональный ИД чата с ботом телеграм. Если у Вас что-то не так, то проверьте токен и название API метода в коде плагина. Давайте напишем метод который будет отправлять данные заказа на телеграмы всех админов и менеджеров кто зарегистрировался на странице плагина. Итак добавим немного кода в наш класс Telegram в файле include/telegram.php

add_action('woocommerce_checkout_order_processed',
  [$this, 'SendOrderToTelegram'], 10, 3);

public function SendOrderToTelegram($order_id, $posted, $order)
{
    $text = ' Заказ № ' . $order->get_order_number() . ' с сайта ' . get_site_url() . PHP_EOL;
    $text .= 'Клиент :' . $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() . PHP_EOL;
    $text .= 'Телефон :' . $order->get_billing_phone() . PHP_EOL;
    $text .= 'Email :' . $order->get_billing_email() . PHP_EOL;
    $text .= 'Сумма заказа :' . $order->get_total() . PHP_EOL;

    $text  .= 'Содержимое заказа :' . PHP_EOL;
    $items = $order->get_items();

    foreach ($items as $item) {
        $product = $item->get_product();
        $qty     = $item->get_quantity() ? $item->get_quantity() : 1;
        $price   = wc_format_localized_price($item->get_total() / $qty);
        $text    .= 'Товар :' . $product->get_name() . ' Кол-во :' . $qty . ' Цена :' . $price;
    }

    foreach ($this->getTelegramUsers() as $user) {
        $chatId = get_user_meta($user->ID, 'telegram', true);
        $this->sendMessageToTelegram($text, $chatId, $this->token);
    }
}

private function getTelegramUsers()
{
    return get_users([
      'meta_key' => 'telegram',
    ]);
}

Мы добавили в конструктор класса вызов action woocommerce_checkout_order_processed. Поместили в него название нашего метода SendOrderToTelegram. Обратите внимание, что мы указали число аргументов которое будет доступно в методе. В самом методе мы объявляем переменную $text в которую будем добавлять наше сообщение. Пробегаемся по позициям заказа и собираем минимальные данные которые хотим отправить в наш Telegram bot для WooCommerce.

Дальше нам нужно получить пользователей у которых заполнен мета тэг telegram . За это будет отвечать наш приватный метод getTelegramUsers. Воспользуемся встроенным в WordPress методом get_users. В качестве аргументов этот метод принимает в том числе и ключ meta_key. Это отберет только тех пользователей у которых в мета данных есть этот ключ.

Полученный от метода getTelegramUsers массив с данными мы переберем , и получим значение chatId из поля telegram. Теперь у нас есть все данные, чтобы отправить сообщение через нашего бота нужным пользователям. Воспользуемся ранее написанным методом sendMessageToTelegram и скормим ему $text $chatId и $token.

Итог.

Вот и все . Теперь наш Telegram bot для WooCommerce умеет отправлять данные заказа нужным пользователям системы. И выглядит это примерно так:

Пример оповещения о заказе отправленным Telegram
Пример оповещения о заказе

Я не стал заострять внимание на различных тонкостях, переводах плагина на другие языки и прочих мелочах. Я постарался донести основные вехи создания написания плагина WooCommerce для Telegram. Желающие могут модифицировать этот плагин под свои нужды, добавить различный функционал и тд.

В итоге наш код приобрел следующий вид.

<?php

if (!defined('ABSPATH')) {
    exit;
}

class Telegram extends WC_Integration
{

    const API_TELEGRAM = 'https://api.telegram.org/bot';

    public $registerWebhook;

    public $token;

    public $chatId;

    public $userId;

    public function __construct()
    {
        $current_user = wp_get_current_user();
        $this->userId = $current_user->ID;

        $this->id                 = "woo-telegram";
        $this->method_title       = "Телеграм бот для WooCommerce";
        $this->method_description = "Плагин связывает WooCommerce c Telegram ботом.";
        $this->init_form_fields();
        $this->init_settings();

        $this->token  = $this->settings['token'];
        $this->chatId = get_user_meta($this->userId, 'telegram', true);
        $this->registerWebhook = $this->checkExistsWebhook($this->token);

        add_action('woocommerce_api_woo-telegram',
          [$this, 'WooTelegramResponse']);
        add_action("woocommerce_update_options_integration_" . $this->id,
          [$this, "process_admin_options"]);
        add_action('woocommerce_checkout_order_processed',
          [$this, 'SendOrderToTelegram'], 10, 3);
    }

    public function init_form_fields()
    {
        $this->form_fields = [
          "token" => [
            "title"       => "Токен Telegram",
            "description" => "Введите token полученный от BotFather",
            "type"        => "text",
            "class"       => "tm-token",
            "desc_tip"    => true,
            "default"     => get_option("token"),
          ],
        ];
    }

    public function process_admin_options()
    {
        $result      = parent::process_admin_options();
        $this->token = $this->settings['token'];
        $this->setTelegramWebhook();
        $this->registerWebhook = $this->checkExistsWebhook($this->token);
        return $result;
    }

    function admin_options()
    {
        $hash = md5('telegram' . $this->userId);

        echo '<table class="form-table">';
        echo $this->generate_settings_html($this->form_fields, false);
        echo '</table>';
        if (!$this->registerWebhook) {
            echo '<a href="#" class="button-secondary" id="webhook">WebHook не зарегистрирован</a>';
        }
        if (empty($this->chatId)) {
            echo "<p> Найдите нашего бота @woo_telegram_bot нажмите Начать и напишите ему команду /key=$this->userId&auth=$hash долждитесь ответа бота и перегрузите эту страницу </p>";
        } else {
            echo "<p>Номер telegram чата : $this->chatId </p>";
        }
        $this->display_errors();
    }

    public function validate_text_field($key, $value)
    {
        if ($key == 'token') {
            if (!$this->checkToken($value)) {
                $this->add_error('Токен не существует');
            }
        }
        return parent::validate_text_field($key, $value);
    }

    private function setTelegramWebhook()
    {
        $logger = wc_get_logger();
        $url    = self::API_TELEGRAM . $this->token . '/setWebhook';
        $logger->info(wc_print_r($url, true));
        $args     = [
          'timeout'     => 5,
          'redirection' => 1,
          'httpversion' => '1.0',
          'blocking'    => true,
          'headers'     => ['Content-Type' => 'application/x-www-form-urlencoded'],
          'body'        => ['url' => home_url('/?wc-api=woo-telegram')],
        ];
        $response = wp_remote_post($url, $args);
        if (is_wp_error($response)) {
            $error_message = $response->get_error_message();
            $logger->info(wc_print_r($error_message, true));
        }
    }

    private function checkExistsWebhook(string $token)
    {
        $logger = wc_get_logger();
        $url    = self::API_TELEGRAM . $token . '/getWebhookInfo';
        $logger->info(wc_print_r($url, true));
        $response = wp_remote_get($url);
        $body     = wp_remote_retrieve_body($response);
        if (!empty($body)) {
            try {
                $data = json_decode($body, true);
                if (!empty($data['result']['url'])) {
                    return true;
                }
            } catch (Exception $e) {
            }
        }
        return false;
    }

    private function checkToken(string $token)
    {
        $url      = self::API_TELEGRAM . $token . '/getMe';
        $response = wp_remote_get($url);
        $body     = wp_remote_retrieve_body($response);
        if (!empty($body)) {
            try {
                $data = json_decode($body, true);
                if (!empty($data['result']['username'])) {
                    return true;
                }
            } catch (Exception $e) {
            }
        }
        return false;
    }

    public function WooTelegramResponse()
    {
        global $woocommerce;
        $data   = file_get_contents("php://input");
        $logger = wc_get_logger();
        try {
            $result = $this->decodePost($data);
            $userId = $this->parseText($result['text']);
            if (update_user_meta($userId, 'telegram', $result['chatId'])) {
                $eol  = PHP_EOL;
                $text = 'Добро пожаловать в WooCommerce.' . $eol;
                $text .= 'На странице плагина Вы должны увидеть номер Вашего чата ' . $result['chatId'] . $eol;
                $text .= 'Спасибо !';
                $this->sendMessageToTelegram($text, $result['chatId'],
                  $this->token);
            } else {
                if ($chatId = get_user_meta($userId, 'telegram', true)) {
                    $text = 'Вы уже зарегистрированы в WooCommerce.' . PHP_EOL;
                    $text .= 'Спасибо за то, что Вы с нами';
                    $this->sendMessageToTelegram($text, $chatId, $this->token);
                }
            }
        } catch (Exception $e) {
            $logger->info(wc_print_r($e->getMessage(), true));
        }
    }

    /**
     * @param string $text
     *
     * @return bool|mixed
     * @throws \Exception
     */
    private function parseText(string $text)
    {
        $input = [];
        parse_str($text, $input);
        $userId = empty($input['key']) ? false : $input['key'];
        $hash   = empty($input['auth']) ? false : $input['auth'];
        if ($userId && $hash && $hash == md5('telegram' . $userId)) {
            return $userId;
        }
        throw new Exception('Не найден пользователь или не совпал секрет !');
    }

    /**
     * @param string $post
     *
     * @return array
     * @throws \Exception
     */
    private function decodePost(string $post): array
    {
        $data   = json_decode($post, true);
        $text   = empty($data['message']['text']) ? false : $data['message']['text'];
        $text   = substr($text, 1);
        $chatId = empty($data['message']['chat']['id']) ? false : $data['message']['chat']['id'];
        if ($text && $chatId) {
            return [
              'text'   => $text,
              'chatId' => $chatId,
            ];
        }
        throw new Exception('Не хватает аргументов text или chatId');
    }


    public function sendMessageToTelegram(
      string $text,
      string $chatId,
      string $token
    ): void {
        $url      = self::API_TELEGRAM . $token . '/sendMessage';
        $args     = [
          'timeout'     => 5,
          'redirection' => 1,
          'httpversion' => '1.0',
          'blocking'    => true,
          'headers'     => ['Content-Type' => 'application/x-www-form-urlencoded'],
          'body'        => ['text' => $text, 'chat_id' => $chatId],
        ];
        $response = wp_remote_post($url, $args);
        $logger   = wc_get_logger();
        if (is_wp_error($response)) {
            $error_message = $response->get_error_message();
            $logger->info(wc_print_r($error_message, true));
        }
    }

    public function SendOrderToTelegram($order_id, $posted, $order)
    {
        $text = ' Заказ № ' . $order->get_order_number() . ' с сайта ' . get_site_url() . PHP_EOL;
        $text .= 'Клиент :' . $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() . PHP_EOL;
        $text .= 'Телефон :' . $order->get_billing_phone() . PHP_EOL;
        $text .= 'Email :' . $order->get_billing_email() . PHP_EOL;
        $text .= 'Сумма заказа :' . $order->get_total() . PHP_EOL;

        $text  .= 'Содержимое заказа :' . PHP_EOL;
        $items = $order->get_items();

        foreach ($items as $item) {
            $product = $item->get_product();
            $qty     = $item->get_quantity() ? $item->get_quantity() : 1;
            $price   = wc_format_localized_price($item->get_total() / $qty);
            $text    .= 'Товар :' . $product->get_name() . ' Кол-во :' . $qty . ' Цена :' . $price;
        }

        foreach ($this->getTelegramUsers() as $user) {
            $chatId = get_user_meta($user->ID, 'telegram', true);
            $this->sendMessageToTelegram($text, $chatId, $this->token);
        }
    }

    private function getTelegramUsers()
    {
        return get_users([
          'meta_key' => 'telegram',
        ]);
    }

}

12 комментариев к “Telegram bot для WooCommerce. Часть 3.

  1. Подскажите ,а что это за имя ‘telegram’ get_user_meta($user->ID, ‘telegram’, true); Я начинающий разраотчик и в первый раз взялся за расширение функционала в WordPress.Прописал код как у вас ,но не понимаю какие id проставлять .Ничего из-за этого не не работает.Бо на запрос /key=1&auth=d91b733421e4c00a432440470829a693 не отвечает…

    1. $this->chatId = get_user_meta($this->userId, ‘telegram’, true);
      $this->chatId это переменная класса в которой мы храним ИД чата
      get_user_meta функция обращения к метаданным пользователя принимает ИД пользователя и имя поля
      таким образом мы считываем из БД ИД чата и присваиваем его переменной класса

  2. Добрый день мне пишет что (WebHook не зарегистрирован), я начинающий разраотчик
    и нет опыта но хочу понять как это работает

    1. Добрый день ! смотрите логи, что куда отправлялось.

  3. День добрый. Создал бота. Установил плагин. Получил код. Все зарегистрировалось, а вот как и где прописать у пользователя никак не пойму. Можно получить инструкцию на пальцах?) Спасибо

    1. Добрый день , извините, но я не занимаюсь написанием инструкций и предоставил код написанного мной плагина «как есть». Почитайте документацию Вордпрес.

  4. Плагин установился нормально и подключился к телеге тоже. Но!
    1. Статус заказов переводится на «на удержание»
    2. Информация о заказах не приходит на почту
    3. При нажатии на кнопку оформить заказ ничего не происходит, но заказ появляется в админке

    Как сделать так что бы в телеграм отправлялась инфа без затрагивания другого функционала?

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

  5. Добрый день! Подскажите, а бот @woo_telegram_bot работает? не могу дождаться ответа для регистрации чата.

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

  6. Подскажите, а @woo_telegram_bot не работает? он не принимает ключ и не реагирует ни на одну из команд(

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *