3.2 接口开发要点

本节主题: 3.2 接口开发要点

课程讲师: Charlie

观看地址: 点我进入


1 本节要点

  • 掌握接口开发中的要点
  • 掌握JSONPath的概念
  • 了解内网穿透的概念

2 课前准备


3 课程内容

3.1 接口开发要点

预览推送的格式

扩展功能 - 数据推送 - 字段对照表及JSON样例


3.1.1 判断推送类型*

op: 推送事件;包括data_create(数据提交)、data_update(数据修改)、data_remove(数据删除)、data_recover(数据恢复)


通过op来区分具体的推送事件

from flask import Flask, request
import json

app = Flask(__name__)     

@app.route('/test/', methods=['POST'])    #因为简道云只接收POST请求
def hello_world():
    
    print("params: ",request.args)
    print("headers: ",request.headers)
    print("未编码data: ",request.data)  
    print("已编码data: ",json.loads(request.data))
    return 'success',200

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=10000) 

url: http://101.132.103.228:10000/test/?nonce=5932d0&timestamp=1585724440

params:  ImmutableMultiDict([('nonce', '5932d0'), ('timestamp', '1585724440')])

headers:  Content-Type: application/json
X-Jdy-Deliverid: 2b85594d-454a-4063-ac1d-91a2b3318b63
Host: 101.132.103.228:10000
Content-Length: 765
Connection: close

原始data:  b'{"data":{"_id":"5dd6740646357c0006e6eb6e","_widget_1574134687834":"\xe6\xb6\xa1\xe8\xbd\xae\xe5\x87\x8f\xe9\x80\x9f\xe6\x9c\xba1","_widget_1574134687849":"DJSM9K2000","_widget_1574134687894":"2019-11-21T11:24:54.000Z","_widget_1574134688078":345999,"_widget_1574134688093":101,"_widget_1574134688108":3459990,"_widget_1574134688185":"\xe5\x8d\x97\xe4\xba\xac\xe6\x82\x9f\xe5\xb8\x86\xe7\xa7\x91\xe6\x8a\x80\xe8\x82\xa1\xe4\xbb\xbd\xe6\x9c\x89\xe9\x99\x90\xe5\x85\xac\xe5\x8f\xb8","_widget_1574142293244":"TSCJ001574335494","appId":"5dce13f43087860006c70e7a","createTime":"2019-11-21T11:24:54.213Z","creator":{"_id":"5cecd40dd23e194ab0867aab","name":"\xe6\x9f\xa5\xe7\x90\x86","username":"cxt7777"},"deleteTime":null,"deleter":null,"entryId":"5dce145c26aecf00062e7db0","formName":"\xe8\xae\xa2\xe5\x8d\x95\xe6\xb1\x87\xe6\x80\xbb","updateTime":"2020-04-01T07:00:40.876Z","updater":{"_id":"5cecd40dd23e194ab0867aab","name":"\xe6\x9f\xa5\xe7\x90\x86","username":"cxt7777"}},"op":"data_update"}'

转换成Python字典后的data:  {'data': {'_id': '5dd6740646357c0006e6eb6e', '_widget_1574134687834': '涡轮减速机1', '_widget_1574134687849': 'DJSM9K2000', '_widget_1574134687894': '2019-11-21T11:24:54.000Z', '_widget_1574134688078': 345999, '_widget_1574134688093': 101, '_widget_1574134688108': 3459990, '_widget_1574134688185': '南京悟帆科技股份有限公司', '_widget_1574142293244': 'TSCJ001574335494', 'appId': '5dce13f43087860006c70e7a', 'createTime': '2019-11-21T11:24:54.213Z', 'creator': {'_id': '5cecd40dd23e194ab0867aab', 'name': '查理', 'username': 'cxt7777'}, 'deleteTime': None, 'deleter': None, 'entryId': '5dce145c26aecf00062e7db0', 'formName': '订单汇总', 'updateTime': '2020-04-01T07:00:40.876Z', 'updater': {'_id': '5cecd40dd23e194ab0867aab', 'name': '查理', 'username': 'cxt7777'}}, 'op': 'data_update'}

3.1.2 多线程处理

Threading :Python 实现多线程编程需要借助于 threading 模块,我们使用多线程来防止处理时间长导致响应超时;


多线程类似于同时执行多个不同程序

  • 使用线程可以把占据长时间的程序中的任务放到后台去处理;
  • 用户界面可以更加吸引人,比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度;
  • 程序的运行速度可能加快;
  • 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。


