11

When using the same Facebook getting started guide (https://developers.facebook.com/docs/messenger-platform/quickstart)

I am getting an error on the node.js console when typing a message and sending it to the bot.

   { error: 
      { message: '(#100) No matching user found',
        type: 'OAuthException',
        code: 100,
        fbtrace_id: 'BLguK1o+VsH' } } } 

I have the latest version of node.js and am using Ngrok to expose my local host.

My app.post routine is below: (It is an exact copy of the getting started guide)

router.post('/webhook', function (req, res) {
  var data = req.body;

  // Make sure this is a page subscription
  if (data.object == 'page') {
    // Iterate over each entry
    // There may be multiple if batched
    data.entry.forEach(function(pageEntry) {
      var pageID = pageEntry.id;
      var timeOfEvent = pageEntry.time;

      // Iterate over each messaging event
      pageEntry.messaging.forEach(function(messagingEvent) {
        if (messagingEvent.optin) {
          receivedAuthentication(messagingEvent);
        } else if (messagingEvent.message) {
          receivedMessage(messagingEvent);
        } else if (messagingEvent.delivery) {
          receivedDeliveryConfirmation(messagingEvent);
        } else if (messagingEvent.postback) {
          receivedPostback(messagingEvent);
        } else {
          console.log("Webhook received unknown messagingEvent: ", messagingEvent);
        }
      });
    });

    // Assume all went well.
    //
    // You must send back a 200, within 20 seconds, to let us know you've 
    // successfully received the callback. Otherwise, the request will time out.
  //  res.sendStatus(200);
  }
}); 

Here is the receivedMessage function that is being called

function receivedMessage(event) {
  var senderID = event.sender.id;
  var recipientID = event.recipient.id;
  var timeOfMessage = event.timestamp;
  var message = event.message;

  console.log("Received message for user %d and page %d at %d with message:", 
    senderID, recipientID, timeOfMessage);
    console.log(JSON.stringify(message));


  var messageId = message.mid;

  // You may get a text or attachment but not both
  var messageText = message.text;
  var messageAttachments = message.attachments;

  if (messageText) {

    // If we receive a text message, check to see if it matches any special
    // keywords and send back the corresponding example. Otherwise, just echo
    // the text we received.
    switch (messageText) {
      case 'image':
        sendImageMessage(senderID);
        break;

      case 'button':
        sendButtonMessage(senderID);
        break;

      case 'generic':
        sendGenericMessage(senderID);
        break;

      case 'receipt':
        sendReceiptMessage(senderID);
        break;

      default:
        //getArticles(function(err,articles){
        //  sendTextMessage(senderID, articles[0].text);
        //});     
        sendTextMessage(senderID, messageText);

       /* client.converse('my-user-session-42', messageText, {})
            .then((data) => {
                console.log('the question asked :' + messageText);
            sendTextMessage(senderID, data.msg);    
            console.log('Yay, got Wit.ai response: ' + JSON.stringify(data));
        }).catch(console.error);
        */


    }
  } else if (messageAttachments) {
    sendTextMessage(senderID, "Message with attachment received");
  }
}

Further more here are my require statements:

const bodyParser = require('body-parser');
var express = require('express');
var request = require('request');
var router = express.Router();
const fetch = require('node-fetch');
const {Wit, log} = require('node-wit');

Here is the rest of the functions used:

function sendTextMessage(recipientId, messageText) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };

  callSendAPI(messageData);
}

function callSendAPI(messageData) {
  request({
    uri: 'https://graph.facebook.com/v2.6/me/messages',
    qs: { access_token: PAGE_ACCESS_TOKEN },
    method: 'POST',
    json: messageData

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      console.log("Successfully sent generic message with id %s to recipient %s", 
        messageId, recipientId);
    } else {
      console.error("Unable to send message.");
      console.error(response);
      console.error(error);
    }
  });  
}

So I read somewhere that it all has to do with page ids or the way that facebook processes ints but I'm a little confused.

Any help would be much appreciated.

