How to build a simple Whatsapp bot on php

Updated hAPIcat 5 Tallied Votes 1K Views Share

Hi, everybody.
I write bots and decided to share my experience of writing bots on the [Chat API] platform, maybe it will be interesting to someone

We’ll tell you how to write a simple bot on PHP using API WhatsApp.

A demo bot will react on commands of ordinary Whatsapp messages to answer them. Now our demo bot features the following functions:

Displaying the list of commands
Displaying the ID of the chat
Displaying the current bot server time
Displaying your name
Sending files of different formats (pdf, jpg, doc, mp3, etc.)
Sending pre-recorded voice messages
Sending geo-coordinates (geo-locations)
Creating a conference (group)

Attention: to make the bot running, the phone must be connected to the Internet and mustn’t be used for Whatsapp Web. It’s more convenient to use a separate smartphone for coding.

Preparatory work
Authorization of Whatsapp via QR code

At the very beginning, we need to connect whatsapp with our script, so as we write the code, we check its operation. To do this, go to your personal account and get a QR code there. Next, open WhatsApp on your smartphone, go to Settings -> WhatsApp Web -> Scan a QR code.

Now we need to indicate a WebHook URL so the server can run the scrip when new messages arrive. Indicate a direct link to your script, e.g. https://domain.com/PHP/whatsappbot.php. You can’t indicate server IP only, but you can indicate the port.

Now let’s produce a whatsappbot.php file to make a following class: class whatsAppBot

Create variables to put the APIUrl and the token. They can be found in your personal account.

{var $APIurl = 'https://api.chat-api.com/instanceYYYYY/';
                            var $token = 'abcdefgh12345678';}

Now let’s indicate the function __construct(), which will be executed automatically every time the script is run. The ChatAPI server will access the bot when new messages arrive (you can find more information below), sending information about the new message in JSON format. We immediately catch this data at the beginning of the function and put it into variables.

{public function __construct(){ $json = file_get_contents('php://input');
                            $decoded = json_decode($json,true);}}

We’re continuing to write the code of the function. You can save the data received to the file to analyze and checkout if needed. To make it, we’ll use an output buffer.

{ ob_start();
                        var_dump($decoded);
                        $input = ob_get_contents();
                        ob_end_clean();
                        file_put_contents('input_requests.log',$input.PHP_EOL,FILE_APPEND);}

Then we’ll write the processing of incoming messages and execution of the corresponding functions. There’ll be a lot of nested code, but we’ll sort it line by line.

{ if(isset($decoded['messages'])){
                        foreach($decoded['messages'] as $message){
                        $text = explode(' ',trim($message['body']));
                        if(!$message['fromMe']){
                        switch(mb_strtolower($text[0],'UTF-8')){
                        case 'hi':  {$this->welcome($message['chatId'],false); break;}
                            case 'chatId': {$this->showchatId($message['chatId']); break;}
                            case 'time':   {$this->time($message['chatId']); break;}
                            case 'me':     {$this->me($message['chatId'],$message['senderName']); break;}
                            case 'file':   {$this->file($message['chatId'],$text[1]); break;}
                            case 'ptt':     {$this->ptt($message['chatId']); break;}
                            case 'geo':    {$this->geo($message['chatId']); break;}
                            case 'group':  {$this->group($message['author']); break;}
                            default:        {$this->welcome($message['chatId'],true); break;}
                            }}}}}

So:

if(isset($decoded['messages']))
Notifications such as "user left the chat" are also sent by the server, but they won’t have an array of messages. This check prevents the Undefined index error.

foreach($decoded['messages'] as $message)
There is an array of messages, so you can get several of them; the bot must react to every and each.

$text = explode(' ',trim($message['body']));
We’ll divide the message body into the single words. The first one is a command, the rest are parameters.

if(!$message['fromMe'])
This check is necessary so that the bot won’t recourse. The mark "fromMe" means that the message was sent by the bot itself. Therefore, we continue the execution only for incoming messages.

switch(mb_strtolower($text[0],'UTF-8'))
Switch block will identify the command (using the first word). The command must be given in the lower register so the bot react to it, no matter HOW It WiLL bE WriTTen.

case 'hi': {$this->welcome($message['chatId'],false)}
Actually, the execution of the appropriate command depends on the first word. We transfer chatId from the message to the function of execution, so that the sending will take place in the corresponding chat. Technially, all the following lines are the same, but pay attention to:

