Home Documentation Rental FAQ Contact details
Sign in

Writing a simple WhatsApp bot in PHP

We will tell you how to write a simple bot in PHP using the WhatsApp API.

We thought that a bot that receives a city name at the input and sends weather conditions in response would be suitable for the introduction.

To get started, let's find an API that will provide the weather conditions, we stopped at Yahoo Weather API

If we go to the link, we will see an example of a query and response.

Write function get_weather() which will accept a line with a city name at the input:


function get_weather($city) {
        
        if (!empty($city)) {
            $yql_query = 'select * from weather.forecast where woeid in (select woeid from geo.places(1) where text="' . $city . '")';
            $yql_query_url = 'http://query.yahooapis.com/v1/public/yql?q=' . urlencode($yql_query) . "&format=json";
            $session = curl_init($yql_query_url);
            curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
            $phpObj = json_decode(curl_exec($session));
            // See what happened
            print_r($phpObj);
        }

        return
            true;
    }
// Call the function
get_weather('Москва');

In response, we get:


stdClass Object
(
    [query] => stdClass Object
        (
            [count] => 1
            [created] => 2018-10-09T18:57:03Z
            [lang] => en-US
            [results] => stdClass Object
                (
                    [channel] => stdClass Object
                        (
                            [units] => stdClass Object
                                (
                                    [distance] => mi
                                    [pressure] => in
                                    [speed] => mph
                                    [temperature] => F
                                )

                            [title] => Yahoo! Weather - Moscow, Moscow Federal City, RU
                            [link] => http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/
                            [description] => Yahoo! Weather for Moscow, Moscow Federal City, RU
                            [language] => en-us
                            [lastBuildDate] => Tue, 09 Oct 2018 09:57 PM MSK
                            [ttl] => 60
                            [location] => stdClass Object
                                (
                                    [city] => Moscow
                                    [country] => Russia
                                    [region] =>  Moscow Federal City
                                )

                            [wind] => stdClass Object
                                (
                                    [chill] => 45
                                    [direction] => 225
                                    [speed] => 11
                                )

                            [atmosphere] => stdClass Object
                                (
                                    [humidity] => 54
                                    [pressure] => 1007.0
                                    [rising] => 0
                                    [visibility] => 16.1
                                )

                            [astronomy] => stdClass Object
                                (
                                    [sunrise] => 6:49 am
                                    [sunset] => 5:43 pm
                                )

                            [image] => stdClass Object
                                (
                                    [title] => Yahoo! Weather
                                    [width] => 142
                                    [height] => 18
                                    [link] => http://weather.yahoo.com
                                    [url] => http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif
                                )

                            [item] => stdClass Object
                                (
                                    [title] => Conditions for Moscow, Moscow Federal City, RU at 09:00 PM MSK
                                    [lat] => 55.741638
                                    [long] => 37.605061
                                    [link] => http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2122265/
                                    [pubDate] => Tue, 09 Oct 2018 09:00 PM MSK
                                    [condition] => stdClass Object
                                        (
                                            [code] => 29
                                            [date] => Tue, 09 Oct 2018 09:00 PM MSK
                                            [temp] => 47
                                            [text] => Partly Cloudy
                                        )

                                    [forecast] => Array
                                        (
                                            [0] => stdClass Object
                                                (
                                                    [code] => 28
                                                    [date] => 09 Oct 2018
                                                    [day] => Tue
                                                    [high] => 50
                                                    [low] => 35
                                                    [text] => Mostly Cloudy
                                                )

                                            [1] => stdClass Object
                                                (
                                                    [code] => 28
                                                    [date] => 10 Oct 2018
                                                    [day] => Wed
                                                    [high] => 56
                                                    [low] => 40
                                                    [text] => Mostly Cloudy
                                                )

                                            [2] => stdClass Object
                                                (
                                                    [code] => 34
                                                    [date] => 11 Oct 2018
                                                    [day] => Thu
                                                    [high] => 54
                                                    [low] => 43
                                                    [text] => Mostly Sunny
                                                )

We see that in $phpObj->query->results->channel->units->temperature we have F, this means that the unit of measure is Fahrenheit by default.

To get the temperature in Celsius, we rewrite the query to:

$yql_query = 'select * from weather.forecast where woeid in (select woeid from geo.places(1) where text="' . $city . '") and u="c"';

Great! Now let's see what data we need, we take the minimum, these are:

  • City and country ($phpObj->query->results->channel->location->city, $phpObj->query->results->channel->location->country)
  • Current temperature ($phpObj->query->results->channel->item->condition->temp)
  • Forecast for the next day. $phpObj->query->results->channel->item->forecast['0']
    • Date ($phpObj->query->results->channel->item->forecast['0']->date)
    • Forecasted minimum temperature ($phpObj->query->results->channel->item->forecast['0']->low)
    • Forecasted maximum temperature ($phpObj->query->results->channel->item->forecast['0']->high)

We also provide an option of a response in two languages. To do this, we write function get_lang() which will receive a mobile phone number at the input and check if the first digit is not seven, then there is no sense to respond in Russian:

function get_lang($p) {
        if ((int) mb_substr($p, 0, 1, 'utf-8') != 7)
            self::$lang = 'en';
    }

We also introduce function lg() that will contain the array for two languages with templates like {CITY} which we will replace with required values thereafter:

function lg() {
        return
                array(
                    'ru' => array(
                        'Город: {CITY}',
                        'Тек. темп.: {CURRENT} C°',
                        'Прогноз на {DATE}:',
                        '{1}C° — {2}C°',
                        'Бот предоставлен https://api-messenger.com',
                        'Город не найден. Возможно Вы допустили ошибку при наборе.'
                    ),
                    'en' => array(
                        'City: {CITY}',
                        'Current temperature: {CURRENT} C°',
                        'Forecast for {DATE}:',
                        '{1}C° — {2}C°',
                        'Bot by https://api-messenger.com',
                        'City not found. Perhaps you made a mistake while typing.'
                    )
        );
    }

Finally, function get_weather() is as follows:


function get_weather($city) {

        if (!empty($city)) {
            $yql_query = 'select * from weather.forecast where woeid in (select woeid from geo.places(1) where text="' . $city . '") and u="c"';
            $yql_query_url = 'http://query.yahooapis.com/v1/public/yql?q=' . urlencode($yql_query) . "&format=json";
            $session = curl_init($yql_query_url);
            curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
            $phpObj = json_decode(curl_exec($session));
            if (count($phpObj->query->results->channel->item) > 0) {
                $str = array(
                    '{CITY}' => $phpObj->query->results->channel->location->city.', '.$phpObj->query->results->channel->location->country,
                    '{CURRENT}' => $phpObj->query->results->channel->item->condition->temp,
                    '{DATE}' => $phpObj->query->results->channel->item->forecast['0']->date,
                    '{1}' => $phpObj->query->results->channel->item->forecast['0']->low,
                    '{2}' => $phpObj->query->results->channel->item->forecast['0']->high
                );
                $txt = strtr(implode("\r\n", array_slice(self::lg()[self::$lang], 0, count(self::lg()[self::$lang]) - 1)), $str);
            } else
                $txt = array_pop(self::lg()[self::$lang]);
        }

        return
                $txt;
    }

Half the work is done. Now we shall link WhatsApp with our script. To do this, go to the href="/my/" target="_blank">personal account and click on "Get a QR code".

Next, open WhatsApp on your mobile phone, go to Settings -> WhatsApp Web -> Scan a QR code.

To receive notifications to the script about the incoming WhatsApp messages, we add a Webhook address.

Further, according to the documentation, we write a processing script for our task:


$body = json_decode(file_get_contents('php://input'));

foreach ($body->messages as $v) {
    if ($v->type == 'chat') {
        $api->get_lang($v->sender);
        $sendArray[] = array('chatId' => $v->sender, 'message' => $api->get_weather($v->body));
    }
}
if (count($sendArray) > 0) {
    $api->send_messages($sendArray);
    unset($sendArray);
}

The final code will look like this:


class api_messenger {

    private static $token = '**********************************';
    private static $lang = 'ru';

    function lg() {
        return
                array(
                    'ru' => array(
                        'Город: {CITY}',
                        'Тек. темп.: {CURRENT} C°',
                        'Прогноз на {DATE}:',
                        '{1}C° — {2}C°',
                        'Бот предоставлен https://api-messenger.com',
                        'Город не найден. Возможно Вы допустили ошибку при наборе.'
                    ),
                    'en' => array(
                        'City: {CITY}',
                        'Current temperature: {CURRENT} C°',
                        'Forecast for {DATE}:',
                        '{1}C° — {2}C°',
                        'Bot by https://api-messenger.com',
                        'City not found. Perhaps you made a mistake while typing.'
                    )
        );
    }

    function get_lang($p) {
        if ((int) mb_substr($p, 0, 1, 'utf-8') != 7)
            self::$lang = 'en';
    }

    function send_messages($array) {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, 'https://app.api-messenger.com/sendmessage?token=' . self::$token);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($array));
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/json; charset=utf-8'));
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
        $res = json_decode(curl_exec($curl), true);
    }

    function get_weather($city) {

        if (!empty($city)) {
            $yql_query = 'select * from weather.forecast where woeid in (select woeid from geo.places(1) where text="' . $city . '") and u="c"';
            $yql_query_url = 'http://query.yahooapis.com/v1/public/yql?q=' . urlencode($yql_query) . "&format=json";
            $session = curl_init($yql_query_url);
            curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
            $phpObj = json_decode(curl_exec($session));
            if (count($phpObj->query->results->channel->item) > 0) {
                $str = array(
                    '{CITY}' => $phpObj->query->results->channel->location->city.', '.$phpObj->query->results->channel->location->country,
                    '{CURRENT}' => $phpObj->query->results->channel->item->condition->temp,
                    '{DATE}' => $phpObj->query->results->channel->item->forecast['0']->date,
                    '{1}' => $phpObj->query->results->channel->item->forecast['0']->low,
                    '{2}' => $phpObj->query->results->channel->item->forecast['0']->high
                );
                $txt = strtr(implode("\r\n", array_slice(self::lg()[self::$lang], 0, count(self::lg()[self::$lang]) - 1)), $str);
            } else
                $txt = array_pop(self::lg()[self::$lang]);
        }

        return
                $txt;
    }

}

$api = new api_messenger;
$body = json_decode(file_get_contents('php://input'));

foreach ($body->messages as $v) {
    if ($v->type == 'chat') {
        $api->get_lang($v->sender);
        $sendArray[] = array('chatId' => $v->sender, 'message' => $api->get_weather($v->body));
    }
}
if (count($sendArray) > 0) {
    $api->send_messages($sendArray);
    unset($sendArray);
}

You just have to substitute your token from the personal account into the $token variable

P.S.: If you do not have enough knowledge to write your own WhatsApp bot, we are always open to dialogue.