Ethan Richardson
  • 461
  • 2
  • 10
  • 28
  • I'm receiving the same error message, and everything here worked a couple of days ago. Can't find any news on breaking changes either. So unstable. – AndreasB Jul 08 '16 at 07:59
  • It's so frustrating as I can't seem to get the official tutorial code to work and I want to understand it and continue to work – Ethan Richardson Jul 08 '16 at 08:11
  • Suddenly those weird errors are gone and I'm able to successfully send/receive messages again. Are you experiencing the same? – AndreasB Jul 08 '16 at 08:36
  • At times it works but now I am getting constant echoes of the message I have typed in. It seems like there is a loop somewhere that I can find. – Ethan Richardson Jul 08 '16 at 08:49
  • So I type on Hi and I am receiving like 10 or more hi messages back from the server. – Ethan Richardson Jul 08 '16 at 08:53
  • Really. Was it a loop on your side? When I received that "no matching user found" error, I probably received 6-7 error webhook requests in a row from them. Maybe something similar is happening for you? – AndreasB Jul 08 '16 at 09:17
  • I haven't solved it yet, I'm looking at why this is happening, have you solved it? I looks like there is a no matching user error and then it tries to resend the message back to the user. – Ethan Richardson Jul 08 '16 at 09:52
  • It was solved pretty much out of the blue here. Can't remember doing anything of actual significance to make it work again (adding and removing some console.logs). However, most of my bot broke a couple of days ago. For some reason the Facebook developer page showed that it was no longer connected to the Page it was supposed to be connected to (don't ask me why, I'm never in the developer pages). Maybe they've reset or defaulted something. Hopeless situation spending two days trying to fix this. – AndreasB Jul 08 '16 at 09:58
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/116785/discussion-between-user1907509-and-andreasb). – Ethan Richardson Jul 08 '16 at 10:21
  • 3
    I had same experience earlier today and figured out it was due to the new echo feature for Facebook Messenger bots causing it to loop and then throw error as stated above (since it eventually tries to send to the page id and not the user id). My solve was to check for `message.is_echo`. If true log it and don't perform any further action(s). This happens since Facebook treats echoes just like messages, i.e. they don't have a flag anywhere but the `is_echo` field (see: https://developers.facebook.com/docs/messenger-platform/webhook-reference/message-echo) – Thomas Jul 08 '16 at 22:02
  • Hi @Thomas I can see your point and want to know what you meant by 'If true log it and don't perform any further actions. I can see what you mean by message.is_echo and I am skipping this element of the messaging_events. var messaging_events = req.body.entry[0].messaging – Ethan Richardson Jul 10 '16 at 18:52
  • @user1907509 W. logging I just meant a simple `console.log` to easily confirm when a message has an `is_echo` value. – Thomas Jul 11 '16 at 20:46

7 Answers7

20

This error occurs because the incorrect token is being used to send messages back to the bot. Ensure you have the correct one (even by hard-coding it at first), which can be copied from your developers.facebook.com page under Messenger -> Settings -> Token Generation.

Michael
  • 201
  • 2
  • 4
  • The tokens change occasionally. In the app settings, we have to choose the associated FB page and generate the token. After that, we have to resubscribe the application like this: https://developers.facebook.com/docs/messenger-platform/webhook-reference#subscribe – Carmela Oct 17 '16 at 09:21
6

You just need to bypass your own messages.

Your Bot has an unique ID (it's not the App ID), so you can try this workaround in your POST logic:

var myID = '...' ;
.....
event = req.body.entry[0].messaging[i];
sender = event.sender.id;
if (event.message && event.message.text && sender != myID) {
.....
}

You can obtain your Bot id by reviewing your messages:

"sender":{
    "id":"USER_ID"
  },

Message Received reference

JSON sample:

even.message: 
 {"sender":{"id":"**yourBotID**"},
   "recipient":{"id":"**clientID**"},
   "timestamp":1468241667962,
   "message":   {"**is_echo":true**,        
   "app_id":**appID**,
   "mid":"mid....",
   "seq":617,"text":"..."}}

Tip: to identify your BotID just look for "message": {"is_echo": true,.. in message payload.

Regards

Daniel Vukasovich
  • 1,692
  • 1
  • 18
  • 26
5

I went to Facebook Messenger Settings -> Webhooks -> Edit events and removed messenger_echoes from the subscribed events. This solved the issue.

Serge
  • 71
  • 1
  • 3
2

I followed this guide http://x-team.com/2016/04/how-to-get-started-with-facebook-messenger-bots/

and it all worked:

I have posted my code below:

'use strict'
const bodyParser = require('body-parser');
var express = require('express');
var request = require('request');
var app = express();
const fetch = require('node-fetch');
const {Wit, log} = require('node-wit');


app.use(bodyParser.urlencoded({extended: false}))

var PAGE_ACCESS_TOKEN =  '********'
var MY_TOKEN = '********';

//  Wit.ai code 
const client = new Wit({accessToken: '*********'});


//  GET home page. 
app.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

app.get('/webhook/', function(req, res) {
  if (req.query['hub.mode'] === 'subscribe' &&
      req.query['hub.verify_token'] === 'hello_token_success') {
    console.log("Validating webhook");
    res.status(200).send(req.query['hub.challenge']);
  } else {
    console.error("Failed validation. Make sure the validation tokens match.");
    res.sendStatus(403);          
  }  
});

//** Receive Messages **

app.post('/webhook/', function (req, res) {

  var data = req.body; 

  var events = req.body.entry[0].messaging;

  for (var i = 0; i < events.length ; i++) {


    var event = events[i];

    if (event.message && event.message.text && !event.message.is_echo) {
        var text = event.message.text;

        sendTextMessage(event.sender.id, "Text received, echo: "+ text.substring(0, 200));
    }

  }


    // Assume all went well.
    //
    // You must send back a 200, within 20 seconds, to let us know you've 
    // successfully received the callback. Otherwise, the request will time out.
    res.sendStatus(200);

});



function receivedMessage(event) {
  var senderID = event.sender.id.toString();
  var recipientID = event.recipient.id.toString();
  var timeOfMessage = event.timestamp;
  var message = event.message;

  console.log("Received message for user %d and page %d at %d with message:", 
    senderID, recipientID, timeOfMessage);
  console.log(JSON.stringify(message));

  var messageId = message.mid;

  // You may get a text or attachment but not both
  var messageText = message.text;
  var messageAttachments = message.attachments;

  if (messageText && !message.is_echo) {

    // If we receive a text message, check to see if it matches any special
    // keywords and send back the corresponding example. Otherwise, just echo
    // the text we received.
    switch (messageText) {
      case 'image':
        sendImageMessage(senderID);
        break;

      case 'button':
        sendButtonMessage(senderID);
        break;

      case 'generic':
        sendGenericMessage(senderID);
        break;

      case 'receipt':
        sendReceiptMessage(senderID);
        break;

      default:
        sendTextMessage(senderID, messageText);
    }
  } else if (messageAttachments) {
    sendTextMessage(senderID, "Message with attachment received");
  }
}



function sendGenericMessage(recipientId) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      attachment: {
        type: "template",
        payload: {
          template_type: "generic",
          elements: [{
            title: "rift",
            subtitle: "Next-generation virtual reality",
            item_url: "https://www.oculus.com/en-us/rift/",               
            image_url: "http://messengerdemo.parseapp.com/img/rift.png",
            buttons: [{
              type: "web_url",
              url: "https://www.oculus.com/en-us/rift/",
              title: "Open Web URL"
            }, {
              type: "postback",
              title: "Call Postback",
              payload: "Payload for first bubble",
            }],
          }, {
            title: "touch",
            subtitle: "Your Hands, Now in VR",
            item_url: "https://www.oculus.com/en-us/touch/",               
            image_url: "http://messengerdemo.parseapp.com/img/touch.png",
            buttons: [{
              type: "web_url",
              url: "https://www.oculus.com/en-us/touch/",
              title: "Open Web URL"
            }, {
              type: "postback",
              title: "Call Postback",
              payload: "Payload for second bubble",
            }]
          }]
        }
      }
    }
  };  

  callSendAPI(messageData);
}

