Подписаться

Messaging API

Содержание статьи:

Введение

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

- Отправить сообщение или ссылку на файл оператору;

- Выбрать, какой именно группе операторов будут отправляться сообщения;

- Передать оператору дополнительную информацию о пользователе;

- Подписаться на уведомления (webhook), посредством которых Messaging API информирует о сообщениях для пользователя, о доставке сообщений пользователя, о необходимости выбрать направление для сообщений, о закрытии обращения оператором.

Если представить реализацию в виде диаграммы последовательности, то самая простая интеграция будет выглядеть следующим образом: 

 

Базовые понятия

  • Посетитель (User/Пользователь) - обращается в чат для получения консультации или поддержки. Посетитель указывается в запросах посредством user_id. Идентификатор контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически. По одинаковым идентификаторам LiveTex группирует обращения посетителя. То есть, если в разные моменты времени состоялось несколько обращений от посетителя, для которого в эти разные моменты времени был установлен один и тот же user_id, то оператор в приложении, при получении очередного обращения от того же user_id, увидит все предыдущие обращения.

  • Оператор (Employee) - оператор организации, обрабатывающий входящие обращения посетителя в приложении LiveTex.

  • Бот (Bot) - автоматизированная система обработки обращений посетителя.

  • Направление маршрутизации (Destination) - под направлением, в котором отправляются полученные от посетителя сообщения, подразумеваются группы операторов созданные в рамках точки контакта, ключ для которой используется для работы с API. У каждой точки контакта обязательно есть минимум одна группа операторов.

  • Уведомления (Webhook-и) - посылаемые на указанный разработчиком адрес сообщения, которые содержат информацию о новых сообщениях и событиях.

 

Взаимодействующие компоненты

  • LiveTex - коммуникационная платформа.

  • Touchpoint Gateway - внешняя точка контакта пользователей с бизнесом. Например, бот в Telegram, Facebook или группа в VK, чат на сайте.

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

Используемый транспорт: HTTPS с TLS шифрованием (http не поддерживается). 

Протокол сериализации данных: JSON 

Доменное имя сервиса: https://messaging.livetex.ru/1.2/

 

Сценарии взаимодействия

1. Пользователь обращается к бизнесу

Touchpoint Gateway оповещает систему LiveTex о новом сообщении от посетителя вызовом методов sendText либо sendFile. Если это первое сообщение посетителя в данном обращении, LiveTex передаст в сторону Touchpoint Gateway оповещение SelectDestination, предлагая выбрать направление, куда будет отправлено сообщение.

2. Пользователь выбирает направление для маршрутизации обращения (группу операторов)

Touchpoint Gateway оповещает систему LiveTex о выборе направления посетителя (SelectDestination). Все отправленные до выбора направления сообщения сохраняются и будут отправлены после выбора направления.

Обратите внимание: мы не рекомендуем вызывать метод SelectDestination до того, как клиент написал первое сообщение!

3. Оператор отправил ответ посетителю

Система LiveTex оповещает Touchpoint Gateway о новом текстовом сообщении (TextMessage) или файле (FileMessage) от оператора. Если url для вебхуков не был задан к моменту ответа оператора, все сообщения от оператора будут сохранены и отправлены после вызова метода setWebhook, но не позднее чем через сутки после отправки сообщения оператором.

4. Закрытие обращения оператором

Оператор в приложении LiveTex Workspace закрывает вкладку с обращением. Система LiveTex посылает событие Closed, оповещая тем самым Touchpoint Gateway о закрытии обращения оператором. После этого событие направление маршрутизации считается не выбранным.

 

Авторизация

Авторизация осуществляется посредством передачи ключа авторизации в параметре каждого запроса:

curl -X POST https://messaging.livetex.ru/<version>/<method>?key=<authentication_key>

То есть отдельно перед выполнением всех запросов проходить авторизацию не требуется. На данный момент вместо version необходимо указать 1.2.

Ключ для авторизации можно получить в личном кабинете https://my.livetex.ru в разделе Настройки - Точки контакта. Нажмите на кнопку “Ключ доступа” напротив вашей точки контакта типа “Messaging API” и вы увидите и сможете скопировать ключ для авторизации, как на этих снимках:

 

 

Сложные типы данных

Destination

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

