樂乎APP接口設(shè)計規(guī)范v1
張遂程 2018年02月06日16:15:03
前言
沒有最優(yōu)的方案稿黄,只有最適合的方案,本文指出對APP接口設(shè)計的一些規(guī)范與大家分享和共勉雳旅,涉及到APP接口設(shè)計規(guī)范v1.0跟磨,設(shè)計案例的分享,和一些PHP編碼的要求攒盈,目的在于開發(fā)出性能優(yōu)異抵拘,結(jié)構(gòu)清晰,維護便捷型豁,安全僵蛛,和高拓展性的接口。如果有說得不正確的地方迎变,也請大家指出充尉。
經(jīng)驗學(xué)習(xí)
在項目中,要做到融會貫通衣形,首先就應(yīng)該做到多學(xué)習(xí)驼侠,學(xué)習(xí)大廠的經(jīng)驗和總結(jié),如果能避免到別家遇到的坑谆吴,那么就最好了倒源,如果避免不到,那么也能做到心中運籌帷幄句狼。程序開發(fā)中有句很流行話就是笋熬,"不要重復(fù)造輪子",要"時刻明確自己是搬磚民工,不是燒磚的窯"鲜锚。
新浪微博 open api
獲取用戶詳情接口設(shè)計 http://open.weibo.com/wiki/2/friendships/friends
{
"users": [
{
"id": 1404376560,
"screen_name": "zaku",
"name": "zaku",
"province": "11",
"city": "5",
"location": "北京 朝陽區(qū)",
"description": "人生五十年突诬,乃如夢如幻;有生斯有死芜繁,壯士復(fù)何憾旺隙。",
"url": "http://blog.sina.com.cn/zaku",
"profile_image_url": "http://tp1.sinaimg.cn/1404376560/50/0/1",
"domain": "zaku",
"gender": "m",
"followers_count": 1204,
"friends_count": 447,
"statuses_count": 2908,
"favourites_count": 0,
"created_at": "Fri Aug 28 00:00:00 +0800 2009",
"following": false,
"allow_all_act_msg": false,
"remark": "",
"geo_enabled": true,
"verified": false,
"status": {
"created_at": "Tue May 24 18:04:53 +0800 2011",
"id": 11142488790,
"text": "我的相機到了。",
"source": "<a rel="nofollow">新浪微博</a>",
"favorited": false,
"truncated": false,
"in_reply_to_status_id": "",
"in_reply_to_user_id": "",
"in_reply_to_screen_name": "",
"geo": null,
"mid": "5610221544300749636",
"annotations": [],
"reposts_count": 5,
"comments_count": 8
},
"allow_all_comment": true,
"avatar_large": "http://tp1.sinaimg.cn/1404376560/180/0/1",
"verified_reason": "",
"follow_me": false,
"online_status": 0,
"bi_followers_count": 215
},
...
],
"next_cursor": 5,
"previous_cursor": 0,
"total_number": 668
}
- 面向?qū)ο笤O(shè)計:用戶是一個完整的對象骏令,其中每個用戶包含一個最新微博的對象蔬捷,微博對象也是一個相對完整的對象,按照新浪微博的APP接口設(shè)計榔袋,獲取每一個用戶列表周拐,都能獲取到列表用戶的最新微博信息。
- 錯誤信息的返回:主接口中沒有直接對錯誤信息的定義凰兑,但凡是能夠獲取到信息妥粟,都認為是正確,而錯誤信息的定義則是用另一種數(shù)據(jù)格式來表示吏够。
{
"request" : "/statuses/home_timeline.json",
"error_code" : "20502",
"error" : "Need you follow uid."
}
- 錯誤信息的說明:'request'表示當(dāng)前請求的接口;'error_code'表示錯誤編號;'error'表示錯誤的提示文字
淘寶開放平臺
查詢買家信息 http://open.taobao.com/docs/api.htm?spm=a219a.7629065.0.0.5Zpljz&apiId=21348
- 正常響應(yīng)
{
"user_buyer_get_response":{
"user":{
"nick":"hz0799",
"sex":"m",
"avatar":"http://assets.taobaocdn.com/app/sns/img/default/avatar-120.png",
"open_uid":"324324324"
}
}
}
- 異常響應(yīng)
{
"error_response":{
"sub_msg":"非法參數(shù)",
"code":50,
"sub_code":"isv.invalid-parameter",
"msg":"Remote service error"
}
}
- 錯誤響應(yīng)也是通過錯誤code來識別的勾给,每個code對應(yīng)一個錯誤內(nèi)容
其他開放API
除了上文說的響應(yīng)方式外滩报,還有一種API響應(yīng)方式也是比較流行,代表者是百度,高德,支付寶等播急。
- 百度舉例
{
address: "CN|北京|北京|None|CHINANET|1|None", #詳細地址信息
content: #結(jié)構(gòu)信息
{
address: "北京市", #簡要地址信息
address_detail: #結(jié)構(gòu)化地址信息
{
city: "北京市", #城市
city_code: 131, #百度城市代碼
district: "", #區(qū)縣
province: "北京市", #省份
street: "", #街道
street_number: "" #門牌號
},
point: #當(dāng)前城市中心點
{
x: "116.39564504", #當(dāng)前城市中心點經(jīng)度
y: "39.92998578" #當(dāng)前城市中心點緯度
}
},
status: 0 #結(jié)果狀態(tài)返回碼
}
- 支付寶舉例
{
"alipay_trade_precreate_response": {
"code": "10000",
"msg": "Success",
"out_trade_no": "6823789339978248",
"qr_code": "https://qr.alipay.com/bavh4wjlxf12tper3a"
},
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
- 這類API相對新興設(shè)計脓钾,在API響應(yīng)上,不區(qū)分正確響應(yīng)和錯誤響應(yīng)的結(jié)構(gòu)桩警,采用統(tǒng)一返回方式可训,其中返回的code 來區(qū)分正確還是錯誤,其中的message來分別給出正確和錯誤的響應(yīng)消息捶枢。
小結(jié)
- API設(shè)計中握截,要根據(jù)自己的業(yè)務(wù)類型和面向群體來綜合考慮
- 都對錯誤級別進行了劃分,并用不同的錯誤code來表示
- API面向?qū)ο笤O(shè)計并不是面向頁面設(shè)計柱蟀,這樣的API就具有了多端不同展示的能力
- 響應(yīng)主體設(shè)計中川蒙,個人比較傾向統(tǒng)一的返回蚜厉,也就是現(xiàn)在我們正在使用的三段式返回长已,不同的客戶端不用去寫過多的兼容代碼和錯誤處理,錯誤處理全部由服務(wù)端來完成昼牛。
- 錯誤處理术瓮,目前我們的錯誤處理機制都還比較簡單,就APP而言贰健,只有 '0' '1' '1001',三種識別碼和對應(yīng)的中文提示內(nèi)容胞四。如果我們后續(xù)要支持多種語言的提示,就必須使用error_code伶椿,然后由客戶端自行提示辜伟。
接口設(shè)計規(guī)范
與前端交互部分
這里概念的定義為與APP部分相互的部分,我們將從安全脊另,版本兼容导狡,命名規(guī)范,迭代偎痛,面向?qū)ο蟮榷鄠€方面說起
接口安全部分
在app的后臺設(shè)計中旱捧,一個很重要的因素是考慮通訊的安全性。
避免信息的泄露踩麦,最簡單的方案是所有涉及到安全性的api請求枚赡,都必須要使用https協(xié)議。
因此谓谦,我們需要考慮的要點有:
- 在app和后臺贫橙,都不能保存任何用戶密碼的明文
- 在app和后臺通訊的過程中,怎么保證用戶信息的安全性
- 在app中反粥,根據(jù)安全考慮卢肃,用戶的操作分為兩類:
- 用戶登錄
- 注冊操作
用戶的其他操作
- 注冊操作
- 在第一點谓松,用戶登錄注冊操作中,是會出現(xiàn)用戶密碼践剂,所以在這個過程中鬼譬,必須要使用https通訊,保證通訊的安全逊脯。
- 在第二點优质,用戶的其他操作,怎么保證這部分通訊的安全呢军洼?
在我們的設(shè)計中巩螃,是采用了公鑰加私鑰保證安全。用戶的id是公鑰匕争,通過一定的算法對用戶的id進行加密得到一個加密字符串是私鑰避乏。當(dāng)用戶登錄或注冊后,通過https把公鑰加私鑰返回給app客戶端甘桑。 - 但這個方法有個缺點拍皮,當(dāng)別人截獲了這個url時可以重復(fù)使用,所以有個改進方法是在傳遞的參數(shù)中增加時間戳跑杭,當(dāng)發(fā)現(xiàn)這個時間戳離現(xiàn)在的時間已經(jīng)很久了铆帽,就判斷這個url已經(jīng)失效了。但用時間戳怎么保證app的時間和服務(wù)器的時間同步德谅?==可以在app每次啟動和注冊登錄時和服務(wù)器同步時間爹橱,然后在app內(nèi)建一個時鐘,時間戳在這個app的內(nèi)部時鐘獲取窄做,防止用戶修改了手機的時間愧驱。==
- 當(dāng)然,這些操作做完了椭盏,也不能保證100%的安全组砚,只能為攻擊增加成本。
效率
APP對服務(wù)器端要求是比較嚴格的庸汗,在移動端有限的帶寬條件下或者弱網(wǎng)絡(luò)下惫确,要求接口響應(yīng)速度要快,蚯舱,拋開后端的開發(fā)框架效率來說改化,對數(shù)據(jù)要求也比較嚴格,如果能做到app需要什么數(shù)據(jù)就傳什么數(shù)據(jù)枉昏,不可多傳陈肛,過多的數(shù)據(jù)量影響處理速度,最重要的是影響傳輸效率那么自然效率是最高的兄裂,但是這之間也要有個取舍句旱,效率和接口設(shè)計思想之間阳藻,后面我們會提到面向?qū)ο蟮脑O(shè)計思想。
面向?qū)ο蟮脑O(shè)計思想
Restful風(fēng)格:RESTfu設(shè)計原則,它被RoyFelding提出(在他的"基于網(wǎng)絡(luò)的軟件架構(gòu)"論文中第五章)谈撒。而REST的核心原則是將你的API拆分為邏輯上的資源腥泥。這些資源通過http被操作(GET,POST,PUT,DELETE)。但現(xiàn)在看啃匿,一般的操作只有兩種:GET ,POST蛔外。
這個設(shè)計原則最簡單的應(yīng)用就是面向?qū)ο笤O(shè)計而不是頁面來設(shè)計api。最開始的時候溯乒,app的一個頁面需要什么數(shù)據(jù)夹厌,api就返回什么數(shù)據(jù)。結(jié)果隨著app的UI不斷改版裆悄,需要的數(shù)據(jù)不斷變化矛纹,不停地修改api,最后當(dāng)api的改動會影響以前的版本的時候光稼,只能寫一個新的api版本或南,最后弄得api中有很多version/2,version/3這樣的標志,惡夢!
==但根據(jù)object來設(shè)計钟哥,又有一個問題迎献,一個大object可能包含很多小object,是一個api返回全部小object腻贰,還是分為多個api返回?根據(jù)業(yè)務(wù)和技術(shù)扒秸,帶寬等仔細考慮吧播演。==
目前我們的接口設(shè)計是根據(jù)業(yè)務(wù)來定制接口和返回,假設(shè)頁面上只顯示五個字段伴奥,那么后端就需要針對這個頁面進行設(shè)計写烤。
當(dāng)然這這樣的好處是顯而易見的,在和客戶端交互的過程中拾徙,傳輸?shù)臄?shù)據(jù)全是有用的數(shù)據(jù)洲炊,極大地節(jié)約了網(wǎng)絡(luò)資源,而且只需請求一個接口尼啡,接口就返回了所有界面顯示的數(shù)據(jù)暂衡,在弱網(wǎng)狀態(tài)下,加快響應(yīng)速度崖瞭。
新浪微博的做法:打開個人中心狂巢,會分多次進行請求,'users/counts'批量獲取用戶的粉絲數(shù)书聚、關(guān)注數(shù)唧领、微博數(shù),'users/domain_show'個性域名相關(guān),'users/show'獲取主要信息藻雌,這是比較極端的做法,僅供參考斩个。
-
下面是一個簡單的例子
image
返回的數(shù)據(jù)結(jié)構(gòu)如下
{
"brand_name": "奧迪",
"car_model": "SUV",
"emission_standard": "國五",
"car_owner": {
"name ": "張三 ",
"driving_years": "5年",
"id": "123 ",
}
}
其中車主是一個對象胯杭,車子是一個對象,兩者是既有關(guān)系又相對獨立受啥。
我的建議是歉摧,新設(shè)計的接口,需要考慮到多端不同展示腔呜,盡可能的偏向于面向?qū)ο笕拢倭刻厥馓幚砜梢悦嫦蝽撁妗.?dāng)然核畴,后端代碼上膝但,都是以對象的形式存在,邏輯必須清楚谤草。
API命名規(guī)則
其中一個原則跟束,一看api名字就知道這個api是干啥。但是有個問題就是當(dāng)你要負責(zé)幾十甚至上百個api丑孩,你就知道不能"望名知api"是個什么樣的痛苦冀宴。
就拿一個接口來舉例吧
/User/userRedDot/version/1