通用 - 签名接口

接口请求字段包含appid,time,nostr,data,sign,具体要求如下:

  • appid 接口请求认证账号,需要保持两端一致;
  • nostr 接口请求随机字符串,可以使用随机函数生成;
  • time 接口请求时间(时差不能超过30秒),这里用的是时间戳,单位为
  • data 接口请求数据(数据需转为JSON格式),需以原格式传输,不然会影响签名;
  • sign 接口数据签名,依次appid,data,time,appkey,nostr 五个字段以#连接,并进行MD5编码获取签名;
  • 特别注意:参与签名的appkey为接口私钥,仅用于签名且不参与接口数据请求,接口的文件传输请使用base64传输(要去掉数据头部);
  • 调试模式:当前接口的debugtrue时,不需要传签名内容,只需要以普通表单传原接口的data内容(非JSON格式),以方便调试编写文档;
  • 列表分页:当使用列表分页时,需要以get方式传page参数,page不需要参与签名,传在dataJSON中会无效,因为数据格式与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);
    }

}

如果需要使用数据库来管理接口账号,需要调整下初始化方法

// 从数据库中账号检查
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->service = InterfaceService::instance();
$this->service->setAuth($this->user['appid'], $this->user['appkey']);
[$this->data, $this->appid] = [$this->service->getData(), $this->service->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));
Last Updated:
Contributors: 邹景立