2017-03-16 46 views
2

我是一名Python初學者,嘗試構建一種服務,它從api.ai獲取信息,將其傳遞給API,然後從其返回的JSON中返回一條確認消息。Python Webhook:傳遞URL +有效載荷

app.py:

#!/usr/bin/env python 

from __future__ import print_function 
from future.standard_library import install_aliases 
install_aliases() 

from urllib.parse import urlparse, urlencode 
from urllib.request import urlopen, Request 
from urllib.error import HTTPError 

import json 
import os 
import sys 
import logging 

from flask import Flask, render_template 
from flask import request 
from flask import make_response 

# Flask app should start in global layout 
app = Flask(__name__) 
app.logger.addHandler(logging.StreamHandler(sys.stdout)) 
app.logger.setLevel(logging.ERROR) 

@app.route('/webhook', methods=['POST']) 

def webhook(): 
    req = request.get_json(silent=True, force=True) 

    print("Request:") 
    print(json.dumps(req, indent=4)) 

    res = processRequest(req) 

    res = json.dumps(res, indent=4) 
    # print(res) 
    r = make_response(res) 
    r.headers['Content-Type'] = 'application/json' 
    return r 

def processRequest(req): 
    if req.get("result").get("action") != "bookMyConference": 
     return {} 

    #oauth 
    orequest = req.get("originalRequest") # work down the tree 
    odata = orequest.get("data") # work down the tree 
    user = odata.get("user") # work down the tree 
    access_token = user.get("access_token") 

    #data 
    result = req.get("result") # work down the tree 
    parameters = result.get("parameters") # work down the tree 
    startdate = parameters.get("start-date") 
    meetingname = parameters.get("meeting-name") 

    payload = { 
     "start-date": startdate, 
     "end-date": startdate, 
     "meeting-name": meetingname 
    } 

    # POST info to join.me 
    baseurl = "https://api.join.me/v1/meetings" 
    p = Request(baseurl) 
    p.add_header('Content-Type', 'application/json; charset=utf-8') 
    p.add_header('Authorization', 'Bearer ' + access_token) #from oauth 
    jsondata = json.dumps(payload) 
    jsondataasbytes = jsondata.encode('utf-8') # needs to be bytes 
    jresult = urlopen(p, jsondataasbytes).read() 
    data = json.loads(jresult) 
    res = makeWebhookResult(data) 
    return res 

def makeWebhookResult(data): 

    speech = "Appointment scheduled!" 

    print("Response:") 
    print(speech) 

    return { 
     "speech": speech, 
     "displayText": speech, 
     # "data": data, 
     "source": "heroku-bookmyconference" 
    } 


if __name__ == '__main__': 
    port = int(os.getenv('PORT', 5000)) 

    print("Starting app on port %d" % port) 

    app.run(debug=False, port=port, host='0.0.0.0') 

編輯4:這是我得到我的Heroku的日誌中的錯誤:

2017-03-21T19:06:09.383612+00:00 app[web.1]: HTTPError: HTTP Error 400: Bad Request

回答

0

借用here,使用urlib模塊內processRequest()你可以像這樣將你的有效載荷添加到urlopen:

req = Request(yql_url) 
req.add_header('Content-Type', 'application/json; charset=utf-8') 
jsondata = json.dumps(payload) 
jsondataasbytes = jsondata.encode('utf-8') # needs to be bytes 
result = urlopen(req, jsondataasbytes).read() 
data = json.loads(result) 

事情變得更簡潔,如果使用requests模塊:

headers = {'content-type': 'application/json'} 
result = requests.post(yql_url, data=json.dumps(payload), headers=headers) 
data = result.json() 

編輯:添加一些細節具體到join.me API

縱觀join.me docs你需要獲得訪問令牌添加到您的標題。但是在獲得訪問令牌之前,您還需要一個應用驗證碼。您可以手動獲取應用認證代碼,或鏈接一些重定向。

要開始,請在瀏覽器中嘗試此網址,並從回調參數中獲取code。使用您的join.me creds:

auth_url = 'https://secure.join.me/api/public/v1/auth/oauth2' \ 
    + '?client_id=' + client_id \ 
    + '&scope=scheduler%20start_meeting' \ 
    + '&redirect_uri=' + callback_url \ 
    + '&state=ABCD' \ 
    + '&response_type=code' 
print(auth_url) # try in browser 

爲了獲得訪問令牌:

token_url = 'https://secure.join.me/api/public/v1/auth/token' 
headers = {'content-type': 'application/json'} 
token_params = { 
    'client_id': client_id, 
    'client_secret': client_secret, 
    'code': auth_code, 
    'redirect_uri': callback_url, 
    'grant_type': 'authorization_code' 
} 
result = requests.post(token_url, data=json.dumps(token_params), headers=headers) 
access_token = result.json().get('access_token') 

然後你的帖子/會議頭將需要看起來像:

headers = { 
    'content-type': 'application/json', 
    'Authorization': 'Bearer ' + access_token 
} 
+0

我我已經添加到我的processRequest()調用,但我現在得到這個錯誤,當我試圖打它「狀態」:{ 「code」:206, 「errorType」:「partial_content」, 「 errorDet ails「:」Webhook通話失敗。錯誤消息:Webhook響應爲空.' – beaconhill

+0

數據在返回時看起來像什麼?這聽起來像它可能需要一些[格式](https://discuss.api.ai/t/webhook-error-206/976/7)。 – brennan

+0

只是對顯示更多的原始帖子進行了編輯。我得到一個401,因爲我沒有通過訪問令牌。如何從請求中訪問它? – beaconhill