为 Twitter 注册 Webhook 的过程是什么?

what is the procedure of registering the webhook for twitter?

我正在尝试通过 twitter 文档中提供的 curl 命令在 twitter 上将 url 注册为 webhook。我认为 Twitter 文档有点过时或不正确。

 curl --request POST --url "https://api.twitter.com/1.1/account_activity/all/prod/webhooks.json?url=https%3A%2F%2FXXXX.com%2Fwebhook%2Ftwitter" --header "authorization: OAuth oauth_consumer_key='XXXXXXXXXXXXXXXXXXXXXX', oauth_nonce='ODgyNjc5NjQ0MTM3NzI4NTcwMjY4NDQ0', oauth_signature='7daMyzB1JClE4xv8hXNCimWpGtA%3D', oauth_signature_method='HMAC-SHA1', oauth_timestamp='1568620293', oauth_token='XXXXXXXXXXXXXXXXXXXXX', oauth_version='1.0'"

在 运行 这段代码之后,我收到错误

{"errors":[{"code":215,"message":"Bad Authentication data."}]}

我用来生成时间戳的代码,oauth_nonce,oauth_signature如下。这些代码在 python3 中。我不太确定他们是否给出了正确的输出。

oauth_timestamp = str(int(time.time()))


#oauth_nonce
def get_nonce():
    nonce = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits)for x in range(32))
return nonce


#oauth_signature

def escape(s):
"""Percent Encode the passed in string"""
    return urllib.parse.quote_plus(s, safe='~')


def create_auth_header(parameters):
"""For all collected parameters, order them and create auth header"""
    ordered_parameters = {}
    ordered_parameters =  collections.OrderedDict(sorted(parameters.items()))
    auth_header = (
    '%s="%s"' % (k, v) for k, v in ordered_parameters.items())
    val = "OAuth " + ', '.join(auth_header)
    return val


def generate_signature(method, url, url_parameters, oauth_parameters, oauth_consumer_key, oauth_consumer_secret, oauth_token_secret=None, status=None):
    """Create the signature base string"""

    #Combine parameters into one hash
    temp = collect_parameters(oauth_parameters, status, url_parameters)

    #Create string of combined url and oauth parameters
    parameter_string = stringify_parameters(temp)

    #Create your Signature Base String
    signature_base_string = (
    method.upper() + '&' +
    escape(str(url)) + '&' +
    escape(parameter_string)
    )

    #Get the signing key
    signing_key = create_signing_key(oauth_consumer_secret, oauth_token_secret)

    return calculate_signature(signing_key, signature_base_string)



 def stringify_parameters(parameters):
     """Orders parameters, and generates string representation of parameters"""
     output = ''
     ordered_parameters = {}
     ordered_parameters =  collections.OrderedDict(sorted(parameters.items()))

     counter = 1
     for k, v in ordered_parameters.items():
          output += escape(str(k)) + '=' + escape(str(v))
          if counter < len(ordered_parameters):
              output += '&'
              counter += 1

     return output



def collect_parameters(oauth_parameters, status, url_parameters):
    """Combines oauth, url and status parameters"""
    #Add the oauth_parameters to temp hash
    temp = oauth_parameters.copy()

    #Add the status, if passed in.  Used for posting a new tweet
    if status is not None:
        temp['status'] = status

    #Add the url_parameters to the temp hash
    for k, v in url_parameters.items():
        temp[k] = v

    return temp




def calculate_signature(signing_key, signature_base_string):
    """Calculate the signature using SHA1"""
    hashed = hmac.new(signing_key,    signature_base_string.encode('utf-8'), hashlib.sha1)


    sig = binascii.b2a_base64(hashed.digest())[:-1]

    return escape(sig)


def create_signing_key(oauth_consumer_secret, oauth_token_secret):
    """Create key to sign request with"""
    signing_key = escape(oauth_consumer_secret) + '&'

    signing_key += escape(oauth_token_secret)

    return signing_key.encode('utf-8')




 oauth_parameters = {
    'oauth_timestamp': str(int(time.time())),
    'oauth_signature_method': "HMAC-SHA1",
    'oauth_version': "1.0",
    'oauth_token': "vvvvvvvvvvvvvvv",
    'oauth_nonce': get_nonce(),
    'oauth_consumer_key': 'bbbbbbbbbbbbbbb'
     }


 oauth_parameters['oauth_signature'] = generate_signature(
    method,
    url,
    url_parameters, oauth_parameters,
    consumer_key,
    consumer_secret,
    access_token_secret
     )


 auth_headers = {'Authorization': create_auth_header(oauth_parameters),
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
                 }


 auth_data = {
       'grant_type': 'client_credentials'
  }


 webhook_endpoint ='https%3A%2F%2Fmy-site.com%2Fwebhook%2Ftwitter'

 url = 'https://api.twitter.com/1.1/account_activity/all/env/webhooks.json?url={}'.format(webhook_endpoint)

 method = "post"
 url_parameters = {
    'exclude_replies': 'true'
     }

 r = requests.post(url, headers=auth_headers, data=auth_data)

