Опубликовано 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',
        ]);
    }

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

WooCommerce и Телеграм. Часть 2.

Итак продолжим писать наш плагин для WooCommerce и Телеграм. В первой части мы написали каркас плагина, зарегистрировали его в списке плагинов и добавили в интеграции WooCommerce.

Создаем бота в Telegram.

Теперь давайте создадим нашего бота. Для этого необходимо в Telegram найти отца всех ботов @BotFather и дать ему команду /newbot.

Переписка с BotFather
Переписка с BotFather

Добавляем поля в наш плагин.

Примерно в таком ключе пройдет Ваше общение с @BotFather в результате которого Вы получите token. Теперь этот токен необходимо сохранить в нашем плагине. Этим токеном мы будем подписывать наши сообщения боту. Давайте добавим наше первое поле в настройку плагина. После добавления наш класс Telegram в файле includes/telegram.php будет выглядеть так :

    public function __construct()
    {
        $this->id = "woo-telegram";
        $this->method_title = "Телеграм бот для WooCommerce";
        $this->method_description = "Плагин связывает WooCommerce c Telegram ботом.";
        $this->init_form_fields();
        $this->init_form_fields();
        $this->token = $this->settings['token'];
        add_action( "woocommerce_update_options_integration_" . $this->id, array( $this, "process_admin_options" ) );
    }

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

Мы добавили новый метод init_form_fileds в котором описали настройку необходимых нам полей , название, описание, тип, также добавили опцию по умолчанию . После того как мы сохраним наши настройки то заново зайдем на эту страницу и в это поле автоматически подставится сохраненное значение. Дальше мы определяем переменную token нашего класса Telegram и заполняем ее значением настройки ‘token’. После этого добавляем action «process_admin_options» который и сохранит все наши настройки в БД WooCommerce.

Теперь в Настройках WooCommerce у нас появилось новое поле Token которое мы можем заполнить и сохранить.

Токен для Telegram
Токен для Telegram

Пишем код плагина для связи с Telegram.

Давайте подумаем, что мы хотим получить от нашего бота ? Самое простое это получать уведомление когда кто-то из клиентов совершает заказ. Это и будет наше минимальное ТЗ.

Но сначала давайте подружим WooCommerce и Телеграм. Все общение с Телеграм может происходить двумя способами. 1) Мы сами запрашиваем обновления. 2) Телеграм присылает нам уведомления на указанный нами адрес. Мы выберем способ номер 2). Для этого у нашего сайта должен быть установлен SSL сертификат. Чтобы наш бот мог отправлять нам сообщения, нам надо получить ИД чата между телеграм ботом и нашим персональным telegram. Для этого мы будем отсылать нашему боту в телеграме команду вроде /key=ИД_юзера_на_сайте&auth=ХЭШ_для_защиты. Наш сайт будет принимать от бота ИД чата и прописывать его нужному юзеру.

Добавим в конструктор __construct() нашего класса вызов action, добавим сам метод WooTelegramResponse, пару вспомогательных методов и так же напишем метод отправки сообщений в Telegram.

add_action('woocommerce_api_woo-telegram',[$this,'WooTelegramResponse']);

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'])) {
            $text = 'Добро пожаловать в WooCommerce.' . PHP_EOL;
            $text .= 'На странице плагина Вы должны увидеть номер Вашего чата ' . $result['chatId'] . PHP_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));
    }
}

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('telegram2019' . $userId)){
        return $userId;
    }
    throw new 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      = 'https://api.telegram.org/bot' . $token . '/sendMessage';
    $args     = [
      'timeout'     => 5,
      '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));
    }
}

Добавив action woocommerce_api_woo-telegram мы тем самым задекларировали, что у нас по адресу https://наш_сайт.ru/?wc-api=woo-telegram будет находится наш обработчик WooTelegramResponse. Смысл этого обработчика в том, что он принимает данные с Telegram декодирует их, обрабатывает и записывает нужному юзеру ИД чата с Телеграм.

Добавляем необходимую информацию на страницу плагина.

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

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

Здесь мы смотрим на полученный ключ сравниваем его с тем что мы задали в методе init_form_fields и запускаем проверку с помощью метода checkToken, если метод вернет false то добавим ошибку в список ошибок и дальше отдадим управление родительскому методу. Опишем метод checkToken :

private function checkToken(string $token)
{
    $url      = 'https://api.telegram.org/bot' . $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;
}

