0

I am getting started on a messenger bot and am getting the above error. I have the following code:

app.post('/webhook', (req, res) => {
  console.log(req.body);
  if (req.body.object === 'page') {
    req.body.entry.forEach((entry) => {
      entry.messaging.forEach((event) => {
        if (event.message.text === 'buy') {
          sendGenericMessage(event)
        } else if (event.postback) {
          processPostback(event)}
      });
    });
    res.status(200).end();
  }
});

function sendGenericMessage(event) {
  const senderID = event.sender.id;

  var messageData = {
    "attachment":{
      "type":"template",
      "payload":{
        "template_type":"generic",
        "elements":[
           {
            ...
            "buttons":[
              {
                "type":"postback",
                "title":"Purchase",
                "payload":"PURCHASE_PAYLOAD"
              },{
                "type":"postback",
                "title":"Start Chatting",
                "payload":"DEVELOPER_DEFINED_PAYLOAD"
              }
            ]
          }, {
           "title":"Welcome to Peter\'s Hats",
           "image_url":"https://static.pexels.com/photos/177809/pexels-photo-177809.jpeg",
           "subtitle":"We\'ve got the right hat for everyone.",
           "buttons":[
             {
               ...
             }
           ]
         }
        ]
      }
    }
  }

  request({
    url: 'https://graph.facebook.com/v2.6/me/messages',
    qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
    method: 'POST',
    json: {
      recipient: {id: senderID},
      message: messageData
    }
  }, function (error, response) {
    if (error) {
        console.log('Error sending message: ', error);
    } else if (response.body.error) {
        console.log('Error: ', response.body.error);
    }
  });
}

function processPostback(event) {
  const senderID = event.sender.id;
  const payload = event.postback.payload;

 if (payload === "PURCHASE_PAYLOAD") {
    var message = event.message.text + " payment"
    sendMessage(event, message)
  }
}

When I type 'buy', the bot will reply with a generic template, and when the button 'purchase' is pressed, the bot crashed. My error logs are as follows:

enter image description here

I have searched and found similar problems like so, but mine originates from postbacks instead of text message as compared to theirs. How to avoid 'cannot read property of undefined' errors?

I'm having "TypeError: Cannot read property 'text' of undefined" while developing Facebook Messenger bot

Some help here would be great, thanks.

Koh
  • 2,687
  • 1
  • 22
  • 62

1 Answers1

1

As it is mentioned on the Webhook Reference for Messenger Platform, there is no property "message" inside the postback call in your webhook.

For postbacks, instead of accessing the "message" property, you have to access the "payload" property to get the data associated with the postback call (In your case the payload of the button pressed).

For this to work, I would firstly add some things inside the payload of the button pressed like this:

"buttons":
  [
    {
      "type":"postback",
      "title":"Purchase",
      "payload": "{"type": "PURCHASE_PAYLOAD", "message": "WHATEVER YOU WANT"}"
    },
    {
      "type":"postback",
      "title":"Start Chatting",
      "payload":"DEVELOPER_DEFINED_PAYLOAD"
    }
  ]

Then I rewrite the processPostback function of your code in this way:

function processPostback(event) {
  const senderID = event.sender.id;
  const payload = JSON.parse(event.postback.payload);

  if (payload.type === "PURCHASE_PAYLOAD") {
    var message = payload.message + " payment"
    sendMessage(event, message)
  }
}

With those changes you actually pass the message that you want to send inside the payload of the button pressed so that anytime the user pushed the button your code knows what to send.

You'll also need to change the code in entry.messaging.forEach. Because your code, tries to access the event.message property which in the case of postbacks doesn't exist (is undefined), so when you try to access a subproperty of event.message (event.message.text), the code exits with an error. So to mitigate this you can check everytime if the .message property is defined, like this:

entry.messaging.forEach((event) => {
  if (event.message) {
    if (event.message.text === 'buy') {
      sendGenericMessage(event)
    }
  } else if (event.postback) {
    processPostback(event)
  }
});
  • Hi @christos, thanks for your response. I have attempted your solution, but it throws an error (#100) invalid data. Referring to the error log above, it seems to suggest that the error of 'Cannot read text property' happens at entry.messaging.forEach. Does this mean that the 'Purchase' button is not recognized as a message? – Koh Jun 19 '17 at 14:14
  • I edited my response to add another change important change in the code. :) – Christos Panagiotakopoulos Jun 19 '17 at 15:04
  • I had a small mistake in the code too. Copy paste the code again ;) – Christos Panagiotakopoulos Jun 19 '17 at 15:12