乐乎APP接口设计规范v1
张遂程 2018年02月06日16:15:03
前言
没有最优的方案,只有最适合的方案,本文指出对APP接口设计的一些规范与大家分享和共勉,涉及到APP接口设计规范v1.0,设计案例的分享,和一些PHP编码的要求,目的在于开发出性能优异,结构清晰,维护便捷,安全,和高拓展性的接口。如果有说得不正确的地方,也请大家指出。
经验学习
在项目中,要做到融会贯通,首先就应该做到多学习,学习大厂的经验和总结,如果能避免到别家遇到的坑,那么就最好了,如果避免不到,那么也能做到心中运筹帷幄。程序开发中有句很流行话就是,"不要重复造轮子",要"时刻明确自己是搬砖民工,不是烧砖的窑"。
新浪微博 open api
获取用户详情接口设计 http://open.weibo.com/wiki/2/friendships/friends
{
"users": [
{
"id": 1404376560,
"screen_name": "zaku",
"name": "zaku",
"province": "11",
"city": "5",
"location": "北京 朝阳区",
"description": "人生五十年,乃如梦如幻;有生斯有死,壮士复何憾。",
"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": "新浪微博",
"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
}
- 面向对象设计:用户是一个完整的对象,其中每个用户包含一个最新微博的对象,微博对象也是一个相对完整的对象,按照新浪微博的APP接口设计,获取每一个用户列表,都能获取到列表用户的最新微博信息。
- 错误信息的返回:主接口中没有直接对错误信息的定义,但凡是能够获取到信息,都认为是正确,而错误信息的定义则是用另一种数据格式来表示。
{
"request" : "/statuses/home_timeline.json",
"error_code" : "20502",
"error" : "Need you follow uid."
}
- 错误信息的说明:'request'表示当前请求的接口;'error_code'表示错误编号;'error'表示错误的提示文字
淘宝开放平台
查询买家信息 http://open.taobao.com/docs/api.htm?spm=a219a.7629065.0.0.5Zpljz&apiId=21348
- 正常响应
{
"user_buyer_get_response":{
"user":{
"nick":"hz0799",
"sex":"m",
"avatar":"http://assets.taobaocdn.com/app/sns/img/default/avatar-120.png",
"open_uid":"324324324"
}
}
}
- 异常响应
{
"error_response":{
"sub_msg":"非法参数",
"code":50,
"sub_code":"isv.invalid-parameter",
"msg":"Remote service error"
}
}
- 错误响应也是通过错误code来识别的,每个code对应一个错误内容
其他开放API
除了上文说的响应方式外,还有一种API响应方式也是比较流行,代表者是百度,高德,支付宝等。
- 百度举例
{
address: "CN|北京|北京|None|CHINANET|1|None", #详细地址信息
content: #结构信息
{
address: "北京市", #简要地址信息
address_detail: #结构化地址信息
{
city: "北京市", #城市
city_code: 131, #百度城市代码
district: "", #区县
province: "北京市", #省份
street: "", #街道
street_number: "" #门牌号
},
point: #当前城市中心点
{
x: "116.39564504", #当前城市中心点经度
y: "39.92998578" #当前城市中心点纬度
}
},
status: 0 #结果状态返回码
}
- 支付宝举例
{
"alipay_trade_precreate_response": {
"code": "10000",
"msg": "Success",
"out_trade_no": "6823789339978248",
"qr_code": "https://qr.alipay.com/bavh4wjlxf12tper3a"
},
"sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}
- 这类API相对新兴设计,在API响应上,不区分正确响应和错误响应的结构,采用统一返回方式,其中返回的code 来区分正确还是错误,其中的message来分别给出正确和错误的响应消息。
小结
- API设计中,要根据自己的业务类型和面向群体来综合考虑
- 都对错误级别进行了划分,并用不同的错误code来表示
- API面向对象设计并不是面向页面设计,这样的API就具有了多端不同展示的能力
- 响应主体设计中,个人比较倾向统一的返回,也就是现在我们正在使用的三段式返回,不同的客户端不用去写过多的兼容代码和错误处理,错误处理全部由服务端来完成。
- 错误处理,目前我们的错误处理机制都还比较简单,就APP而言,只有 '0' '1' '1001',三种识别码和对应的中文提示内容。如果我们后续要支持多种语言的提示,就必须使用error_code,然后由客户端自行提示。
接口设计规范
与前端交互部分
这里概念的定义为与APP部分相互的部分,我们将从安全,版本兼容,命名规范,迭代,面向对象等多个方面说起
接口安全部分
在app的后台设计中,一个很重要的因素是考虑通讯的安全性。
避免信息的泄露,最简单的方案是所有涉及到安全性的api请求,都必须要使用https协议。
因此,我们需要考虑的要点有:
- 在app和后台,都不能保存任何用户密码的明文
- 在app和后台通讯的过程中,怎么保证用户信息的安全性
- 在app中,根据安全考虑,用户的操作分为两类:
-
- 用户登录
-
- 注册操作
用户的其他操作
- 注册操作
- 在第一点,用户登录注册操作中,是会出现用户密码,所以在这个过程中,必须要使用https通讯,保证通讯的安全。
- 在第二点,用户的其他操作,怎么保证这部分通讯的安全呢?
在我们的设计中,是采用了公钥加私钥保证安全。用户的id是公钥,通过一定的算法对用户的id进行加密得到一个加密字符串是私钥。当用户登录或注册后,通过https把公钥加私钥返回给app客户端。 - 但这个方法有个缺点,当别人截获了这个url时可以重复使用,所以有个改进方法是在传递的参数中增加时间戳,当发现这个时间戳离现在的时间已经很久了,就判断这个url已经失效了。但用时间戳怎么保证app的时间和服务器的时间同步?==可以在app每次启动和注册登录时和服务器同步时间,然后在app内建一个时钟,时间戳在这个app的内部时钟获取,防止用户修改了手机的时间。==
- 当然,这些操作做完了,也不能保证100%的安全,只能为攻击增加成本。
效率
APP对服务器端要求是比较严格的,在移动端有限的带宽条件下或者弱网络下,要求接口响应速度要快,,抛开后端的开发框架效率来说,对数据要求也比较严格,如果能做到app需要什么数据就传什么数据,不可多传,过多的数据量影响处理速度,最重要的是影响传输效率那么自然效率是最高的,但是这之间也要有个取舍,效率和接口设计思想之间,后面我们会提到面向对象的设计思想。
面向对象的设计思想
Restful风格:RESTfu设计原则,它被RoyFelding提出(在他的"基于网络的软件架构"论文中第五章)。而REST的核心原则是将你的API拆分为逻辑上的资源。这些资源通过http被操作(GET,POST,PUT,DELETE)。但现在看,一般的操作只有两种:GET ,POST。
这个设计原则最简单的应用就是面向对象设计而不是页面来设计api。最开始的时候,app的一个页面需要什么数据,api就返回什么数据。结果随着app的UI不断改版,需要的数据不断变化,不停地修改api,最后当api的改动会影响以前的版本的时候,只能写一个新的api版本,最后弄得api中有很多version/2,version/3这样的标志,恶梦!
==但根据object来设计,又有一个问题,一个大object可能包含很多小object,是一个api返回全部小object,还是分为多个api返回?根据业务和技术,带宽等仔细考虑吧。==
目前我们的接口设计是根据业务来定制接口和返回,假设页面上只显示五个字段,那么后端就需要针对这个页面进行设计。
当然这这样的好处是显而易见的,在和客户端交互的过程中,传输的数据全是有用的数据,极大地节约了网络资源,而且只需请求一个接口,接口就返回了所有界面显示的数据,在弱网状态下,加快响应速度。
新浪微博的做法:打开个人中心,会分多次进行请求,'users/counts'批量获取用户的粉丝数、关注数、微博数,'users/domain_show'个性域名相关,'users/show'获取主要信息,这是比较极端的做法,仅供参考。
-
下面是一个简单的例子
返回的数据结构如下
{
"brand_name": "奥迪",
"car_model": "SUV",
"emission_standard": "国五",
"car_owner": {
"name ": "张三 ",
"driving_years": "5年",
"id": "123 ",
}
}
其中车主是一个对象,车子是一个对象,两者是既有关系又相对独立。
我的建议是,新设计的接口,需要考虑到多端不同展示,尽可能的偏向于面向对象,少量特殊处理可以面向页面。当然,后端代码上,都是以对象的形式存在,逻辑必须清楚。
API命名规则
其中一个原则,一看api名字就知道这个api是干啥。但是有个问题就是当你要负责几十甚至上百个api,你就知道不能"望名知api"是个什么样的痛苦。
就拿一个接口来举例吧
/User/userRedDot/version/1