Facebook webhook 多次调用同一条消息?

Facebook webhook making multiple calls for the same message?

我使用 Python 和无服务器在 AWS 上制作并回应了机器人。

我不断收到相同的请求。 我阅读了常见问题解答,它说你必须提供状态代码 200,否则它将继续重试 webhook。

我不确定我该怎么做。

我注意到调用的序列号始终相同,因此我假设我发送的回复未被确认。 我的代码在这里

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

我在很多地方都给出了状态代码 200,但我不确定我是否仍然遇到同样的问题。

我来自 Java 背景,但我仍然会尽力帮助您。

在处理 webhook 挑战时我可以看到你 returning 200 状态码

但在处理消息块 200 时未 returned 您在发送消息中设置了 200 状态代码。但它不会工作你必须 return 200 从句柄消息块。

另外 200 应该被 returned 即使在这个块中发生任何异常,否则在异常时它会被阻止。所以可能在 finally 块中你可以 return 200.

如果您收到多条消息,您的服务器 没有 return 200 状态代码到来自 Facebook 服务器的 webhook 请求。这意味着您发生了错误,否则 200 应该 returned。在我看来,问题出在以下几行:

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}})

首先,您在消息的数据主体中传递 statusCode,根据此 documentation 消息响应不应包含它。

另一个问题可能是在参数中发送状态代码。我将从 send_message 方法中完全删除状态代码。我怀疑那里需要它。您基本上是在错误地尝试 return 状态 200。您正在尝试 return 它输出而不是输入(从 Facebook 的角度来看)。

所以很可能您从 Facebook 正确地收到了消息,但您仍然 returning 了错误的状态代码,因为您正在从消息传递事件和 send_message 方法内部调用 send_message 方法应该 return 状态为“400 错误请求”,因为您正在发送错误的请求。因此您的服务器也 return 错误的响应代码。

只需确保您的代码工作正常,200 应该 returned。

编辑: 所以我会尝试使用以下代码:

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

当 Facebook 调用时,您的 webhook 回调应该始终 return 200 OK HTTP 响应。如果不这样做,可能会导致您的 webhook 被 Messenger 平台取消订阅。 (从 Messenger 文档中复制。) 您必须从 returning 回复中搜索问题。与发送数据无关

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

这段代码对我来说工作正常

作为替代方案,您可以使用 chatbotproxy.com,它总是在 1 毫秒内 return 200,并将完全相同的请求传递到您的端点。由于立即响应对于 Facebook Messenger 平台非常重要,因此 1 毫秒时间是一个非常有前途的功能。如果您需要帮助来尝试,请告诉我。

我正在使用 Node/Express 服务器开发 Facebook Messenger 聊天机器人,但遇到了完全相同的问题。服务器适当地发送了 200 个响应,但问题仍然存在。我通过缓存消息 ID 并在处理之前检查重复项解决了这个问题:

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 .....

我希望这对某人有所帮助。快把我逼疯了。