请告诉我哪个代码不正确或者我做错了什么?如果你能在答案中写下下面的代码,那将是有益的。

好的,所以我终于可以注册我的 webhook,以下是我遵循的步骤

1) 首先我在 rbenv

的帮助下安装了 ruby

2) 然后我使用

安装了 twurl
gem install twurl

3) 现在使用以下命令授权您的应用程序

twurl authorize --consumer-key key --consumer-secret secret

4) 在命令提示符下 运行 执行上述命令后,您将得到

的输出
Go to https://api.twitter.com/oauth/authorize?oauth_consumer_key=xxxxxxxxxxxxx&oauth_nonce=xxxxxxxxxxx&oauth_signature=xxxxxxxxxxxx&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1568986465&oauth_token=xxxxxxx&oauth_version=1.0 and paste in the supplied PIN

5) 只需转到 url ,推特页面将打开,其中包含 9876506 之类的 pin,只需复制 pin 并粘贴到命令行即可。

6)然后你的cmd会输出授权成功

7) 现在您已经授权了您的应用程序。

8) 现在,在注册 webhook 之前,您在 Twitter 应用的详细信息部分中提供的回调 url 应该会生成一个 crc 令牌。

9) 如果您的域是 "www.my_domain.com" 创建一个端点作为 "www.my_domain.com/webhook/twitter" 并添加以下代码以在您的 Web 应用程序中生成 crc。

def twitterCrcValidation():    
    crc = request.args['crc_token']    
    validation = hmac.new(key=bytes(CONSUMER_SECRET, 'utf-8'),msg=bytes(crc, 'utf-8'),
    digestmod = hashlib.sha256
    )
    digested = base64.b64encode(validation.digest())
    response = {
               'response_code':200,
               'response_token': 'sha256=' + format(str(digested)[2:-1])
                }
    print('responding to CRC call')    
    return json.dumps(response)

10) 现在 运行 下面的命令来注册 webhook,代替放置环境的名称,例如 "prod"

twurl -X POST "/1.1/account_activity/all/<environment>/webhooks.json?url=https://www.my_domain.com/webhooks/twitter"

11) 之后您将收到如下 json 响应

{"id":"1174326336837472256",
 "url":"https://www.my_domain.com/webhooks/twitter",
 "valid":true,
  "created_timestamp":"2019-09-18 14:16:31 +0000"
 }

12) 最后你的 url 被注册为 webhook。

P.S ----Twitter 每 24 小时向您的端点发送一次 crc 令牌,以检查 url 端点是否存活。因此,包含 url 端点的服务器应该处于 运行ning 状态。我在 heroku 服务器上部署了包含 url 端点的烧瓶应用程序。因此,与 ngrok 不同,heruko 为您提供了一个带有单个 url 的免费服务器。在 ngrok 中,每当您 运行 服务器时,您都会得到一个新的 url ,而 twitter 则不需要。但是如果你不刷新网站,heroku 服务器每 10 分钟就会休眠一次。 所以 twitter 可能 运行 我的网站上有 crc 检查,我的网站由于 heroku 的政策处于休眠状态,我的 webhook id 变得无效。

您可以通过 运行 给出以下命令使您的 webhook id 再次有效。

twurl -X PUT "/1.1/account_activity/all/prod/webhooks/11743xxxxxxxxxx6.json"

然后您可以通过 运行以下命令

获取有关您的 webhook 的信息
twurl -X GET "/1.1/account_activity/all/webhooks.json" --header authorization:bearer token

有人应该为这个回复付你一杯啤酒。 Twitter 让事情变得异常复杂,大声笑。

谢谢,效果很好。 提醒一下,环境来自 https://developer.twitter.com/en/account/environments。所以一定要在那里创建一些东西,以便放入 POST url.