8

I made and echo bot on AWS with Python and serverless.

I keep getting the same request again and again. I read the faq where it says u have to deliver a status code 200 else it will keep retrying the webhook.

I'm not sure How I do this.

I have noticed that the sequence number is always the same for the calls so I assume the reply I sent was not acknowledged. my code is here

import os
import json
import requests
import random
from datetime import datetime
######################
# helper functions
######################
##recursively look/return for an item in dict given key
def find_item(obj, key):
    item = None
    if key in obj: return obj[key]
    for k, v in obj.items():
        if isinstance(v,dict):
            item = find_item(v, key)
            if item is not None:
                return item

##recursivley check for items in a dict given key
def keys_exist(obj, keys):
    for key in keys:
        if find_item(obj, key) is None:
            return(False)
    return(True)

##send txt via messenger to id
def send_message(send_id, msg_txt):
    print("Send message called")
    print (datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3])
    params  = {"statusCode": 200,"access_token": os.environment['accesstoken']}
    headers = {"statusCode": "200","Content-Type": "application/json"}
    data = json.dumps({"statusCode": "200","recipient": {"id": send_id},
                       "message": {"text": msg_txt}})

    r = requests.post("https://graph.facebook.com/v2.9/me/messages", params=params, headers=headers, data=data)
    print (r.text)

    if r.status_code != 200:
        print(r.status_code)
        print(r.text)



#-----------------------------------------------------------

def hello(event, context):
    #debug
    event=json.loads(json.dumps(event))
    print("event:" )
    print(event)
    # print("context")
    # print(context)


    #handle webhook challenge
    try:

        if keys_exist(event, ["queryStringParameters","hub.verify_token","hub.challenge"]):
            print("subscribe to webhook invoked")
            v_token   = str(find_item(event, 'hub.verify_token'))
            challenge = find_item(event, 'hub.challenge')
            if ("strongtoken" == v_token):
                response = {
                    "statusCode": 200,
                    "body": str(challenge)
                }
                print(challenge)
                return response

        #handle messaging events
        if keys_exist(event, ['body']):
            event_entry=json.loads(event['body'])
            if ((len(event_entry['entry'])>0) & (keys_exist(event_entry['entry'][0],['messaging'])) ):
                messaging_event = event_entry['entry'][0]['messaging'][0]
                if (keys_exist(messaging_event,['message'])):
                    msg_txt   = messaging_event['message']['text']
                    sender_id = messaging_event['sender']['id']
                    print(sender_id)
                    first_word = msg_txt.split(" ")[0]
                    send_message(sender_id, msg_txt)
                else:
                    print("Did not send message")
                    pass
            else:
                print("Did not send message")
                pass

        else:
            pass
    except:
        pass

I have given the status code 200 in soo many places and I'm not sure y I still keep getting the same problem.

SitiSchu
  • 1,361
  • 11
  • 20
Arsenal Fanatic
  • 3,663
  • 6
  • 38
  • 53
  • on each request you need to send the 200, maybe you can handle your send_message on delay, so you send the ACK to Fb then you handle your request asynchroniously – kaizer Jul 05 '17 at 12:14
  • why are sending statusCode: 200 in post data? – Erdenezul Jul 06 '17 at 13:57
  • I thought Facebook required the 200 code to be sent for every message. https://developers.facebook.com/docs/messenger-platform/webhook-reference#response – Arsenal Fanatic Jul 06 '17 at 14:09

5 Answers5

6

If you are getting multiple messages your server did not return 200 status code to webhook request from Facebook server. This means an error occurred on your part otherwise 200 should be returned. It looks to me that problems are in following lines:

params  = {"statusCode": 200,"access_token": os.environment['accesstoken']}
headers = {"statusCode": "200","Content-Type": "application/json"}
data = json.dumps({"statusCode": "200","recipient": {"id": send_id},
                   "message": {"text": msg_txt}})

Firstly you are passing statusCode in a data body of message and according to this documentation message response should not contain it.

Another problem could be sending status code inside params. I would remove status code completely from send_message method. I doubt its needed there. You are basically trying to return status 200 on wrong end. You are trying to return it on output instead of input (from Facebooks point of view).

So its quite possible you are correctly getting message from Facebook but you are still returning wrong status code because you are calling send_message method from inside messaging event and send_message method should return status "400 bad request" because you are sending faulty request. Thus your server also returns wrong response code.

Just make sure your code works correctly and 200 should be returned.

EDIT: So i would try with following code:

params  = {"access_token": os.environment['accesstoken']}
headers = {"Content-Type": "application/json"}
data = json.dumps({"recipient": {"id": send_id},
                   "message": {"text": msg_txt}})
dafilipaj
  • 1,064
  • 14
  • 24
  • Thanks a lot! My code throwed error that's why status 200 wasn't returning and I've got endless repeating of one webhook (further webhooks for new messages were not handled). After I've fixed error - no repeating webhooks and further messages are also handled correctly by webhook. – PokatilovArt Aug 19 '20 at 22:16
4

I'm working on a Facebook Messenger chatbot with a Node/Express server and was having the same exact issue. The server was appropriately sending 200 responses and yet the issue persisted. I resolved the problem by caching message ID's and checking for duplicates before processing:

var NodeCache = require('node-cache');
var myCache = new NodeCache();

app.post('/webhook/', function(req, res) {
    var messageID = req.body.entry[0].messaging[0].message.mid;
    var checkForDupe = myCache.get(messageID);

    if (checkForDupe == undefined) {
        var setID = myCache.set(req.body.entry[0].messaging[0].message.mid, req.body.entry[0].messaging[0].message.mid);
        //Handle message .....

I hope this helps someone. It was driving me nuts.

  • Thanks for the solution. Unfortunately, the above method works only for type `message` not for `postbacks`. Because postback messages don't have `mid` in their payload. Any way to get around this? – Thilak Feb 17 '20 at 11:21
1

Your webhook callback should always return a 200 OK HTTP response when invoked by Facebook. Failing to do so may cause your webhook to be unsubscribed by the Messenger Platform. (copied from messenger docs.) You have to search problem from your returning response. It is not with the sending data.

response = requests.post(POST_MESSAGE_URL, headers={
            'Content-Type': 'application/json'
        }, params={
            'access_token': ACCESS_TOKEN
        }, data=json.dumps(DATA_JSON)

this code working fine for me

Erdenezul
  • 597
  • 1
  • 7
  • 10
0

I am from Java background but still I will try to help you.

In handle webhook challenge I can see you returning 200 status code

But in handle messaging block 200 is not returned You have set 200 status code in send message. But it will not work you have to return 200 from handle messaging block.

Also 200 should be returned even if any exception occurs in this block otherwise on exception it will get blocked. So may be in finally block you can return 200.

raja pateriya
  • 332
  • 2
  • 15
0

As an alternative, you can use chatbotproxy.com which always return 200 in 1ms and pass the exact same request to your endpoint. Since immediate response is very important for Facebook Messenger platform, 1 millisecond time is a very promising feature. If you need help to try, let me know.