通用 - 签名接口
接口请求字段包含appid
,time
,nostr
,data
,sign
,具体要求如下:
appid
接口请求认证账号,需要保持两端一致;nostr
接口请求随机字符串,可以使用随机函数生成;time
接口请求时间(时差不能超过30
秒),这里用的是时间戳,单位为秒
;data
接口请求数据(数据需转为JSON
格式),需以原格式传输,不然会影响签名;sign
接口数据签名,依次appid
,data
,time
,appkey
,nostr
五个字段以#
连接,并进行MD5
编码获取签名;- 特别注意:参与签名的
appkey
为接口私钥,仅用于签名且不参与接口数据请求,接口的文件传输请使用base64
传输(要去掉数据头部); - 调试模式:当前接口的
debug
为true
时,不需要传签名内容,只需要以普通表单传原接口的data
内容(非JSON格式),以方便调试编写文档; - 列表分页:当使用列表分页时,需要以
get
方式传page
参数,page
不需要参与签名,传在data
的JSON
中会无效,因为数据格式与Page
参数不符;
前端客户端请求案例:
签名用到了MD5
插件,需要自行加载组件哦,最好做下md5
算法测试:
// 对字符串 test 进行 md5 加密测试
let md5 = require('js-md5');
console.log(md5('test'));
// 输出值为: 098f6bcd4621d373cade4e832627b4f6
JavaScript 客户端请求案例:
let md5 = require('js-md5');
let params = {appid: 'APPID', appkey: 'APPKEY'};
let postdata = {name: 1, test: 2, desc: '你的参数'};
// 接口请求数据组装
let nostr = Math.random();
let json = JSON.stringify(postdata);
let time = Math.ceil(Date.now() / 1000);
let sign = md5.hex([params.appid, json, time, params.appkey, nostr].join('#'));
let data = {appid: params.appid, time: time, nostr: nostr, data: json, sign: sign};
$.form.load('{:url("data/api.data/getSlider")}', data, 'post', function (ret) {
// @TODO 处理返回的结果
console.log(ret);
return false;
});
后端客户端请求案例:
use think\admin\service\InterfaceService;
// 实例接口服务接口
$service = InterfaceService::instance();
$service->getway(GETWAY); // 设置接口请求网关
$service->setAuth(APPID, APPKEY); // 设置接口认证账号
$result = $service->doRequest('API_URL', DATA); // 发起接口请求
print_r($result);
服务端接口控制器案例:
namespace app\data\controller\api;
use think\admin\Controller;
use think\admin\service\InterfaceService;
/**
* 接口授权基础控制器
* Class Auth
* @package app\data\controller\api
*/
class Auth extends Controller
{
/**
* 当前请求数据
* @var array
*/
protected $data;
/**
* 接口ID
* @var string
*/
protected $appid = '接口账号';
/**
* 接口密钥
* @var string
*/
protected $appkey = '接口密钥';
/**
* 接口服务对象
* @var InterfaceService
*/
protected $interface;
/**
* 接口授权初始化
*/
protected function initialize()
{
// 实例接口对象
$this->interface = InterfaceService::instance();
// 获取接口数据
$this->interface->setAuth($this->appid, $this->appkey);
$this->data = $this->interface->getData();
}
/**
* 响应错误消息
* @param mixed $info
* @param mixed $data
* @param mixed $code
*/
public function error($info, $data = '{-null-}', $code = 0): void
{
$this->interface->error($info, $data, $code);
}
/**
* 响应成功消息
* @param mixed $info
* @param mixed $data
* @param mixed $code
*/
public function success($info, $data = '{-null-}', $code = 1): void
{
$this->interface->success($info, $data, $code);
}
/**
* 响应高级数据
* @param array $data
*/
protected function response(array $data = []): void
{
$this->interface->baseSuccess('接口调用成功!', $data);
}
}
如果需要使用数据库来管理接口账号,需要调整下初始化方法
// 接口实例初始化
$this->interface = InterfaceService::instance();
// 从数据库中账号检查 ( 用自己的数据表 )
$map = $this->_vali(['appid.require' => '参数APPID不能为空!']);
$this->user = $this->app->db->name('AppUser')->where($map)->find();
if (empty($this->user)) $this->error('接口账号不存在!');
if (empty($this->user['status'])) $this->error('接口账号已被禁用!');
if (!empty($this->user['is_deleted'])) $this->error('接口账号已被移除!');
// 接口数据初始化
$this->interface->setAuth($this->user['appid'], $this->user['appkey']);
[$this->data, $this->appid] = [$this->interface->getData(), $this->interface->getAppid()];
处理业务时,可以对接口提交过来的数据进行二次验证(需要继承基础控制器)
// 接收并验证参数是否符合要求,失败返回业务错误内容
$data = $this->_vali([...], $this->data, [$this,'error']);
// 使用 $this->_query 动态传参数查询,与后台控制器操作无差别(只需要指定数据)
$query = $this->_query($this->table, $this->data);
$query->like(...)->equal(...)->in(...); // 绑定查询条件
$this->success("操作成功", $query->page(true,false));