【问题标题】:Facebook webhook making multiple calls for the same message?Facebook webhook 多次调用同一条消息?
【发布时间】:2017-06-30 14:05:16
【问题描述】:

我使用 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,但我不确定你是否仍然遇到同样的问题。

【问题讨论】:

  • 在您需要发送 200 的每个请求上,也许您可​​以延迟处理您的 send_message,因此您将 ACK 发送到 Fb,然后您异步处理您的请求
  • 为什么在 post 数据中发送 statusCode: 200?
  • 我认为 Facebook 需要为每条消息发送 200 代码。 developers.facebook.com/docs/messenger-platform/…

标签: python facebook http python-requests chatbot


【解决方案1】:

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

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

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

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

所以很有可能您从 Facebook 正确获取了消息,但您仍然返回错误的状态代码,因为您正在从消息传递事件内部调用 send_message 方法,并且 send_message 方法应该返回状态“400 bad request”,因为您正在发送错误请求。因此,您的服务器也会返回错误的响应代码。

只要确保您的代码正常运行,并且应该返回 200。

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

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

【讨论】:

  • 非常感谢!我的代码抛出了错误,这就是为什么状态 200 没有返回并且我无休止地重复一个 webhook(未处理新消息的进一步 webhook)。在我修复了错误之后 - 没有重复的 webhook,webhook 也正确处理了进一步的消息。
【解决方案2】:

我正在使用 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 .....

我希望这对某人有所帮助。这让我发疯了。

【讨论】:

  • 感谢您的解决方案。不幸的是,上述方法仅适用于message 类型,不适用于postbacks。因为回发消息的负载中没有mid。有什么办法可以解决这个问题?
【解决方案3】:

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

响应 = requests.post(POST_MESSAGE_URL, headers={ “内容类型”:“应用程序/json” },参数={ 'access_token':访问令牌 }, 数据=json.dumps(DATA_JSON)

这段代码对我来说很好用

【讨论】:

  • 我有一个 django 应用程序,可以更轻松地从 Facebook 聊天中发送和接收消息。我可以分享我的代码。
  • 嗨,我试过了,但我仍然得到同样的错误。如果可能的话,你能分享一下代码吗?
  • 在这个应用程序中,它将所有类型的消息保存在相关的 django 模型中。我可以从 django 管理员创建模板消息,然后将其发送到 facebook.... 等
  • utils.py 和 views.py 对你来说更有趣
  • 200 状态码必须作为响应。你不需要发送它。我认为错误一定在其他地方。
【解决方案4】:

我有 Java 背景,但我仍会尽力帮助您。

在处理 webhook 挑战中,我可以看到您返回 200 状态代码

但是在句柄消息块中没有返回 200 您在发送消息中设置了 200 状态码。但是你必须从句柄消息块中返回 200 是行不通的。

即使此块中发生任何异常,也应返回 200,否则将被阻止。所以可能在 finally 块中你可以返回 200。

【讨论】:

    【解决方案5】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-18
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      • 2019-11-24
      相关资源
      最近更新 更多