How to Create a WhatsApp Bot in Java: Example

The complete guide
Bot source repository
Published: November 5, 2020

In this article, we will look at how to write a simple WhatsApp bot in Java using our WhatsApp API.

In the example below, the bot will receive commands in the form of regular WhatsApp messages and reply to them. Don’t forget to download the ready-to-use bot from our repository and use it in your work!

What Functions Does the Bot Have?

  1. When you send the chatid command, the bot replies with a message with the current chat ID;
  2. When you send the file [format] command, the bot sends files (pdf, jpg, doc, mp3) that you have previously prepared;
  3. When you send the ogg command, the bot sends a file with the .ogg extension (a voice message);
  4. When you send the geo command, the bot sends GPS location;
  5. When you send the group command, the bot creates a group chat for itself and the user;
  6. When you send any non-command messages, the bot replies with a welcome message describing all commands (as a sort of menu);

Preparation

The first thing you should do is to connect WhatsApp to our script so that you could check the bot’s work while you are writing the code. To do this, go to your user account and get the QR code. Then open WhatsApp on your mobile phone and go to Settings -> WhatsApp Web -> Scan the QR code.

Note!
For the bot to work, your phone must be connected to the internet and must not be used for Whatsapp Web.

In order to react to commands, our bot must be able to receive and process incoming data. This will require setting up your own webhook. Specify its address in your user account.

A Few Words About Why You Need a Webhook

A webhook helps prevent pauses in answering incoming messages. Without it, our bot would have to constantly, at regular intervals, send requests for incoming data to the server. That would slow the response time and increase the server load.

But if you specify the webhook’s address, you are spared this problem. The servers will send notifications about incoming changes as soon as they appear. The webhook, in its turn, will receive and process them correctly, thus implementing the bot’s logic. You can specify either the domain name or the IP address.

Put webhook in your personal cabinet Set up webhook in your personal profile

How to Set Up Your Own Server in Java Using the Spring Boot Framework

To simplify the process of making the template of our spring boot app, use spring initializr: specify the necessary settings, pick the required Java version, and click on Generate

The next step is to download the generated project and open it in your IDE. In our example, we will use Intellij IDEA. Create a "controller" folder where you will keep your controller (it will process the data incoming to your server) and the classes necessary for the bot’s work.

Chat API sends JSON data that we will need to parse and process.

To see what particular data is sent to JSON, open the тестирование page in your user account, and go to the Webhook Simulator tab.

JSON body is the data (the structure of the data) that will be sent to our server. To comfortably work with it in Java, we will deserialize it into an object and treat the data as object properties.

For your convenience, use the service that allows for the automatic generation of JSON string to Java class. Copy JSON body, click on Preview and paste the automatically generated Java classes to our project. For this purpose, create the jsonserializables.java file and paste the code to the file.

After the class describing JSON body has been created, it’s time to start implementing the controller itself. The latter will process incoming data. Create a MessageController file and define the MessageController class in it.

@RestController
@RequestMapping("webhook")
    public class MessageController {
        @PostMapping
        public String AnswerWebhook(@RequestBody RequestWebhook hook) throws IOException {
            return  "ok";
        }

The @RequestMapping("webhook") annotation designates the address where our controller will process data. Example: "localhost:8080/webhook"

The @PostMapping annotation means that the AnswerWebhook function will process POST requests.

At the same time, the function’s parameter RequestWebhook is our deserialized JSON class whose deserialization is performed by Spring Boot. So, we get a ready-to-use object and can work with it within the function itself. Also within the function, we will describe the bot’s logic.

How to Implement the Logic of the Controller

@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";
        }

Within the cycle, go over all the incoming messages and process them in switch. It is necessary to check the bot’s work at the beginning of the cycle to make sure it will not loop into a recursive call. In case you get a message from yourself, just skip (don’t process) it.

Next, assign the received command to the option variable. To do this, use the split method to split the message body and lower-case the command text so that your bot could respond to commands irrespective of the case. In switch, depending on the incoming command, call the required method from the ApiWA class (see below).

The ApiWA Class

This class will implement static API methods. Within the class, we will describe the variables that will keep our token — so that we could successfully use the API when sending these data. You can find your token in your user account.

public class ApiWA {
        private static String APIURL = "https://eu115.chat-api.com/instance123456/";
        private static String TOKEN = "1hi0xw1fzaen1234";
    }

Next, we need to implement a method that will send a POST request.

 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);
    }

This method’s parameters include an URI link (where you will have to send a POST request) and a dictionary that you will need to serialize into a JSON string and send to the server.

To implement each of these methods, you will have to see detailed documentation and repeat requests.

Here is what the chatid sending method looks like:

    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);
    }

Now you need to form a URI where you will send requests and a dictionary with parameters. After that, use the method of sending POST requests that we have implemented above.

We described the implementation of sending a file via Whatsapp chatbot in the next chapter, and the rest of the functionality, such as sending geolocation, creating a group and other commands, you can see in the source code of our bot.

Other Commands
Other methods are implemented in a similar way. As for the source code, you can view and download it at Github.

How to Implement the Method of Sending Files

 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);
        }
    }

This method contains a dictionary where the keys are file formats while the values are strings in the Base64 format. To generate a string, you can use a dedicated service on our website. If a file format you need is not in the dictionary, you will get a notification saying that the file format is not supported.

We have described the Base64Help class and methods that allow you to get a string with a file of the required format. The string itself is stored in TXT files on the server and when we use the code, we just read it from the file. This is vital because, in Java, you cannot store strings that long right in the code. You can generate a Base64 string either automatically or through special services.

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

    }

Summing up, we have described the work of a simple WhatsApp bot and uploaded its fully functioning source code to Github.

The code and guide will be available at Github via the link: https://github.com/chatapi/whatsapp-java-bot-en

java chat bot tutorial for whatsapp

All you will need to do is to insert your token (specified in your user account) and your instance number into the code.

Java chat bot tutorial for Whatsapp

Now it is time to upload your server’s code together with the bot to the hosting and specify your domain name as your webhook. Every time you have an incoming message, the data will be sent to the server and processed there. If you have any questions, feel free to contact our Technical Support Team!