Опубликовано Оставить комментарий

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',
        ]);
    }

}

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

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