15 KiB
如何开发接口
使用PhalApi专业版开发接口,非常简单,大致流程如下。
目录结构
PhalApi Pro版的目录结构如下,
./
├── README.md # 简介
├── bin # 脚本目录
├── config # 配置目录
│ ├── app.php # 应用配置
│ ├── dbs.php # 数据库配置
│ ├── di.php # 依赖服务配置
│ └── sys.php #系统配置
├── data # 数据库
│ └── phalapi_pro.sql # 数据库安装时的文件
├── language # 翻译包
├── pro_admin # 管理后台的前端源代码,基于iview-admin
├── pro_platform # 开放平台的前端源代码,基于iview-admin
├── public # 对外访问的目录
│ ├── admin # 管理后台访问入口(相当于pro_admin打包构建后的dist目录)
│ ├── api # 接口访问入口(内分前台API和后台API)
│ ├── docs # 离线生成的HTML接口文档
│ ├── docs.php # 在线版接口文档访问入口
│ ├── index.php
│ ├── init.php # 全局初始化文件
│ ├── install # 安装向导(成功安装后建议删除此目录)
│ ├── platform # 开放平台访问入口(相当于pro_platform打包构建后的dist目录)
│ ├── static # 静态资源
│ ├── uploads # 上传目录(需要有写入权限)
│ └── wiki # 技术文档
├── runtime # 运行目录
│ ├── _install.lock # 安装锁定文件
│ ├── cache # 文件缓存
│ └── log # 文件日志
├── sdk # SDK包
├── src # 项目源代码,非常重要
│ ├── admin # 后台接口源代码(遵循ADM模式)
│ ├── app # 开放平台接口源代码(遵循ADM模式)
│ ├── base # 基础包源代码(放置底层公共的代码,不对外直接提供接口,即不提供Api层)
│ ├── platform # 开放平台接口源代码(遵循ADM模式)
│ ├── task # 计划任务接口源代码(遵循ADM模式)
│ └── view # 页面模板目录(如接口文档)
├── tests # 单元测试
└── vendor # composer包,不需要手动修改,通过composer install/update可进行安装和更新
编写Api接口层
如果需要编写开放接口,可以在./src/app/Api目录下新增一个PHP文件,类名和文件名一样(需要区分大小写)。并继承App\Common\Api基类即可。
例如开放接口的Hello World示例,接口文件是:./src/app/Api/HelloWorld.php,类名是:App\Api\HelloWorld,对接的接口服务名称是:App.HelloWorld.Say。
<?php
namespace App\Api;
use App\Common\Api;
/**
* Hello World示例
*/
class HelloWorld extends Api {
// 接口参数配置
public function getRules() {
return array(
'say' => array(
'nickname' => array('name' => 'nickname', 'desc' => '昵称'),
),
);
}
/**
* 示例
* @desc 第一个前台接口示例
*/
public function say() {
$nickname = $this->nickname;
return array('content' => 'Hello world!');
}
}
如果需要编写后台接口,则需要放置在./src/admin/Api目录下,并继承Admin\Common\Api基类。其他开发要求类似。
温馨提示:以下方法是系统保留的函数名,不以用于接口函数名称,否则会影响接口正常运行。系统保留接口函数名称有:tryToGetUid()、checkUserLogin()、tryToGetAppKey()、checkAppOnline()、getCurContext()、init()、createMemberValue()、getApiRules()、getApiCommonRules()、getRules()、filterCheck()、userCheck()、isServiceWhitelist()、equalOrIngore()。
如何取消接口令牌验证?
默认情况下,前台接口需要进行access_token令牌验证,以保护接口不被非法请求。如果不需要对指定的接口进行验证,可以在配置文件./config/app.php中的service_whitelist白名单中添加接口。例如上面的HelloWorld接口不需要接口验证,可以在最后追加配置:
'service_whitelist' => array(
'Site.Index',
'HelloWorld.Say', // 追加Hello World示例白名单
),
接口白名单配置,会取消过滤器,不进行任何校验和判断,此时不会相应调整应用的接口权限。如果需要让接口权限在界面上显示保持一致,可以配置接口权限规则。
温馨提示:配置接口白名单,开放平台和管理后台的接口权限显示不会影响。
如何取消接口权限判断?
-
如何取消全部接口权限判断?
可以修改./config/app.php里面的default_app_api_rigths_is_allow配置项为true,即可让开放接口默认拥有权限,相当于取消全部接口权限判断。 -
如何取消某个接口类的接口权限判断?
在你的接口具体子类中,重载\App\Common\Api::userCheck()方法,不进行任何操作即可。
/**
* 平台接口基类
*/
class Api extends \App\Common\Api {
/**
* 进行接口权限判断
* @throws BadRequestException
*/
protected function userCheck() {
// 不需要
}
}
温馨提示:通过代码取消接口权限判断,开放平台和管理后台的接口权限显示不会影响。
- 如何取消一个接口的接口权限判断?
在你的接口具体子类中,重载\App\Common\Api::userCheckActionWhitelist()方法,返回不需要进行接口权限判断的接口白名单。
<?php
namespace App\Api;
use App\Common\Api;
/**
* Hello World示例
*/
class HelloWorld extends Api {
protected function userCheckActionWhitelist() {
return array('hiApp', 'hiMember');
}
}
温馨提示:通过代码取消接口权限判断,开放平台和管理后台的接口权限显示不会影响。
如何获取当前上下文信息?
如何获取当前上下文、登录会员ID和app_key?
在App\Common\Api接口基类中,已经封装了针对于当前上下文、登录会员ID和app_key等接口,方便项目快速开发。
以下是使用代码和相关说明。
class HelloWorld extends Api {
public function say() {
// 获取会员ID,未登录时异常返回
$uid = $this->tryToGetUid();
// 获取会员ID,未登录时返回0
$uid = $this->tryToGetUid(false);
// 检测会员是否已登录,未登录时异常返回
$this->checkUserLogin();
// 获取app_key,未指定时异常返回
$appKey = $this->tryToGetAppKey();
// 获取app_key,未指定时返回空字符串
$appKey = $this->tryToGetAppKey(false);
// 检测是否已指定app_key
$this->checkAppOnline();
// 获取当前上下文
$context = $this->getCurContext();
var_dump($context->getUid()); // 会员ID
var_dump($context->getAppKey()); // app_key
}
}
如何隐藏access_token参数?
如果不需要在接口文档上显示access_token参数,可以在接口参数规则里这样配置(设置is_doc_hide为true即可)。
class HelloWorld extends Api {
public function getRules() {
return array(
'say' => array(
'accessToken' => array('name' => 'access_token', 'is_doc_hide' => true),
),
)
}
}
编写Domain领域层
Domain领域层主要用于封装复杂的业务逻辑、规则和算法。此部分PHP代码放置在./src/app/Domain目录下。此部分根据不同项目的业务需求,具体开发即可。
编写Model数据层
Model数据层主要用于操作MySQL数据库,全部的Model子类可继承Base\Model\Base基类,此基类封装了很多实用的方法和接口,极大减少了数据库封装的代码。例如对应配置表的配置Model类代码如下:
<?php
namespace App\Model;
class Config extends Base {
}
对应源代码文件是:./src/app/Model/Config.php。
在继承Base\Model\Base数据库基类后,可以很方便进行数据库的操作和查询。
更多关于数据库的连接、操作、查询、多数据库使用等,请参考DataModel数据模型 - PhalApi 2.x 开发文档。
如何新增API接口命名空间?
默认情况,推荐将接口统一放置在App命名空间,即src/app目录下。如果项目有需要,可以新增自己的接口命名空间。
首先,参考开源版文档如何增加一个顶级命名空间?,增加一个新的顶级命名空间。
然后,修改./config/app.php配置文件里的open_api_namespaces配置,追加你的命名空间。
// 开放接口的命名空间,配置后可提供接口权限分配,可配置多个
'open_api_namespaces' => array('App', '新的顶级命名空间'),
例如,加了Task命名空间后:
// 开放接口的命名空间,配置后可提供接口权限分配,可配置多个
'open_api_namespaces' => array('App', 'Task'),
在管理后台可以自动管理该命名空间下的接口权限。
接口权限分配:

接口服务列表:

如何隐藏接口?
和开源版一样,在接口类或方法中添加@ignore注释。
如:
<?php
namespace App\Api;
use App\Common\Api;
/**
* Hello World示例
* @ignore
*/
class HelloWorld extends Api {
/**
* 接口示例
* @desc 一个开放接口示例,可直接访问,不需要任何验证,因为配置了service_whitelist白名单。熟悉后可删除此示例接口。
* @ignore
* @return string content 一句话
*/
public function say() {
return array('content' => 'Hello PhalApi Pro!');
}
}
如何开启接口参数加密传输?
为了保护客户端传递的参数不被外界非法获取,除了使用HTTPS协议外,也可以通过代码方式来增加。
在PhalApi专业版,你可以:
** 客户端RSA公钥加密传输API接口参数 + 服务端RSA私钥解密API接口参数。**
重要配置
首先,是RSA私钥和公钥的文件,分别是:
- rsa私钥文件:./config/phalapi_pro_rsa.pri
- rsa公钥文件:./config/phalapi_pro_rsa.pub
在项目启动或开始时,你可以更换以上RSA配置文件,项目开始使用后,不建议再更换。
其次,还可以开启./config/app.php配置文件中的encrypt_data公共参数,方便客户端查看可以传递此参数以及其格式要求说明。
/**
* 应用接口层的统一参数
*/
'apiCommonRules' => array(
'accessToken' => array('name' => 'access_token', 'default' => '', 'desc' => '访问令牌,仅当开启签名验证时需要传递,生成令牌可使用App.Auth.ApplyToken接口'),
/** ----- 如果你需要使用第二套加密算法,请开启以下参数规则 ----- **/
// 'app_key' => array('name' => 'app_key', 'default' => '', 'desc' => 'app_key,用于区分客户端应用,首次接入需要创建应用并等待管理员审核通过'),
// 'sign' => array('name' => 'sign', 'desc' => '动态签名,签名算法是:<br/><ul><li>1、全部参数(排除sign),按key进行字典排序</li><li>2、全部参数值,把原始值按字符串进行拼接,并在最后加上app_secret密钥</li><li>3、对第2步结果,拼接密钥后,进行MD5加密</li><li>4、对第3步结果,转成大写,得到sign签名(32位)</li></ul>'),
// 'uid' => array('name' => 'uid', 'type' => 'int', 'default' => 0, 'desc' => ''),
// 'accessToken' => array('name' => 'access_token', 'default' => '', 'desc' => '访问令牌,保留使用但不需要在文档上展示', 'is_doc_hide' => true),
'encryptData' => array('name' => 'encrypt_data', 'desc' => '客户端加密的接口,格式是:RSA公钥加密(base64编码(JSON原始数据))。开启后,同时支持原来普通的参数传递方式。'),
),
客户端RSA公钥加密传输API接口参数
将rsa公钥文件:./config/phalapi_pro_rsa.pub提供给受信任的客户端开发人员,其中待加密的encrypt_data参数格式是:
encrypt_data = RSA公钥加密(base64编码(JSON原始数据))
也就是:
- 第1步、把全部的原始参数通过JSON格式封装
- 第2步、对第1步结果进行base64编码
- 第3步、使用RSA公钥进行加密
- 第4步、得到encrypt_data
以下是PHP作为客户端编写的代码示例:
// 公钥加密-由客户端完成
$public_key = openssl_pkey_get_public(file_get_contents('./phalapi_pro_rsa.pub'));
openssl_public_encrypt('{"name":"phalapi pro"}', $crypted, $public_key);
$_REQUEST['encrypt_data'] = base64_encode($crypted);
// K07LIy/V+cfZqfHgZpIPnmdkwlkFbTkyRXVXx2JfQrF3YFAIsFcHnC9TjGTezzyup2f0V24nYH71Uf3oXVIqz/X9wgPXW0AGAbJw4kDOIq9Jao5L0mG7t5FV/2DLzJ14qO6fvANv6e/Hy2pFBcKvHnQ8uRJ/wyAV+RpUAa21wCY6zzuo9OhS89NPZg4B4CUORR8SIuIqWTUlXHB0woFIfRiO/AKCGltc9oDkyzJFYVvgI0LwijkQUV9RoruCEx6EvmZY7OVLB5+AXwfnfFKKtCw3jucqHyclzXwCQoif8FXN1NzCNpYvwj7DbzqU/WzRgxnPgXQSyjbCDlw19BrWoQ==
以上,原始的参数是:{"name":"phalapi pro"},最后加密后的结果如上。
温馨提示:客户端可以把需要加密的参数放到encrypt_data,同时服务端接口也会继续支持原来原始参数的传递。两者重复时以加密的参数为准。
服务端RSA私钥解密API接口参数
此部分由后端API接口自动完成。不影响原有的接口参数传递方式和接口参数规则配置。
composer的使用
PhalApi专业版和PhalApi 2.x开源一样,都是使用了composer,如果对PHP composer不熟悉,可以查看Composer 中文网 / Packagist 中国全量镜像,简单来说,composer是 PHP 用来管理依赖(dependency)关系的工具。
由于国外镜像通常会很慢,本地使用时可以切换到中国镜像。执行以下命令:
$ composer config -g repo.packagist composer https://packagist.phpcomposer.com
扩展阅读
更多内容请参考PhalApi 2.x 开发文档。