case 'file': {$this->file($message['chatId'],$text[1])}
Here we give one more parameter which is indicated with the second word. Everything will be discussed below. Also, pay attention to:

case 'me': {$this->me($message['chatId'],$message['senderName'])}
Here the second parameter is the name of the interlocutor, taken from the message data. And in default we execute a function that displays a list of commands, but with the true parameter, which means getting the wrong command.

We’ve finished writing the __construct() function. Let’s turn to the functions executed by the commands from the above-mentioned switch block. In the part of the functions, the sendMessage () function is executed, in another part - the sendRequest () function. In the script, these functions are below, but we will tell about them immediately:

The sendRequest() function directly queries the ChatAPI server for sending messages and various media. It takes 2 parameters, $method and $data.

$method determines which chatAPI method should be executed
$data contains the data required for transfer.

{ public function sendRequest($method,$data){
                        $url = $this->APIurl.$method.'?token='.$this->token;
                        if(is_array($data)){ $data = json_encode($data);}
                        $options = stream_context_create(['http' => [
                        'method'  => 'POST',
                        'header'  => 'Content-type: application/json',
                        'content' => $data
                        ]]);
                        $response = file_get_contents($url,false,$options);
                        file_put_contents('requests.log',$response.PHP_EOL,FILE_APPEND);}

Let us examine in more detail: In $url we form a valid URL containing the APIUrl, method and token. Then we check the incoming data. If it is an array, convert it to JSON. If not, then the conversion to JSON has already been implemented in the executed function. $options set HTTP headers. Then through file_get_contents we execute the request for the generated URL, passing the data. The last line is optional, it simply writes the ChatAPI server's response to a file for debugging and logging.

The sendMessage() function is just a shell for sending simple text messages. It forms the correct data array and passes it to the abovementioned sendRequest() function with the "message" method.

{ public function sendMessage($chatId, $text){
                        $data = array('chatId'=>$chatId,'body'=>$text);
                        $this->sendRequest('message',$data);}}

Now we’ll create control functions from the switch block. Functions that send a simple text message, usually execute sendMessage() with certain text. Functions that send various media form their data arrays and execute sendRequest() with other methods.

Welcome() function will display the list of available commands.

{ public function welcome($chatId, $noWelcome = false){
                        $welcomeString = ($noWelcome) ? "Incorrect command\n" : "WhatsApp Demo Bot PHP\n";
                        $this->sendMessage($chatId,
                        $welcomeString.
                        "Commands:\n".
                        "1. chatId - show ID of the current chat\n".
                        "2. time - show server time\n".
                        "3. me - show your nickname\n".
                        "4. file [format] - get a file. Available formats: doc/gif/jpg/png/pdf/mp3/mp4\n".
                        "5. ptt - get a voice message\n".
                        "6. geo - get a location\n".
                        "7. group - create a group with the bot");}}

If the $noWelcome parameter is false, then the first line of the message will be the greeting displayed by the "hi" command. If it’s true, the greeting will be replaced with a message to the wrong command.

The showchatId() function displays the current chat ID using the "chatId" command.

{ public function showchatId($chatId){
                        $this->sendMessage($chatId,'chatId: '.$chatId);}}

The time() function display the current server time using the "time" command.

{ public function time($chatId){
                        $this->sendMessage($chatId,date('d.m.Y H:i:s'));}}

The me() function display the name of the interlocutor using the "me" command.

{
                        public function me($chatId,$name){
                        $this->sendMessage($chatId,$name);
                        }}

The file() function sends a file using the "file" command. This function is most interesting, since it works with the parameter. The parameter is the format of the file to be sent.

{ public function file($chatId,$format){
                        $availableFiles = array(
                        'doc' => 'document.doc',
                        'gif' => 'gifka.gif',
                        'jpg' => 'jpgfile.jpg',
                        'png' => 'pngfile.png',
                        'pdf' => 'presentation.pdf',
                        'mp4' => 'video.mp4',
                        'mp3' => 'mp3file.mp3'
                        );
                        if(isset($availableFiles[$format])){
                        $data = array(
                        'chatId'=>$chatId,
                        'body'=>'https://domain.com/PHP/'.$availableFiles[$format],
                        'filename'=>$availableFiles[$format],
                        'caption'=>'Get your file '.$availableFiles[$format]
                        );
                        $this->sendRequest('sendFile',$data);}}}

Let’s explore it:

$availableFiles is an array in which the keys are the function parameters and the values are the file names. Naturally, files with names from the array must be present on the server. In this example, they are in the same place as the bot script, but you can put them in another folder.
if (isset ($availableFiles [$format])) checks the existence of an array key with the received parameter. If it exists, then we form an array of data, and pass it to sendRequest() with the "sendFile" method. The following data should be in the data array:
chatId as usual, the chat ID to which the response is sent.
body is a direct link to the file on your server. Please note that SSL must be enabled on the server!
filename is the file name, you can specify any
caption accompanies this file message.
Ptt() function sends a voice message using the "ptt" command. The voice message must be an .ogg file on your server.

{ public function ptt($chatId){
                        $data = array(
                        'audio'=>'https://domain.com/PHP/ptt.ogg',
                        'chatId'=>$chatId
                        );
                        $this->sendRequest('sendAudio',$data);}}

Here, as in the previous function, we form an array of data: chatId - chat ID audio - a direct link to the .ogg file, SSL is again required. And we’ll pass it to the sendRequest function with the "sendAudio" method.

The geo() function sends geo-coordinates with the "geo" command

{ public function geo($chatId){
                        $data = array(
                        'lat'=>51.51916,
                        'lng'=>-0.139214,
                        'address'=>'Your address',
                        'chatId'=>$chatId
                        );
                        $this->sendRequest('sendLocation',$data);
                        }}

The process is the same as for the previous two functions. The array should contain the following data: lat and lng - coordinates; address is an address, but you can write any string; and of course chatId.

The function group() creates a conference for you and the bot with the "group" command.

{ public function group($author){
                        $phone = str_replace('@c.us','',$author);
                        $data = array(
                        'groupName'=>'Group with the bot PHP',
                        'phones'=>array($phone),
                        'messageText'=>'It is your group. Enjoy'
                        );
                        $this->sendRequest('group',$data);}}

Here we need to specify the phone numbers of users who will be added to the conference. In the first line, we retrieve the user's phone number from his personal ID, which looks like 79991234567@c.us Then we form an array:

groupName is the name of the conference;
phones is an array of phone numbers;
messageText is the text of the first message in the group;
Please note that this is the only function where you DONO’T NEED to send the chatId. And we pass the array to sendRequest().

Now that we have finished working with functions, write a string after the closing bracket class: new whatsAppBot();

So the class will be executed automatically at the call to a script.

The final code will look like this.

{
                        class whatsAppBot{
                        //specify instance URL and token
                        var $APIurl = 'https://api.chat-api.com/instanceYYYYY/';
                        var $token = '**************************';

                        public function __construct(){
                        //get the JSON body from the instance
                        $json = file_get_contents('php://input');
                        $decoded = json_decode($json,true);

                        //write parsed JSON-body to the file for debugging
                        ob_start();
                        var_dump($decoded);
                        $input = ob_get_contents();
                        ob_end_clean();
                        file_put_contents('input_requests.log',$input.PHP_EOL,FILE_APPEND);

                        if(isset($decoded['messages'])){
                        //check every new message
                        foreach($decoded['messages'] as $message){
                        //delete excess spaces and split the message on spaces. The first word in the message is a command, other words are parameters
                        $text = explode(' ',trim($message['body']));
                        //current message shouldn't be send from your bot, because it calls recursion
                        if(!$message['fromMe']){
                        //check what command contains the first word and call the function
                        switch(mb_strtolower($text[0],'UTF-8')){
                        case 'hi':  {$this->welcome($message['chatId'],false); break;}
                            case 'chatId': {$this->showchatId($message['chatId']); break;}
                            case 'time':   {$this->time($message['chatId']); break;}
                            case 'me':     {$this->me($message['chatId'],$message['senderName']); break;}
                            case 'file':   {$this->file($message['chatId'],$text[1]); break;}
                            case 'ptt':     {$this->ptt($message['chatId']); break;}
                            case 'geo':    {$this->geo($message['chatId']); break;}
                            case 'group':  {$this->group($message['author']); break;}
                            default:        {$this->welcome($message['chatId'],true); break;}
                            }}}}}

                        //this function calls function sendRequest to send a simple message
                        //@param $chatId [string] [required] - the ID of chat where we send a message
                        //@param $text [string] [required] - text of the message
                        public function welcome($chatId, $noWelcome = false){
                        $welcomeString = ($noWelcome) ? "Incorrect command\n" : "WhatsApp Demo Bot PHP\n";
                        $this->sendMessage($chatId,
                        $welcomeString.
                        "Commands:\n".
                        "1. chatId - show ID of the current chat\n".
                        "2. time - show server time\n".
                        "3. me - show your nickname\n".
                        "4. file [format] - get a file. Available formats: doc/gif/jpg/png/pdf/mp3/mp4\n".
                        "5. ptt - get a voice message\n".
                        "6. geo - get a location\n".
                        "7. group - create a group with the bot"
                        );
                        }

                        //sends Id of the current chat. it is called when the bot gets the command "chatId"
                        //@param $chatId [string] [required] - the ID of chat where we send a message
                        public function showchatId($chatId){
                        $this->sendMessage($chatId,'chatId: '.$chatId);
                        }
                        //sends current server time. it is called when the bot gets the command "time"
                        //@param $chatId [string] [required] - the ID of chat where we send a message
                        public function time($chatId){
                        $this->sendMessage($chatId,date('d.m.Y H:i:s'));
                        }
                        //sends your nickname. it is called when the bot gets the command "me"
                        //@param $chatId [string] [required] - the ID of chat where we send a message
                        //@param $name [string] [required] - the "senderName" property of the message
                        public function me($chatId,$name){
                        $this->sendMessage($chatId,$name);
                        }
                        //sends a file. it is called when the bot gets the command "file"
                        //@param $chatId [string] [required] - the ID of chat where we send a message
                        //@param $format [string] [required] - file format, from the params in the message body (text[1], etc)
                        public function file($chatId,$format){
                        $availableFiles = array(
                        'doc' => 'document.doc',
                        'gif' => 'gifka.gif',
                        'jpg' => 'jpgfile.jpg',
                        'png' => 'pngfile.png',
                        'pdf' => 'presentation.pdf',
                        'mp4' => 'video.mp4',
                        'mp3' => 'mp3file.mp3'
                        );

                        if(isset($availableFiles[$format])){
                        $data = array(
                        'chatId'=>$chatId,
                        'body'=>'https://domain.com/PHP/'.$availableFiles[$format],
                        'filename'=>$availableFiles[$format],
                        'caption'=>'Get your file '.$availableFiles[$format]
                        );
                        $this->sendRequest('sendFile',$data);}}

                        //sends a voice message. it is called when the bot gets the command "ptt"
                        //@param $chatId [string] [required] - the ID of chat where we send a message
                        public function ptt($chatId){
                        $data = array(
                        'audio'=>'https://domain.com/PHP/ptt.ogg',
                        'chatId'=>$chatId
                        );
                        $this->sendRequest('sendAudio',$data);}

                        //sends a location. it is called when the bot gets the command "geo"
                        //@param $chatId [string] [required] - the ID of chat where we send a message
                        public function geo($chatId){
                        $data = array(
                        'lat'=>51.51916,
                        'lng'=>-0.139214,
                        'address'=>'Ваш адрес',
                        'chatId'=>$chatId
                        );
                        $this->sendRequest('sendLocation',$data);}

                        //creates a group. it is called when the bot gets the command "group"
                        //@param chatId [string] [required] - the ID of chat where we send a message
                        //@param author [string] [required] - "author" property of the message
                        public function group($author){
                        $phone = str_replace('@c.us','',$author);
                        $data = array(
                        'groupName'=>'Group with the bot PHP',
                        'phones'=>array($phone),
                        'messageText'=>'It is your group. Enjoy'
                        );
                        $this->sendRequest('group',$data);}

                        public function sendMessage($chatId, $text){
                        $data = array('chatId'=>$chatId,'body'=>$text);
                        $this->sendRequest('message',$data);}

                        public function sendRequest($method,$data){
                        $url = $this->APIurl.$method.'?token='.$this->token;
                        if(is_array($data)){ $data = json_encode($data);}
                        $options = stream_context_create(['http' => [
                        'method'  => 'POST',
                        'header'  => 'Content-type: application/json',
                        'content' => $data]]);
                        $response = file_get_contents($url,false,$options);
                        file_put_contents('requests.log',$response.PHP_EOL,FILE_APPEND);}}
                        //execute the class when this file is requested by the instance
                        new whatsAppBot();}

You’ll only need to substitute your token from your personal account into the $ token variable and instance number

Thank you for reading, I hope you will find it useful

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.