В Telegram есть простой метод getMe который возвращает данные бота или 404 ошибку если бота с таким токеном не существует. Если мы получаем от Телеграм username в данных, то считаем что проверка прошла и возвращаем true, во всех остальных случаях возвращаем false.

Теперь у нас есть валидация Token напишем метод setTelegramWebhook который указывает Telegram куда отсылать webhook.

private function setTelegramWebhook()
{
    $logger = wc_get_logger();
    $url    = 'https://api.telegram.org/bot' . $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));
    }
}

Здесь мы подключаем встроенный в WooCommerce логер, чтобы фиксировать ошибки в логах. Телеграм метод setWebhook принимает несколько аргументов, но нам нужен только обязательный url в который мы прописываем наш адрес.

Проведем еще немного рефакторинга и добавим проверок в результате которых наш код примет примерно такой вид.

<?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"]);
    }

    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('telegram2019' . $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('telegram2019' . $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));
        }
    }

}

В итоге сейчас любой Админ или Менеджер магазина , может зайти на страницу плагина получить свой код регистрации в нашем телеграм боте. В следующей части интеграции WooCommerce и Телеграм мы напишем с Вами реализацию отправки заказа в нашему телеграм боту для отправки всем зарегистрированным пользователям.

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

Telegram бот для WooCommerce. Часть 1.

Этой статьей я открываю небольшой тренинг по написанию расширений для WooCommerce. Чтобы не писать зря мы сделаем Telegram бот для WooCommerce.

Bot father
Так выглядит папа ботов

Давно хотел написать Telegram бота для своего Интернет магазина.Я хочу получать всю информацию о заказах в свой telegram и может быть реализовать какие то функции по управлению заказами.

Вначале статьи приведу несколько ссылок на официальную документацию :

От слов к делу. Создадим начальный каркас нашего плагина. Откроем PHPStorm или любой другой привычный Вам редактор PHP , создадим файл woo-telegram.php и заполним его.

Вот так это может выглядеть :

/*
Plugin Name: WooCommerce -> Telegram
Description: Плагин интеграции  WooCommerce c Telegram.
*/
if ( ! defined('ABSPATH')) {
    exit;
}

if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
    function wc_telegram_add_integration($integrations) {
        global $woocommerce;

        if (is_object($woocommerce)) {
            include_once( 'includes/telegram.php' );
            $integrations[] = 'Telegram';
        }
        return $integrations;
    }

    add_filter('woocommerce_integrations', 'wc_telegram_add_integration', 10);
}

Вначале идут описание плагина, стандартные проверки на прямой вызов скрипта и существование плагина WooCommerce. Дальше пишем функцию wc_telegram_add_integration смысл которой создать нашу интеграцию в WooCommerce. В ней же определяем где будет лежать наш основной код (includes/telegram.php). Завершаем все стандартным фильтром add_filter который регистрирует нашу функцию в WooCommerce.

Вид плагина
Так выглядит наш плагин в общем списке плагинов

В принципе наш вновь созданный Telegram бот для WooCommerce уже имеет вид плагина. Разместив его в папке wp-content/plugins вы увидите его в списке плагинов и даже сможете активировать/деактивировать его.

Но в WooCommerce->Настройки->Интеграции Вы его пока не увидите. Исправим это и напишем минимальную обвязку плагина. Открываем наш файл includes/telegram.php и добавляем в него:

<?php

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

class Telegram extends WC_Integration
{
    public function __construct()
    {
        $this->id = "woo-telegram";
        $this->method_title = "Телеграм бот для WooCommerce";
        $this->method_description = "Плагин связывает WooCommerce c Telegram ботом.";
    }
}

В начале опять проверка на прямой запуск плагина, дальше мы создаем наш класс Telegram и наследуем его от встроенного класса WC_Integration. Все плагины для WooCommerce интеграций должны наследоваться от этого класса. Заполняем минимально необходимой информацией. Где id это идентификатор нашего класса, method_title — Наименование которое будет отображаться в настройках а method_description описание плагина. Оно также будет отображаться в настройках плагина.

Интеграции в Woocommerce
Интеграции в Woocommerce

Активируйте плагин , перейдите на страницу Интеграция настроек WooCommerce и Вы увидите , что наш плагин уже существует и отображает всю информацию которую мы в него пока заложили. На этом закончим первую часть, в следующей части мы зарегистрируем нашего бота в телеграм, добавим в него настроек и подумаем над минимальным функционалом.

Спасибо.