threading.Thread(target=<函数名>).start()
# 多线程赋值
threading.Thread(target=<函数名>, args=(<变量>,).start()

import threading
import time

def handle_a():
    for i in range(5):
        print("a",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) )
        time.sleep(1)
        
def handle_b():
    for i in range(5):
        print("b",time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) )
        time.sleep(1)
   
#使用多线程
threading.Thread(target=handle_a).start()
time.sleep(0.1)
handle_b()

#正常按顺序执行函数
handle_a()
handle_b()

#传入参数
def printtime(a):
    print(a, time.time())
x = 123

threading.Thread(target=print,args=(x,)).start()

3.1.3 接口加密

加密:防止接口被攻击;



import hashlib

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'

3.2 JSONPath

测试网址:点击查看

{
    "data": [
        {
            "creator": {
                "_id": "5cecd40dd23e194ab0867aab",
                "name": "查理",
                "username": "cxt7777"
            },
            "updater": {
                "_id": "5cecd40dd23e194ab0867aab",
                "name": "查理",
                "username": "cxt7777"
            },
            "deleter": null,
            "createTime": "2020-03-26T02:41:06.491Z",
            "updateTime": "2020-03-26T02:46:27.825Z",
            "deleteTime": null,
            "_widget_1557886562320": "iPhone 11",
            "_widget_1557886562335": "5998",
            "_widget_1557886562350": "17",
            "_id": "5e7c164229e01a00063be284",
            "appId": "5e798363b587cc0006b40445",
            "entryId": "5cdb765b5a6ae613aeed0f84"
        },
        {
            "creator": {
                "_id": "5cecd40dd23e194ab0867aab",
                "name": "查理",
                "username": "cxt7777"
            },
            "updater": {
                "_id": "5cecd40dd23e194ab0867aab",
                "name": "查理",
                "username": "cxt7777"
            },
            "deleter": null,
            "createTime": "2020-03-26T02:47:02.037Z",
            "updateTime": "2020-03-26T02:47:02.037Z",
            "deleteTime": null,
            "_widget_1557886562320": "iPhone X",
            "_widget_1557886562335": "4998",
            "_widget_1557886562350": "5",
            "_id": "5e7c17a650bccb0006441778",
            "appId": "5e798363b587cc0006b40445",
            "entryId": "5cdb765b5a6ae613aeed0f84"
        },
        {
            "creator": {
                "_id": "5cecd40dd23e194ab0867aab",
                "name": "查理",
                "username": "cxt7777"
            },
            "updater": {
                "_id": "5cecd40dd23e194ab0867aab",
                "name": "查理",
                "username": "cxt7777"
            },
            "deleter": null,
            "createTime": "2020-03-26T02:47:43.059Z",
            "updateTime": "2020-03-26T02:47:43.059Z",
            "deleteTime": null,
            "_widget_1557886562320": "iPhone 8",
            "_widget_1557886562335": "3998",
            "_widget_1557886562350": "32",
            "_id": "5e7c17cfcd87510006cf8189",
            "appId": "5e798363b587cc0006b40445",
            "entryId": "5cdb765b5a6ae613aeed0f84"
        }
    ]
}

提取规则类似Python:

取出iPhone 11的商品数量("_widget_1557886562350")

$.data[0]._widget_1557886562350

$.data[0][’_widget_1557886562350’]


3.3 内网穿透(演示)

现在我们编写的接口,仅能在 本地(你自己的主机,localhost 或 127.0.0.1) 访问,我们需要将本地端口映射至公网环境,才能被简道云或是其他人访问(这里不要求掌握如何进行内网穿透,了解概念即可);

当然也可以直接把服务部署在具有公网地址的云服务器(ECS)上,这是我们下节课介绍的内容!

这里编写了一个接口,请求与返回格式均为JSON

from flask import Flask, request
import json

app = Flask(__name__)     

@app.route('/test/', methods=['POST'])    #因为简道云只接收POST请求
def hello_world():
    
    print("params: ",request.args)
    print("headers: ",request.headers)
    print("未编码data: ",request.data)  
    print("已编码data: ",json.loads(request.data))
    return 'success',200

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=3100) 
本文是否对您有帮助?
 有帮助
 没帮助
您是否遇到了以下问题?
如需获取即时帮助,请联系技术支持