Имя Тип Обязательный Комментарий
destination_type String Да Тип направления маршрутизации. На данный момент доступно только значение “Department”.
destination_id String Да Идентификатор направления маршрутизации
name String Нет Имя направления маршрутизации. Для отображения пользователю
has_online Boolean Нет Проверка операторов в статусе "Доступен". При получении статуса через webhook, данное поле отсутствует
is_available Boolean Нет Проверка операторов доступных для распределения новых обращений, с учетом занятых слотов в соответствии с лимитами. При получении статуса через webhook, данное поле отсутствует

 

Employee

Оператор. Содержит информацию об операторе, обрабатывающем обращение.

Имя Тип Обязательный Комментарий
employee_id String Да Идентификатор оператора
first_name String Да Имя оператора
last_name String Нет Фамилия оператора
avatar_url String Нет Ссылка на аватар оператора
nick_name String Нет Псевдоним оператора

 

DestinationSelected

Cистемное сообщение, содержащее информацию о том, какое направление маршрутизации было выбрано.

Формат сообщения:

Имя Тип Обязательный Комментарий
type String Да Константа - "DestinationSelected"
id String Да Уникальный строковый идентификатор сообщения
destination_type String Да Тип направления маршрутизации. На данный момент доступно только значение: "Department"
destination_id String Да Идентификатор направления маршрутизации
webhook_key String Нет Аутентификационный ключ внешнего канала, отдается только в webhook. В истории отдаваться не будет
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
timestamp Long Да Время в формате Unix time

 

Методы Messaging API

Все запросы выполняются только по HTTPS.
Все запросы, подразумевающие наличие JSON в теле запроса, должны содержать следующие заголовки: - Content-Type: "application/json" - Content-Length: <количество байт в теле запроса>

sendText

Отправка текста в обращение от лица посетителя/пользователя. При получении сообщения оператором, создается оповещение MessageDelivered, которое через webhook-и отправляется клиенту

Пример

curl -X POST -d '{"user_id": "<user_id>", "text": "Hello World!"}' \ https://messaging.livetex.ru/<version>/sendText?key=<authentication_key>

Формат запроса

Имя Тип Обязательный Комментарий
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
text String Да Текстовое сообщение, отправленное посетителем/пользователем.

Формат ответа

Имя Тип Обязательный Комментарий
success Boolean Да Проверка успешности выполнения запроса
message_id String Да Идентификатор, присвоенный сообщению
timestamp Long Да Время в формате Unix time
error_message String Нет Описание ошибки
error_code Integer Нет Код ошибки. Для возможности интернационализации

 

sendFile

Отправка файла в обращение от лица посетителя/пользователя.

Пример

curl -X POST -d '{"user_id": "<user_id>", "url": "https://livetex.ru/wp-content/themes/livetex/ltx/img/Logo_LiveTex.png"}' \
  https://messaging.livetex.ru/<version>/sendFile?key=<authentication_key>

Формат запроса

Имя Тип Обязательный Комментарий
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
url String Да Ссылка для скачивания файла
file_name String Нет Имя файла для скачивания
size Long Нет Размер файла в байтах
comment String Нет Комментарий к переданному файлу

Формат ответа

Имя Тип Обязательный Комментарий
success Boolean Да Проверка успешности выполнения запроса
message_id String Да Идентификатор, присвоенный сообщению
timestamp Long Да Время в формате Unix time
error_message String Нет Описание ошибки
error_code Integer Нет Код ошибки. Для возможности интернационализации

 

selectDestination

Выбор посетителем, либо внутренней логикой конкретного TouchPoint Gateway направления маршрутизации обращения.
Согласно архитектуре у каждой точки контакта может быть несколько (но не менее одной) групп/отделов, в которые добавляются операторы. Обычно операторы таким образом разделяются на области компетенции, например, на отдел продаж и поддержку. Выбор направления, это по сути выбор группы операторов, в которую в итоге обратится пользователь за консультацией.


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

Выбор направления маршрутизации может происходить как реакция на оповещение о необходимости выбрать направление SelectDestination. Выбор направления действует до того момента, как оператор закроет обращение у себя в приложении.

Обратите внимание: Если оператора не закрыл обращение и завершил работу приложения, то выбранное направление будет продолжать действовать и все сообщения пользователя получит этот же оператор, но только по возвращению в приложение.

Пример

curl -X POST -d '{"user_id": "<user_id>", "destination_type": "Department", "destination_id": "<touchpoint_id>"}' \
   https://messaging.livetex.ru/<version>/selectDestination?key=<authentication_key>

Формат запроса

