开发API小技巧

restful api

传统api

获取用户信息 get /api/user/read

更新用户信息 post /api/user/updat

新增用户信息 post/api/user/add

删除用户信息 post/api/user/delete

restful api

获取用户信息 get /api/user/1

更新用户信息put /api/user/1

新增用户信息 post /api/user

删除用户信息deletean/api/user/1

API数据结构格式

HTTP状态码使用TK自带的json实现

status 业务状态码

message 提示信息

data 数据层

functionshow($status, $message, $data=[], $httpCode=200){ $data = ['status'=> $status,'message'=> $message,'data'=> $data, ];returnjson($data, $httpCode);}

不可预知的内部异常api数据输出解决方案

TP5是通过thinkphp-library-think-exception-Handle.php-render来呈现异常数据(但是客户端识别不到这种异常)

config配置exception_handle填写异常类路径

'exception_handle' => '\app\common\lib\exception\ApiHandleException',

class ApiHandleException extends Handle {

/**

* http 状态码

* @var int

*/

public $httpCode = 500;

public function render(\Exception $e) {

// 还原正常报错,上线后为flase(服务端开发)

if(config('app_debug') == true) {

return parent::render($e);

}

if ($e instanceof ApiException) {

$this->httpCode = $e->httpCode;

}

return show(0, $e->getMessage(), [], $this->httpCode);

}

}

支持状态码修改

classApiExceptionextendsException{public$message ='';public$httpCode =500;public$code =0;/** *@paramstring $message *@paramint $httpCode *@paramint $code */publicfunction__construct($message ='', $httpCode =0, $code =0){$this->httpCode = $httpCode;$this->message = $message;$this->code = $code; }}

API数据安全

背景

接口请求地址和参数暴露

重要接口返回数据明文暴露

APP登录态请求的数据完全性问题

代码层的数据完全问题

解决方式就是各种的加密:MD5 AES(对称加密) RSA(非对称,效率较低)基本参数放入header

每次http请求都携带sign (有效时间,唯一性)

sign唯一性保证

请求参数、返回数据按安全性适当加密

access token

客户端和服务器端时间不一致性解决方案

解决:获取服务端时间,客户端拿到服务端正确时间进行对比。然后如果有差值,然后把差值在计算的时候补上