function receivedPostback(event) {
  var senderID = event.sender.id;
  var recipientID = event.recipient.id;
  var timeOfPostback = event.timestamp;

  // The 'payload' param is a developer-defined field which is set in a postback 
  // button for Structured Messages. 
  var payload = event.postback.payload;

  console.log("Received postback for user %d and page %d with payload '%s' " + 
    "at %d", senderID, recipientID, payload, timeOfPostback);

  // When a postback is called, we'll send a message back to the sender to 
  // let them know it was successful
  sendTextMessage(senderID, "Postback called");
}

function sendTextMessage(recipientId, messageText) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };

  callSendAPI(messageData);
}

function callSendAPI(messageData) {
  request({
    uri: 'https://graph.facebook.com/v2.6/me/messages',
    qs: { access_token: PAGE_ACCESS_TOKEN },
    method: 'POST',
    json: messageData

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      console.log("Successfully sent generic message with id %s to recipient %s", 
        messageId, recipientId);
    } else {
      console.error("Unable to send message.");
      console.error(response);
      console.error(error);
    }
  });  
}



module.exports = app; 
Ethan Richardson
  • 461
  • 2
  • 10
  • 28
1

Make sure you have used correct ID of recipient. Recipient is not the page or app ID but it is (if you want to send message to the user) ID of the user.

You can configure webhook such as https://requestb.in and examine requests from messanger and the ID which you are looking for is:

{"sender":{"id":"1499894473423552"}}
Damian
  • 437
  • 5
  • 11
1

I would like to share my experience. I was getting the same error when calling the v15.0/me/messages API.

I was using a test version of my app. When I started using my app directly, the error disappeared. It seemed, at least for my case, is that test apps do not look up users.

orabis
  • 2,749
  • 2
  • 13
  • 29
0

i removed message echoes in events, and selected only messaging and postbacks, it solved the problem