Функционал из данного гайда был перенесен на messengers Business API, с помощью которого вы также сможете производить рассылки, создавать чат боты и многое другое, но без риска быть заблокированным.
В связи с изменением условий работы API, в данном гайде частично могут использоваться неактуальные сведения. Пожалуйста, посмотрите документацию перед началом работы.
Сейчас Chat API предлагает самый доступный и автоматизированный messengers Business API на рынке с Многопользовательским Чатом, Визуальным конструктором ботов, готовыми интеграциями приложений и другими полезными функциями.
Расскажем, как написать простого ватсап бота на Java, используя наш API messengers.
В данном примере бот будет реагировать на команды, поступающие ему в виде обычных сообщений в messengers и отвечать на них. Не забудьте скачать готового бота с нашего репозитория и использовать его в своей работе!
Какой функционал у данного бота?
- При отправке команды "chatid" бот должен отправить сообщение с текущим ID чата;
- При отправке команды "file [format]" бот должен отправить заранее подготовленные файлы (pdf, jpg, doc, mp3);
- При отправке команды "ogg", бот должен отправить файл с расширением "ogg" (Голосовое сообщение);
- При отправке команды "geo", бот должен отправить гео-координаты (локацию);
- При отправке команды "group" бот должен создать группу с собой и пользователем;
- Реагировать приветственным сообщением с описанием команд на все входящие не "командные" сообщения (как аналог "меню");
Подготовка
В самом начале, сразу свяжем messengers с нашим скриптом, чтобы по мере написания кода - проверять его работу. Для этого переходим в личный кабинет и получаем там QR-код. Далее открываем messengers на мобильном телефоне, заходим в Настройки -> messengers Web -> Сканируем QR-код.
Для того, чтобы наш бот реагировал на команды необходимо, чтобы бот мог принять и обработать входящие данные. Для этого требуется поднять собственный сервер - Webhook и указать его адрес в личном кабинете.
Немного о том, для чего нужен Webhook
Webhook решает проблему с задержкой на отклик входящих сообщений. Без него, нашему боту пришлось бы постоянно спрашивать у сервера о входящих данных, делать периодические фиксированные во времени запросы к серверам. Тем самым имея некоторую задержку в отклике, а также это способствовало бы нагрузке на сервер.
Но, если мы укажем адрес Webhook сервера, то данная необходимость перестанет быть актуальной. Сервера сами будут присылать уведомления о входящих изменениях, как только они появятся. А задача Webhook сервера их принять и правильно обработать, реализовывая логику бота. Указывать можно как домен, так и ip адрес
Поднимаем собственный сервер на Java с помощью фреймворка Spring Boot
Для упрощения создания заготовки нашего spring boot приложения будем использовать spring initializr: Выставляем необходимые настройки, выбираем нужную версию Java и жмём Generate
Далее необходимо скачать сгенерированный проект и открыть в вашей IDE. Я буду использовать Intellij IDEA. Создадим папку "controller", в которой будем хранить наш контроллер по обработке входящих данных на наш сервер и необходимые классы для работы бота.
Сhat-api присылает Json данные, которые нам необходимо будет распарсить и обработать.
Для того, чтобы узнать, что именно нам приходит в json, воспользуемся страницей тестирование в личном кабинете и перейдем во вкладку "Симуляция Weebhoka"
JSON body - Данные, которые будут приходить к нам на сервер (Их структура). Для того, чтобы удобно с ним работать из Java мы будем десериализовывать его в объект и обращаться с данными, как со свойствами объекта.
Для нашего удобства воспользуемся сервисом по автоматической генерации Json to Java class. Копируем JSON body. Жмем Preview и копируем автоматически сгенерированные классы Java в наш проект. Для этого создадим файл jsonserializables.java и вставляем код в файл.
После того, как наш класс, описывающий JSON тело создан, приступаем к реализации самого контроллера, который будет обрабатывать входящие данные. Для этого создадим новый файл "MessageController" и опишем в нём класс MessageController.
@RestController
@RequestMapping("webhook")
public class MessageController {
@PostMapping
public String AnswerWebhook(@RequestBody RequestWebhook hook) throws IOException {
return "ok";
}
Аннотация @RequestMapping("webhook") отвечает за адрес, по которому будет обрабатываться наш контроллер. Например: "localhost:8080/webhook"
Аннотация @PostMapping означает, что функция AnswerWebhook будет обрабатывать Post запросы.
В тоже время, параметр RequestWebhook в параметрах функции - это наш десериализованный JSON класс, десериализацию которого берет на себя Spring Boot и мы получаем сразу готовый объект и можем с ним работать внутри самой функции. В ней мы опишем логику работы бота.
Реализуем логику контроллера
@RestController
@RequestMapping("webhook")
public class MessageController {
@PostMapping
public String AnswerWebhook(@RequestBody RequestWebhook hook) throws IOException {
for (var message : hook.getMessages()) {
if (message.getFromMe())
continue;
String option = message.getBody().split(" ")[0].toLowerCase();
switch (option)
{
case "chatid":
ApiWA.sendChatId(message.getChatId());
break;
case "file":
var texts = message.getBody().split(" ");
if (texts.length > 1)
ApiWA.sendFile(message.getChatId(), texts[1]);
break;
case "ogg":
ApiWA.sendOgg(message.getChatId());
break;
case "geo":
ApiWA.sendGeo(message.getChatId());
break;
case "group":
ApiWA.createGroup(message.getAuthor());
break;
default:
ApiWA.sendDefault(message.getChatId());
break;
}
}
return "ok";
}
В цикле проходимся по всем пришедшим сообщениям и обрабатываем их в switch. Проверка в начале цикла нужна для того, чтобы бот не зациклился сам на себя. В случае, если сообщение пришло от самого себя - то пропускаем его и не обрабатываем.
Далее записываем в переменную option пришедшую команду. Для этого тело сообщения мы разбиваем методом split и приводим команду в нижний регистр, чтобы бот реагировал на команды независимо от регистра. В switch, в зависимости от пришедшей команды, мы вызываем необходимый метод из класса ApiWA, о реализации которого мы сейчас и поговорим.
Класс ApiWA
Данный класс будет реализовывать статические методы по обращению к API. Внутри класса опишем переменные, которые будут хранить наш токен, чтобы мы могли успешно пользоваться API, передавая эти данные. Их можно найти в личном кабинете
public class ApiWA {
private static String APIURL = "https://eu115.chat-api.com/instance123456/";
private static String TOKEN = "1hi0xw1fzaen1234";
}
После чего нам потребуется реализовать метод, который будет отправлять POST запрос.
public static CompletableFuture<Void> postJSON(URI uri,
Map<String,String> map)
throws IOException
{
ObjectMapper objectMapper = new ObjectMapper();
String requestBody = objectMapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(map);
HttpRequest request = HttpRequest.newBuilder(uri)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
return HttpClient.newHttpClient()
.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::statusCode)
.thenAccept(System.out::println);
}
Данный метод принимает в параметры ссылку URI, на которую необходимо сделать Post запрос, а также словарь, который сериализуется в Json строку и передается на сервер.
Для реализации каждого из методов смотрим подробную документацию и повторяем запросы.
Так выглядит метод по отправке chatid:
public static void sendChatId(String chat_id) throws IOException {
URI uri = URI.create(APIURL + "sendMessage?token=" + TOKEN);
Map<String, String> map = new HashMap<String, String>();
map.put("body", "Your ID: " + chat_id);
map.put("phone", chat_id);
ApiWA.postJSON(uri, map);
}
Формируем ссылку, на которую нужно сделать запрос и словарь с параметрами. После чего обращаемся к методу по отправке post запроса, который мы реализовали выше.
Реализацию отправки файла через messengers бота мы описали ниже, а остальной функционал: отправка геолокации, создании группы и прочие команды, вы можете посмотреть в исходниках нашего бота.
Отдельно поговорим о реализации метода по отправке файлов
public static void sendFile(String chat_id, String file_format) throws IOException {
Map<String, String> formats= new HashMap<String, String>();
formats.put("doc", Base64Help.getDOC());
formats.put("jpeg", Base64Help.getJPEG());
formats.put("pdf", Base64Help.getPDFtring());
formats.put("mp3", Base64Help.getMP3String());
if (formats.containsKey(file_format))
{
Map<String, String> map = new HashMap<String, String>();
map.put("phone", chat_id);
map.put("body", formats.get(file_format));
map.put("filename", "ThisIsFile");
map.put("caption", "ThisIsCaption");
URI uri = URI.create(APIURL + "sendFile?token=" + TOKEN);
ApiWA.postJSON(uri, map);
}
else
{
Map<String, String> map = new HashMap<String, String>();
map.put("phone", chat_id);
map.put("body", "File not found");
URI uri = URI.create(APIURL + "sendMessage?token=" + TOKEN);
ApiWA.postJSON(uri, map);
}
}
Данный метод хранит в себе словарь, в котором ключи - формат файлов, а значения - строка в формате Base64. Base64 строкa используется для передачи файлов. Для генерации строки можно воспользоваться сервисом на нашем сайте. Если файл нужного формата отсутствует в словаре, то мы отправляем сообщение о том, что файл не найден.
Мы описали класс Base64Help и методы по получению строки с файлом нужного формата. Сама строка хранится в txt файлах на сервере, а из кода мы просто считываем её из файла. Это необходимо, потому что Java не позволяет хранить такие длинные строки прямо в коде. Вы же можете генерировать строку Base64 автоматически, либо пользуясь сервисами.
public class Base64Help {
static public String getPDFString() throws IOException {
return new String(Files.readAllBytes(Paths.get("src/main/resources/pdf.txt")));
}
static public String getMP3String() throws IOException {
return new String(Files.readAllBytes(Paths.get("src/main/resources/mp3.txt")));
}
static public String getJPEG() throws IOException {
return new String(Files.readAllBytes(Paths.get("src/main/resources/jpeg.txt")));
}
static public String getDOC() throws IOException {
return new String(Files.readAllBytes(Paths.get("src/main/resources/doc.txt")));
}
}
Итак, мы описали работу простого ватсап-бота и выложили исходник с готовым функционалом на github.
Вам необходимо только подставить в коде свой токен из личного кабинета и номер инстанса.
messengers бот на Java
Теперь необходимо загрузить наш сервер вместе с ботом на хостинг и в качестве webhook указать ваш домен. При каждом входящем сообщении на сервер будут приходить и обрабатываться данные. Если у вас возникнут какие-либо вопросы, вы всегда можете обратиться в нашу техническую поддержку!