/** * 生成每次请求的sign *@paramarray $data *@returnstring */publicstaticfunctionsetSign($data = []){// 1 按字段排序ksort($data);// 2拼接字符串数据 &$string = http_build_query($data);// 3通过aes来加密$string = (newAes())->encrypt($string);return$string; }/** * 检查sign是否正常 *@paramarray $data *@param$data *@returnboolen */publicstaticfunctioncheckSignPass($data){ $str = (newAes())->decrypt($data['sign']);if(empty($str)) {returnfalse; }// diid=xx&app_type=3parse_str($str, $arr);if(!is_array($arr) ||empty($arr['did']) || $arr['did'] != $data['did'] ) {returnfalse; }// 有效时间:时间间隔不能超过60s (时间使用13位时间戳,这样唯一性会比较强)if(!config('app_debug')) {if((time() - ceil($arr['time'] /1000)) > config('app.app_sign_time')) {returnfalse; }//echo Cache::get($data['sign']);exit;// 唯一性判定if(Cache::get($data['sign'])) {returnfalse; } }returntrue; }/**

* 检查每次app请求的数据是否合法

*/publicfunctioncheckRequestAuth(){// 首先需要获取headers$headers = request()->header();// todo// sign 加密需要 客户端工程师 , 解密:服务端工程师// 1 headers body 仿照sign 做参数的加解密// 2// 3// 基础参数校验if(empty($headers['sign'])) {thrownewApiException('sign不存在',400); }if(!in_array($headers['app_type'], config('app.apptypes'))) {thrownewApiException('app_type不合法',400); }// 需要signif(!IAuth::checkSignPass($headers)) {thrownewApiException('授权码sign失败',401); } Cache::set($headers['sign'],1, config('app.app_sign_cache_time'));// 存储方式 :1、文件 2、mysql 3、redis$this->headers = $headers; }

API接口文档编写(API入参,出参的格式)

有利于客户端工程师熟悉接口

有利于服务端工程师接手项目

API接口地址

请求方式

入参格式

出参格式

http code

APP版本升级

APP更新迭代快

APP是安装在用户手机设备上

APP版本升级的类型

用户自主选择更新

强制更新

开设API接口

APP识别接口做相关判定3

/**

* 客户端初始化接口

* 1、检测APP是否需要升级

*/publicfunctioninit(){// app_type 去ent_version 查询$version = model('Version')->getLastNormalVersionByAppType($this->headers['app_type']);if(empty($version)) {returnnewApiException('error',404); }if($version->version >$this->headers['version']) { $version->is_update = $version->is_force ==1?2:1; }else{ $version->is_update =0;// 0 不更新 , 1需要更新, 2强制更新}// 记录用户的基本信息 用于统计$actives = ['version'=>$this->headers['version'],'app_type'=>$this->headers['app_type'],'did'=>$this->headers['did'], ];try{ model('AppActive')->add($actives); }catch(\Exception$e) {// todo//Log::write();}returnshow(config('code.success'),'OK', $version,200); }

APP端异常、性能监控及定位分析

常见的移动端异常

Crash在使用APP的过程中突然发生闪退现象

卡顿出现画面的卡顿

Exception 程序被catch起来的exception

ANR 出现提示无响应弹框(android)

端异常数据收集方案解剖(统计数据)

Crash 卡顿Exception ANR次数

影响用户数

第三方成熟服务

听云

oneapm

端APP只需要集成第三方平台提供的sdk

APP推送

原始-轮训法处理

APP每隔一段时间向后端发送请求

第三方:极光推送

PHP->第三方推送消息凭条jpush->APP

点赞功能

/** * 新闻点赞功能开发 *@returnarray */publicfunctionsave(){ $id = input('post.id',0,'intval');if(empty($id)) {returnshow(config('code.error'),'id不存在', [],404); }// 判定这个 id的新闻文章 -> ent_news 小伙伴自行加入$data = ['user_id'=>$this->user->id,'news_id'=> $id, ];// 查询库里面是否存在 点赞$userNews = model('UserNews')->get($data);if($userNews) {returnshow(config('code.error'),'已经点赞过,不能再次点赞', [],401); }try{ $userNewsId = model('UserNews')->add($data);if($userNewsId) { model('News')->where(['id'=> $id])->setInc('upvote_count');returnshow(config('code.success'),'OK', [],202); }else{returnshow(config('code.error'),'内部错误 点赞失败', [],500); } }catch(\Exception$e) {returnshow(config('code.error'),'内部错误 点赞失败', [],500); } }/**

* 取消点赞

*/publicfunctiondelete(){ $id = input('delete.id',0,'intval');if(empty($id)) {returnshow(config('code.error'),'id不存在', [],404); }// 判定这个 id的新闻文章 -> ent_news 小伙伴自行加入$data = ['user_id'=>$this->user->id,'news_id'=> $id, ];// 查询库里面是否存在 点赞$userNews = model('UserNews')->get($data);if(empty($userNews)) {returnshow(config('code.error'),'没有被点赞过,无法取消', [],401); }try{ $userNewsId = model('UserNews') ->where($data) ->delete();if($userNewsId) { model('News')->where(['id'=> $id])->setDec('upvote_count');returnshow(config('code.success'),'OK', [],202); }else{returnshow(config('code.error'),'取消失败', [],500); } }catch(\Exception$e) {returnshow(config('code.error'),'内部错误 点赞失败', [],500); } }

小知识点:

后台权限控制使用封装Base类库来达到统一管理的目的,_initialize

调试小技巧 : $this->getLastSql(); halt(); echo ** exit;

mysql default null影响索引性能。

作者:侠客岛的含笑

链接:https://www.imooc.com/article/266726


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容