API接口规范
<h3>版本记录</h3>
<table>
<thead>
<tr>
<th>版本号</th>
<th>版本说明</th>
<th>作者</th>
<th>日期</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<tr>
<td>V1.0</td>
<td>API接口规范</td>
<td>Meeler</td>
<td>2018-08-22</td>
<td>修订版</td>
</tr>
<tr>
<td>------------</td>
<td>------------</td>
<td>------------</td>
<td>------------</td>
<td>------------</td>
</tr>
</tbody>
</table>
<hr />
<h3>接口概述</h3>
<p> 接口是纯数据的交互,是产品服务和业务之间进行通信的途径,实质是以特定的规则(参数)通过接口直接操作数据库的增删改查。</p>
<h3>HTTP Content-Type</h3>
<div style="border:none;padding:10px;color:blue;background-color:#ccc">默认Content-Type : <span style="color:red">application/json</span>, charset=utf-8
表单中上传文件 Content-Type 用 multipart/form-data</div>
<hr />
<h3>HTTP Method</h3>
<table>
<thead>
<tr>
<th>序号</th>
<th>方法</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>GET</td>
<td>请求指定的页面信息,并返回实体主体。</td>
</tr>
<tr>
<td>2</td>
<td>HEAD</td>
<td>类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头</td>
</tr>
<tr>
<td>3</td>
<td>POST</td>
<td>向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立或已有资源的修改。</td>
</tr>
<tr>
<td>4</td>
<td>PUT</td>
<td>从客户端向服务器传送的数据取代指定的文档的内容。</td>
</tr>
<tr>
<td>5</td>
<td>DELETE</td>
<td>请求服务器删除指定的页面。</td>
</tr>
</tbody>
</table>
<ul>
<li>GET传输数据会受到URL长度的限制(特定浏览器和服务器对URL长度有限制);POST由于不是通过URL传值,理论上数据不受限。</li>
<li>GET产生的URL地址可以被浏览器Bookmark并混存,而POST不会。</li>
<li>对参数的数据类型,GET只接受ASCII字符,而POST没有限制;GET请求只能进行url编码,而POST支持多种编码方式。</li>
<li>GET提交数据可能会造成<a href="https://www.cnblogs.com/suizhikuo/p/4545981.html" title="Cross-site request forgery">Cross-site request forgery</a>。</li>
<li>POST不支持复杂数据类型,因为post没有定义传输数据结构的语义和规则,可以转为字符串后传输。</li>
<li>GET产生一个TCP数据包,POST产生两个TCP数据包。GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。<strong>在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点</strong>。</li>
</ul>
<div style="border:none;padding:10px;color:blue;background-color:#ccc"><span style="color:red">POST</span>:增删改 + params;<span style="color:green">GET</span>:查 + params</div>
<hr />
<h3>API设计</h3>
<p> 整体采用<a href="http://www.ruanyifeng.com/blog/2014/05/restful_api.html" title="RESTful">RESTful</a>设计</p>
<ul>
<li>
<p>域名
应该尽量将API部署在专用域名之下。
eg: <code>https://dataapi.cn.miaozhen.com/</code>
如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下。
eg: <code>https://content.cn.miaozhen.com/api/</code></p>
</li>
<li>
<p>api版本控制
应该将API的版本号放入URL。
eg:<code>https://content.cn.miaozhen.com/api/v{n}/</code>
另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。Github采用这种做法。</p>
</li>
<li>
<p>API 路径规则
在RESTful架构中,每个网址代表一种资源(resource),所以网址中的资源用名词,而且所用的名词往往与数据库的表名对应。
eg :
<code>https://content.cn.miaozhen.com/api/v{n}/users</code>
<code>https://content.cn.miaozhen.com/api/v{n}/contents/weixin</code>
<code>https://content.cn.miaozhen.com/api/v{n}/keywords/ID</code>
有时为满足业务需要,会设计非RESTful形式的api,资源名用名词,下级增加处理逻辑:
eg:资源users的增删改
<code>https://content.cn.miaozhen.com/api/v{n}/users/new</code>
<code>https://content.cn.miaozhen.com/api/v{n}/users/delete</code>
<code>https://content.cn.miaozhen.com/api/v{n}/users/update</code></p>
<div style="border:none;padding:10px;color:blue;background-color:#ccc">1.URL请求采用小写字母,数字,部分特殊符号(非制表符)组成;
2.URL请求中不采用大小写混合的驼峰命名方式,尽量采用全小写单词;
3.如果需要连接多个单词,则采用连接符连接单词,<span style="color:red">google官方建议在网址中使用连字符 "-" 而尽量避免使用下划线 "_"</span> 。
</div>
</li>
<li>
<p>页面级的api
把当前页面中需要用到的所有数据通过一个接口一次性返回全部数据,不针对某个资源
eg:<code>https://content.cn.miaozhen.com/api/v{n}/get-all-data</code></p>
</li>
<li>
<p>API 传入参数4种类型</p>
<div style="border:none;padding:10px;color:blue;background-color:#ccc">1.地址栏参数
restful 地址栏参数 /api/v1/users/122,122为用户编号,获取用户编号为122的信息
GET方式的查询字串
2.请求body数据(POST)
3.cookie (多用于Auth认证)
4.request header(多用于Auth认证)
</div>
</li>
<li>API 常见参数(待补充)
<pre><code class="language-json">{
offset:1, // 指定返回记录的开始位置
currentPage: 1,
pageSize: 10, // 分页大小
totalCount: 0, // 总数量
limit:10 // 指定返回记录的数量
}</code></pre>
<hr /></li>
</ul>
<h3>API 调用注意事项</h3>
<div style="border:none;padding:10px;color:blue;background-color:#ccc">1. 必须明确方法的类型<span style="color:red">Method</span>或<span style="color:red">POST</span>;明确Content-Type,默认为application/json。
2. 必须明确<span style="color:red">参数的名称、是否必填、值类型、备注等信息</span>,非必要不得随意更改。
</div>
<table>
<thead>
<tr>
<th style="text-align: left;">参数名</th>
<th style="text-align: left;">必填</th>
<th style="text-align: left;">类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">keyword</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">string</td>
<td>搜索关键字</td>
</tr>
<tr>
<td style="text-align: left;">category</td>
<td style="text-align: left;">否</td>
<td style="text-align: left;">string</td>
<td>账号类型, 选择账号分类时才有该参数</td>
</tr>
<tr>
<td style="text-align: left;">mediaType</td>
<td style="text-align: left;">否</td>
<td style="text-align: left;">string</td>
<td>平台类型,1-微博,2-微信,20014-小红书 ,选择平台分布时才有该参数</td>
</tr>
</tbody>
</table>
<hr />
<h3>Json输出格式</h3>
<ul>
<li>正确返回
<pre><code class="language-java">{
"data": {}, // JSON对象
"success": true, // 请求flag true
"errorCode": 200, // 状态码,200为成功
"errorMsg":"" // 描述信息
}</code></pre></li>
<li>异常返回
<pre><code class="language-java">{
"data": null, // null
"success": false, // 请求flag false
"errorCode": 4XX, // 状态码,不为200则失败
"errorMsg": "失败" // 描述信息
}</code></pre></li>
</ul>
<p>说明:</p>
<div style="border:none;padding:10px;color:blue;background-color:#ccc">1. data为JSON对象,只能是对象。
2. 获取单条对象信息:data为*JSON**对象***,<span style="color:red">所有字段必须列出</span>,字段值为空或为null或为0也不例外,此时success为true,errorCode为200。eg:
</div>
<pre><code class="language-java">{
// 返回结果为对象,字段必须列出
"data":{ "keyword" : "美白", "total" : 0, "articles" : [],"conments" : "" },
"success":true, // 请求flag
"errorCode":200, // 状态码,200为成功
"errorMsg":"" // 描述信息
}</code></pre>
<div style="border:none;padding:10px;color:blue;background-color:#ccc">获取列表对象信息:data为*JSON**对象***,里面包一层<span style="color:red">数组对象items</span>存放列表信息,若无记录则items数组为空数组;若有记录,则数组内对象所有字段必须列出,此时success为true,errorCode为200。(若返回多个数组对象信息,可以跟业务结合自定义字段,比如starList,playList)eg:
</div>
<pre><code class="language-java">{
// 返回结果为数组,字段必须列出
//"data" : { items : [] , "totalPage": 0, "pageSize": 10,"totalCount": 0},
"data" :{
"totalPage": 10,
"pageSize": 10,
"totalCount": 100,
"items": [
{
"catalogId": 1,
"pubAccountId": 69,
"wxId": "geely-auto",
"wxName": "吉利汽车",
"biz": "MzA5NTUxMzEwMQ==",
"groupList": []
}
],
},
"success":true, // 请求flag
"errorCode":200, // 状态码,200为成功
"errorMsg":"" // 描述信息
}</code></pre>
<hr />
<h3>返回状态码及说明 (待补充)</h3>
<div style="border:none;padding:10px;color:blue;background-color:#ccc">1.请求成功 200
2.权限错误 4XXX, eg:4001,4002,4003
3.系统错误 5XXX, eg:5001,5002,5003
4.数据库错误 6XXX, eg:6001,6002,6003
5.业务错误 9XXX, eg:9001,9002,9010
</div>
<table>
<thead>
<tr>
<th style="text-align: left;">状态码 errorCode</th>
<th style="text-align: left;">错误解释 errorMsg</th>
<th style="text-align: left;"> 备注 </th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">200</td>
<td style="text-align: left;">请求成功</td>
<td style="text-align: left;">请求成功</td>
</tr>
<tr>
<td style="text-align: left;">4001</td>
<td style="text-align: left;">用户认证失败</td>
<td style="text-align: left;">权限错误</td>
</tr>
<tr>
<td style="text-align: left;">4003</td>
<td style="text-align: left;">授权过期</td>
<td style="text-align: left;">权限错误</td>
</tr>
<tr>
<td style="text-align: left;">5001</td>
<td style="text-align: left;">未知错误</td>
<td style="text-align: left;">系统错误</td>
</tr>
<tr>
<td style="text-align: left;">5002</td>
<td style="text-align: left;">参数错误</td>
<td style="text-align: left;">系统错误</td>
</tr>
<tr>
<td style="text-align: left;">6001</td>
<td style="text-align: left;">数据入库失败</td>
<td style="text-align: left;">数据库错误</td>
</tr>
<tr>
<td style="text-align: left;">6002</td>
<td style="text-align: left;">回滚失败</td>
<td style="text-align: left;">数据库错误</td>
</tr>
<tr>
<td style="text-align: left;">6003</td>
<td style="text-align: left;">es查询出现错误</td>
<td style="text-align: left;">数据库错误</td>
</tr>
<tr>
<td style="text-align: left;">9001</td>
<td style="text-align: left;">搜索关键字不合法</td>
<td style="text-align: left;">业务错误</td>
</tr>
<tr>
<td style="text-align: left;">9002</td>
<td style="text-align: left;">搜索次数不足</td>
<td style="text-align: left;">业务错误</td>
</tr>
</tbody>
</table>
<hr />
<h3>传入和返回参数</h3>
<div style="border:none;padding:10px;color:blue;background-color:#ccc">所有参数命名方式均为<span style="color:red"> 『小驼峰』</span>,如userOpt,starList等。
</div>
<hr />
<h4>接口分类</h4>
<ul>
<li>
<p>查询类接口
查询类接口是指客户端传递一些参数,服务端根据参数依据需求,前往数据库查询需要的结果返回数据的一类接口。返回类型一般有两种。第一种是返回一个对象,第二种是返回一个数组对象。</p>
</li>
<li>
<p>操作类接口
操作类接口是指,客户端通过接口进行一些增删改的操作。比如新增一个客户,修改客户信息,或者删除一个客户。服务器一般返回执行的状态,有的需要返回执行结果的一些信息,比如新增客户后,返回客户的ID。</p>
</li>
<li>
<p>上传下载类接口
上传下载类接口是涉及到文件传输的接口。比如上传团片,需要上传图片到服务器,服务端根据需求响应保存并返回结果。</p>
</li>
<li>推送类接口(用的很少,『kafka消息推送』使用第三方中间件进行处理或才用阻塞模式)
服务端有消息需要通知客户端的情况,这时候就是服务端向客户端发送消息</li>
</ul>
<h3>接口调用示例</h3>
<ul>
<li>
<p>接口描述
<code>用户登录认证接口</code></p>
</li>
<li>
<p>API 地址 <code>https://content.cn.miaozhen.com/test/api/user/login</code></p>
</li>
<li>请求方式 <code>POST</code></li>
</ul>
<p>传入参数</p>
<table>
<thead>
<tr>
<th style="text-align: left;">参数名</th>
<th style="text-align: left;">必选</th>
<th style="text-align: left;">类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">code</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">string</td>
<td>小程序用户code</td>
</tr>
<tr>
<td style="text-align: left;">encryptedDataBase64</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">string</td>
<td>encryptedData</td>
</tr>
<tr>
<td style="text-align: left;">ivBase64</td>
<td style="text-align: left;">是</td>
<td style="text-align: left;">string</td>
<td>iv</td>
</tr>
<tr>
<td style="text-align: left;">inviteCode</td>
<td style="text-align: left;">否</td>
<td style="text-align: left;">string</td>
<td>如果有邀请者,则传入邀请者的unionId</td>
</tr>
</tbody>
</table>
<p>返回示例</p>
<pre><code class="language-json"> {
"success":true,
"data":{
"exist":false,
"openId":"oRe_D5CRB3_OtbSWBJ9Q1SgRPk38",
"nickName":"kiprince",
"gender":2,
"language":"zh_CN",
"city":"Wuhan",
"province":"Hubei",
"country":"China", "avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKsrDK3DBfK1eYrt1DR9FDfyHqpdUohXiaxC5ia80xgBic7ibDdXpyHzE7O1U2V4pzL2DXndsnEaNqb6g/132",
"unionId":"test",
"watermark":{
"timestamp":1533710247,
"appid":"wxa82df282e43e48bc"
},
"token":"9zl3bgrga339hgqg6a2dbdxwuyc9l8bk"
}
}</code></pre>
<p>返回参数说明</p>
<table>
<thead>
<tr>
<th style="text-align: left;">参数名</th>
<th style="text-align: left;">类型</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left;">token</td>
<td style="text-align: left;">String</td>
<td>所有请求的header</td>
</tr>
</tbody>
</table>
<hr />