開發指南
推播方式
Jodoo 目前僅支援 POST 請求,請求中 Header 的 Content-type 類型為 application/json。
POST http://example.com/jdy/hook?timestamp=1498586609&nonce=0f5ade
Headers: {
"X-JDY-Signature": "72d3162e-cc78-11e3-81ab-4c9367dc0958",
"X-JDY-DeliverId": "sha1=7d38cdd689735b008b3c702edd92eea23791c5f6"
}
{
op: "data_create",
data: {}
}
請求中還包含以下 Header 欄位:
- X-JDY-DeliverId 為推播事件 ID,每次推播的 ID 是唯一的。可以透過該欄位完成請求的去重,防止重複接收同一個事件。
- X-JDY-Signature 為簽名內容,使用方式在下面的簽名驗證內容中會提到。
參數 | 說明 | 備註 |
op | 推播事件 | / |
data | 具體資料內容 | / |
send_time | 推播時間 | 僅訊息推播有 |
簽名驗證
為了防止 webhook 的接收伺服器被第三方惡意攻擊,使用者在開發回調 API 時,建議對回調請求進行簽名校驗,以確保回調請求來源來自於 Jodoo。hook 會以 POST 的形式將內容以 JSON 格式發送給指定地址。
- 在界面上隨機生成一個 secret 或者自己指定一個 secret,並儲存。這樣,資料推播時就會把加密前的內容和透過 secret 加密後的內容一起推播到指定地址。
- 把 http 請求體字串作為 payload,將其和 secret,請求參數裏的 nonce、timestamp 按照 “{nonce}:{payload}:{secret}:{timestamp}” 的形式(用冒號分隔),組合為校驗字串 signature。
- 以 utf-8 編碼形式計算 signature 的 sha-1 散列
- 將 signature 散列的十六進制字串與 POST 請求 header 中的 "X-JDY-Signature" 做比較,若比較結果相同,則透過簽名驗證;若比較結果不同,則無法透過檢查
以 Python 為例:
def get_signature(nonce, payload, secret, timestamp):
content = ':'.join([nonce, payload, secret, timestamp]).encode('utf-8')
m = hashlib.sha1()
m.update(content)
return m.hexdigest()
@app.route('/callback', methods=['POST'])
def callback():
payload = request.data.decode('utf-8')
nonce = request.args['nonce']
timestamp = request.args['timestamp']
if request.headers['x-jdy-signature'] != get_signature(nonce, payload, 'test-secret', timestamp):
return 'fail', 401
threading.Thread(target=handle, args=(json.loads(payload), )).start()
return 'success'
回應規則
- Jodoo 向對應目標伺服器推播請求後,該伺服器需在 2 秒內使用 2xx 作為回應的狀態碼進行回應,即認為資料推播成功。
- 一次推播重試最多 5 次,如果單次推播連續重試 5 次均失敗,則該次推播失敗,此時會記錄該資料在失敗記錄裏,當連續失敗達到 100 次時,該推播功能將被關閉,管理會獲得訊息通知,則需要管理員在推播設定中重新啟動推播。
Webhook 推播錯誤說明
- 接收到推播後需要返回給 Jodoo2xx 表示推播接收成功。其他的返回結果則為返回資訊錯誤,使用者可以根據HTTP 狀態碼自行定義推播錯誤的情況給 Jodoo 的返回碼,Jodoo 接受後,可在推播日誌中顯示出。
開發注意點
- 由於我們會對 API 做各種擴展,為了保證每個對接的應用服務接收到更多樣的推播資料時,不出現異常。所以請在接收到更多的 op 參數的資料類型時,直接回應成功,不要回應為失敗。