Имя Тип Обязательный Комментарий
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
destination_type String Да Тип направления маршрутизации. На данный момент доступно только значение “Department”.
destination_id String Да Идентификатор направления маршрутизации
name String Нет Имя посетителя. Если не значение передано, то оператор увидит "Гость" в качестве имени.
attributes Map<string, string=""></string,> Нет Набор кастомных атрибутов, которые будут переданы оператору
hidden_attributes Map<string, string=""></string,> Нет Набор кастомных атрибутов, которые НЕ будут переданы оператору. Атрибуты будут доступны только при просмотре истории обращений в личном кабинете и в выгрузке обращений.

Формат ответа

Имя Тип Обязательный Комментарий
success Boolean Да Проверка успешности выполнения запроса
error_message String Нет Описание ошибки
error_code Integer Нет Код ошибки. Для возможности интернационализации

 

getDestinations

Запрос доступных направлений для маршрутизации обращения

Пример

curl -X POST https://messaging.livetex.ru/<version>/getDestinations?key=<authentication_key>

Формат ответа

Имя Тип Обязательный Комментарий
success Boolean Да Проверка успешности выполнения запроса
destinations List[Destination] Да Направление маршрутизации обращения
error_message String Нет Описание ошибки
error_code Integer Нет Код ошибки. Для возможности интернационализации

 

getCurrentDestination

Запрос текущего направления маршрутизации

Пример

curl -X POST -d'{"user_id": "<user_id>"}' http://messaging.livetex.ru/<version>/getCurrentDestination?key=<authentication_key>

Формат запроса

Имя Тип Обязательный Комментарий
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.

Формат ответа

Имя Тип Обязательный Комментарий
success Boolean Да Проверка успешности выполнения запроса
destination Destination Нет Выбранное направление маршрутизации обращения. Отсутствие поля указывает на то, что направление не было выбрано.
error_message String Нет Описание ошибки
error_code Integer Нет

Код ошибки. Для возможности интернационализации

 

getHistory

Запрос истории обращения посетителем.

Пример

curl –X POST -d'{"user_id": "<user_id>", "limit": 10, "messageId": "<message_id>", "chunk": "After"}' \
  https://messaging.livetex.ru/<version>/getHistory?key=<authentication_key>

Формат запроса

Имя Тип Обязательный Комментарий
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
limit Long Нет Количество запрашиваемых сообщений. Ответ будет содержать количество сообщений не более указанного значения. Если значение не указано, то используется значение по умолчанию - 20.
message_id String Нет Если идентификатор не указан, то отдаются сообщения начиная с последнего созданного.
chunk String Нет Before - Отдавать сообщения созданные раньше, чем указанное.
After - Отдавать сообщения созданные позже, чем указанное.
По умолчанию Before.

Формат ответа

Имя Тип Обязательный Комментарий
success Boolean Да Проверка успешности выполнения запроса
messages List[Message] Да Список сообщений:MessageDelivered, TextMessage, FileMessage, SelectDestination, Closed, HoldMessage, DestinationSelected
error_message String Нет Описание ошибки
error_code Integer Нет Код ошибки. Для возможности интернационализации

 

Пример взаимодействия

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

1. Проверяем доступность направлений для маршрутизации запросе. Показываем посетителю статус бизнеса - доступен он для общения или нет. Если доступно несколько отделов, показываем посетителю выбор направления маршрутизации.

curl -X POST https://messaging.livetex.ru/<version>/getDestinations?key=<authentication_key>

Ответ:

{
  "destinations" : [{
    "destination_type" : "Department",
     "destination_id" : "54321",
     "name" : "Группа для Messaging API",
     "has_online" : true,
     "is_available": true
  }],
  "success" : true
}

2. Отправляем сообщение посетителя. Запрос:

curl -X POST -d '{
    "user_id": "123-321-123-321",
    "text": "Hello World!"
}' \ https://messaging.livetex.ru/<version>/sendText?key=<authentication_key>

Ответ:

{
    "message_id" : "1f00f857-6afe4-4618-c208-92ad57401abe",
    "timestamp" : 1502783446318,
    "success" : true
}

3. Указываем выбранное посетителем направление и указываем информацию о клиенте.
Запрос:

curl -X POST -d '{
    "user_id": "123-321-123-321",
    "destination_type" : "Department",
    "destination_id" : "54321",
    "name" : "Иванов Василий Петрович",
    "attributes" : {"Номер заказа" : "№98765"}
}' \ https://messaging.livetex.ru/<version>/selectDestination?key=<authentication_key>

Ответ:

{
    "success" : true
}

4. Отправим вдогонку файл. Запрос:

