Бот Facebook Chat (веб-перехватчик PHP) отправляет несколько ответов

Мой чат-бот Facebook работает, но отправляет несколько сообщений после моего первоначального сообщения. Это мой сценарий веб-перехватчика (я ценю, что это очень грубый рабочий пример):

$challenge = $_REQUEST['hub_challenge'];
$verify_token = $_REQUEST['hub_verify_token'];

if ($verify_token === 'MY_VERIFICATION_TOKEN') {
  echo $challenge;
}

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

$sender = $input['entry'][0]['messaging'][0]['sender']['id'];
$message = $input['entry'][0]['messaging'][0]['message']['text'];


//API Url
$url = 'https://graph.facebook.com/v2.6/me/messages?access_token=<my-token>';

//Initiate cURL.
$ch = curl_init($url);

//The JSON data.
$jsonData = '{
    "recipient":{
        "id":"'.$sender.'"
    }, 
    "message":{
        "text":"Hey Lee!"
    }
}';

//Encode the array into JSON.
$jsonDataEncoded = $jsonData;

//Tell cURL that we want to send a POST request.
curl_setopt($ch, CURLOPT_POST, 1);

//Attach our encoded JSON string to the POST fields.
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncoded);

//Set the content type to application/json
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));

//Execute the request
$result = curl_exec($ch);

person Lee Woodman    schedule 13.04.2016    source источник


Ответы (3)


Я думаю, это потому, что вы не проверяете, пусты ли отправленные сообщения:

попробуйте это вместо этого:

$challenge = $_REQUEST['hub_challenge'];
$verify_token = $_REQUEST['hub_verify_token'];

if ($verify_token === 'MY_VERIFICATION_TOKEN') {
  echo $challenge;
}

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

$sender = $input['entry'][0]['messaging'][0]['sender']['id'];
$message = $input['entry'][0]['messaging'][0]['message']['text'];


//API Url
$url = 'https://graph.facebook.com/v2.6/me/messages?access_token=<my-token>';

//Initiate cURL.
$ch = curl_init($url);

//The JSON data.
$jsonData = '{
    "recipient":{
        "id":"'.$sender.'"
    }, 
    "message":{
        "text":"Hey Lee!"
    }
}';

//Encode the array into JSON.
$jsonDataEncoded = $jsonData;

//Tell cURL that we want to send a POST request.
curl_setopt($ch, CURLOPT_POST, 1);

//Attach our encoded JSON string to the POST fields.
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncoded);

//Set the content type to application/json
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));

//Execute the request
if(!empty($input['entry'][0]['messaging'][0]['message'])){
$result = curl_exec($ch);
}
person Normann Marit    schedule 14.04.2016
comment
Вместо этого появляются эти странные ошибки: `‹br /› ‹b›Deprecated‹/b›: автоматическое заполнение $HTTP_RAW_POST_DATA устарело и будет удалено в будущей версии. Чтобы избежать этого предупреждения, установите для параметра «always_populate_raw_post_data» значение «-1» в php.ini и вместо этого используйте поток ввода php://. in ‹b›Неизвестно‹/b› в строке ‹b›0‹/b›‹br /› ‹br /› ‹b›Предупреждение‹/b›: Невозможно изменить информацию заголовка — заголовки уже отправлены в ‹b›Неизвестно‹ /b› в строке ‹b›0‹/b›‹br /› {ошибка: {сообщение: неверный токен доступа OAuth., тип: OAuthException, код: 190, fbtrace_id: BsNG\/mJVYem}} ^As - person Volatil3; 21.04.2016
comment
Вам нужно поставить exit(); после эха $challenge; линия - person mileusna; 17.05.2016
comment
Я также сталкиваюсь с подобной проблемой, но я добавил проверку на пустое сообщение (доставку). Когда я проверил URL-адрес веб-перехватчика, кажется, что он попал дважды. Я использую ngrok с локальным сервером в качестве веб-перехватчика, и я ясно вижу, что к URL-адресу веб-перехватчика обращаются дважды, при этом поле сообщения заполняется оба раза. Есть идеи?? - person thekosmix; 16.06.2016
comment
Спасибо за этот ответ! Оно работает! Странный баг... :) - person Seishin; 23.08.2016

FB передает URL-адрес вашего веб-перехватчика исходному входящему сообщению, и вы его обрабатываете. Затем вы отправляете ответ пользователю, и сценарий завершается. Затем, как только сообщение доставлено пользователю, FB отправляет подтверждение доставки на URL-адрес веб-перехватчика. Поскольку ваш сценарий всегда настроен на отправку «Эй, Ли!» каждый раз, когда он вызывается, обратный вызов доставки фактически запускает отправку другого сообщения, а затем приходит другое подтверждение доставки, а затем этот процесс повторяется сам. Чтобы исправить это, поместите оператор if вокруг своего кода, чтобы отправить сообщение. Вот пример.

$challenge = $_REQUEST['hub_challenge'];
$verify_token = $_REQUEST['hub_verify_token'];

if ($verify_token === 'MY_VERIFICATION_TOKEN') {
  echo $challenge;
}

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

$sender = $input['entry'][0]['messaging'][0]['sender']['id'];
$message = $input['entry'][0]['messaging'][0]['message']['text'];


//API Url
$url = 'https://graph.facebook.com/v2.6/me/messages?access_token=<my-token>';

//Initiate cURL.
$ch = curl_init($url);

if($message=="hello")
{
        //The JSON data.
        $jsonData = '{
        "recipient":{
                "id":"'.$sender.'"
        },
        "message":{
                "text":"Hey Lee!"
        }
        }';
}

//Encode the array into JSON.
$jsonDataEncoded = $jsonData;

//Tell cURL that we want to send a POST request.
curl_setopt($ch, CURLOPT_POST, 1);

//Attach our encoded JSON string to the POST fields.
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncoded);

//Set the content type to application/json
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));

//Execute the request
$result = curl_exec($ch);

Надеюсь, это поможет.

person Drew Smith    schedule 14.04.2016
comment
Я использую пример. Webhook был проверен, когда я пытаюсь отправить сообщение своему боту, он ничего не возвращает. Я тоже не знаю, как отлаживать страницу Webhooked - person Volatil3; 21.04.2016
comment
У меня тоже была проблема отладки, но поскольку Drupal (бэкэнд-платформа для моего чат-бота) крут, у него есть функция Watchdog, которая представляет собой модуль ведения журнала, поэтому вы можете отправлять все в Watchdog для отладки. Очень сильно упрощает процесс. Вот так: $input = json_decode(file_get_contents('php://input'), true); watchdog(Получены данные веб-перехватчика, '‹pre›' . print_r( $input, true) . '‹/pre›'); - person Lee Woodman; 06.05.2016
comment
Тот факт, что для подтверждения доставки выложен вебхук, меня поразил. Большое спасибо @Drew. - person nikk wong; 15.06.2016
comment
классное объяснение. имеет смысл. - person lilsizzo; 14.09.2016

Пробовал то же самое, первый запрос содержит фактическое сообщение пользователя, а другие запросы - нет. Я просто отправляю ответ, если
$message = $input['entry'][0]['messaging'][0]['message']['text']; не равен нулю:

if ($message){
//send your message here
}
person Antonis Polychroniou    schedule 18.11.2016
comment
Как отправить несколько ответов на одно сообщение, если кто-то говорит привет, бот должен ответить привет (1-е сообщение), как вас зовут (2-е сообщение) .. - person Srinivas08; 01.03.2018