开发指南
推送方式
简道云目前仅支持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 的接收服务器被第三方恶意攻击,用户在开发回调接口时,建议对回调请求进行签名校验,以确保回调请求来源来自于简道云。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'
响应规则
- 简道云向对应目标服务器推送请求后,该服务器需在2秒内使用2xx作为响应的状态码进行响应,即认为数据推送成功。
- 一次推送重试最多5次,如果单次推送连续重试5次均失败,则该次推送失败,此时会记录该数据在失败记录里,当连续失败达到100次时,该推送功能将被关闭,管理会获得消息通知,则需要管理员在推送设置中重新启动推送。
- webhook推送错误说明
- 接收到推送后需要返回给简道云2xx表示推送接收成功。其他的返回结果则为返回信息错误,用户可以根据HTTP状态码自行定义推送错误的情况给简道云的返回码,简道云接受后,可在推送日志中显示出。
- 开发注意点
- 由于我们会对接口做各种扩展,为了保证每个对接的应用服务接收到更多样的推送数据时,不出现异常。所以请在接收到更多的op参数的数据类型时,直接响应成功,不要响应为失败。