curl -X POST -d '{
        "user_id": "123-321-123-321",
        "url": "https://livetex.ru/wp-content/themes/livetex/ltx/img/Logo_LiveTex.png",
        "file_name": "LiveTex.png",
        "size": 5,
        "comment": "Вот, посмотрите, какой файл я приложил!"
}' \ https://messaging.livetex.ru/<version>/sendFile?key=<authentication_key>

Ответ:

{
    "message_id" : "ed31802b-7c7a-4948-abf5-ff2a34ec7b07",
    "timestamp" : 1502783544207,
    "success" : true
}

Готово, оператор получил сообщение и файл. Если на момент выполнения запросов оператор не был авторизован в приложении оператора, то он получит сообщение и файл после авторизации.

Чтобы получить ответ от оператора необходимо слушать уведомления от сервера. Уведомления доставляются посредством Webhooks, подключение которых мы рассмотрим далее.

 

Методы для работы с Webhook

setWebhook

Настройка оповещений. Оповещения будут присылаться по URL, указанному при конфигурации. В теле запроса будет присутствовать webHookKey, который позволит идентифицировать источник оповещения на принимающей стороне. В ответ на запрос сервер ожидает 200 HTTP ответ. Если ответ поступил в другом виде (например сервер недоступен), или настройки для получения оповещений не были заданы, или мы просто не получили ответ в течение 60 секунд, то сервер оповещений LiveTex повторяет запрос. LiveTex пробует доставить уведомление в течение 24 часов.

Подсказка: Проверить работу webhook-ов поможет, например, ресурс https://requestb.in/
На главной странице нажмите кнопку "Create a RequestBin" и на открывшейся странице скопируйте адрес из поля Bin URL. Скопированный URL установите для получения оповещений при помощи метода setWebhook. Когда от LiveTex начнут поступать оповещения, вы сможете их видеть, если пройдёте в браузере по этому же URL. Если никакие данные не поступили, то вы увидите только надпись "Ok" на белом фоне.
Обратите внимание, что выдаваемые данным ресурсом адреса доступны временно.

Пример

curl -X POST -d '{"url": "https://example.com/webhooks", "webhook_key": "zbb5y4PZ98R8fW4w", "webhook_event_types": [ "MessageDelivered", "TextMessage", "FileMessage", "SelectDestination", "Closed", "HoldMessage", "EmployeeAvailabilityChanged" ]}' \
  https://messaging.livetex.ru/<version>/setWebhook?key=<authentication_key>

Формат запроса

Имя Тип Обязательный Комментарий
url String Да URL, на который будут отсылаться WebHooks оповещения. Поддерживаются только HTTPS соединения. Самоподписанные сертификаты не поддерживаются
webhook_key String Да Ключ аутентификации передаваемый во всех сообщениях оповещения
webhook_event_types List[Message] Нет Параметр, в котором задается список оповещений, которые будет отправлять сервис. Доступные события: MessageDelivered, TextMessage, FileMessage, SelectDestination, Closed, HoldMessage, EmployeeAvailabilityChanged. Если параметр не указан, то сервис отправит все доступные оповещения

Формат ответа

Имя Тип Обязательный Комментарий
success Boolean Да Проверка успешности выполнения запроса
error_message String Нет Описание ошибки
error_code Integer Нет Код ошибки. Для возможности интернационализации

 

getWebhookSettings

Получить текущие настройки для webhook.

Пример

curl -X POST https://messaging.livetex.ru/<version>/getWebhookSettings?key=<authentication_key>

Формат ответа

Имя Тип Обязательный Комментарий
success Boolean Да Проверка успешности выполнения запроса
url String Да URL, по которому посылаются WebHooks оповещения. URL будет пустой, если WebHook не настроен
webhook_event_types List[Message] Да Список оповещений на которые подписались
error_message String Нет Описание ошибки
error_code Integer Нет Код ошибки. Для возможности интернационализации

 

Оповещения посредством Webhook

TextMessage

Оповещение о новом текстовом сообщении от оператора.

Формат оповещения:

Имя Тип Обязательный Комментарий
type String Да Константа - "TextMessage"
id String Да Уникальный строковый идентификатор сообщения
webhook_key String Нет Аутентификационный ключ внешнего канала, отдается только в webhook. В истории отдаваться не будет
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
employee Employee Да Оператор, приславший сообщение
timestamp Long Да Время в формате Unix time
text String Да Текстовое сообщение, отправленное оператором
from String Нет Константа "User", "Employee"

 

FileMessage

Оповещение о новом файле от оператора.

Формат оповещения:

Имя Тип Обязательный Комментарий
type String Да Константа - "FileMessage"
id String Да Уникальный строковый идентификатор сообщения
webhook_key String Нет Аутентификационный ключ внешнего канала, отдается только в webhook. В истории отдаваться не будет
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
employee Employee Да Оператор, приславший файл
timestamp Long Да Время в формате Unix time
url String Да Ссылка для скачивания файла
name String Нет Имя файла для скачивания
size Long Нет Размер файла в байтах
comment String Нет Комментарий к передаваемому файлу
from String Нет Константа "User", "Employee"

 

SelectDestination

Оповещение о необходимости выбрать направление маршрутизации для обращения.

Формат оповещения:

Имя Тип Обязательный Комментарий
type String Да Константа - "SelectDestination"
id String Да Уникальный строковый идентификатор сообщения
webhook_key String Нет Аутентификационный ключ внешнего канала, отдается только в webhook. В истории отдаваться не будет
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
destinations List Да Список доступных направлений маршрутизации

 

EmployeeAvailabilityChanged

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

Формат оповещения:

Имя Тип Обязательный Комментарий
type String Да Константа - "EmployeeAvailabilityChanged"
id String Да Уникальный строковый идентификатор сообщения
webhook_key String Нет Аутентификационный ключ внешнего канала, отдается только в webhook. В истории отдаваться не будет
touchPointId String Да Идентификатор точки контакта в которой происходит общение
employee Emploee Да Информация о операторе, который послал оповещение
online Boolean Да Доступность оператора для новых обращений
timestamp Long Да Время в формате Unix time

 

MessageDelivered

Оповещение о том, что сообщение доставлено до оператора.

Формат оповещения:

Имя Тип Обязательный Комментарий
type String Да Константа - "MessageDelivered"
id String Да Уникальный строковый идентификатор события
message_id String Да Идентификатор доставленного сообщения
webhook_key String Нет Аутентификационный ключ внешнего канала, отдается только в webhook. В истории отдаваться не будет
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
employee Employee Нет Оператор, прочитавший сообщение
timestamp Long Да Время в формате Unix time

 

HoldMessage

Удерживающее сообщение, которые приходят согласно настроенным сценариям удержания. Настроить сценарии удержания можно в личном кабинете https://my.livetex.ru в разделе Сценарии - вкладка Удержание.

Имя Тип Обязательный Комментарий
type String Да Константа - "HoldMessage"
id String Да Уникальный строковый идентификатор сообщения
webhook_key String Нет Аутентификационный ключ внешнего канала, отдается только в webhook. В истории отдаваться не будет
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
timestamp Long Да Время в формате Unix time
text String Да Текст удерживающего сообщения

 

Closed

Оповещение о закрытии обращения со стороны оператора.

Формат оповещения:

Имя Тип Обязательный Комментарий
type String Да Константа - "Closed".
id String Да Уникальный строковый идентификатор сообщения
webhook_key String Нет Аутентификационный ключ внешнего канала, отдается только в webhook. В истории отдаваться не будет
user_id String Да Идентификатор посетителя в точке контакта. Задается и контролируется на стороне разработчика, который использует Messaging API. LiveTex не устанавливает идентификаторы пользователей автоматически.
touch_point_id String Да Идентификатор точки контакта, в которой велось общение
employee Employee Да Оператор закрывший обращение
timestamp Long Да Время в формате Unix time

 

Статусы HTTP ответов

В случае успешной обработки LiveTex возвращает ответ с кодом 200. Прочие поддерживаемые статусы: 400, 401, 403, 404, 500

Возможные ошибки

Статус Код Сообщение Причина возникновения
400 1 Authentication key is not specified В запросе не указан ключ авторизации
401 2 Authentication key is not valid Указанный в запросе authentication_key не зарегистрирован в LiveTex
400 3 Empty body Пустое тело запроса
400 4 Wrong JSON format Невалидный формат JSON в запросе
400 5 URL [$url] is not valid: $reason Для получения Webhook-ов передан невалидный url
404 6 Unsupported HTTP request ${request.method} ${request.path} Выполнен недопустимый HTTP запрос
500 7 Internal server error Произошло непредвиденное исключение на стороне LiveTex
403 8 Forbidden method for your account Метод недоступен для используемой версии продуктов
400 9 Invalid data: $reason Переданные данные не валидны
Была ли эта статья полезной?
Пользователи, считающие этот материал полезным: 0 из 0
Еще есть вопросы? Отправить запрос

Комментарии