此文章更新于 38 天前,有些内容可能已经过期,代码仅供参考,请仔细辨别。

只有拥有访问授权的域名才可以使用所有API接口。域名免费授权请求接口 https://api.ui.ac.cn/auth/apply?domain=你的域名&secretkey=自定义Key 或者访问 https://ui.ac.cn/admin/app.php(需注册)进行申请。

API文档请参阅 https://api.ui.ac.cn/docs.php
完整实例请直接划到文章最底部。

获取Token

拥有授权以后,我们需要请求 https://api.ui.ac.cn/auth/config 来获取token,需要传递的参数为 domain 以及 secretkey ,此接口建议使用 POST 方法请求。注意每次签发的token有效期为两个小时(即7200秒)。以下为请求示例:

$URL = 'https://api.ui.ac.cn/auth/config';
$res = json_decode(httpCurl($URL, [
    'post'=>[
        'domain' => $domain,
        'secretkey' => md5($secretkey)
    ]
]));
$token = $res->data->token;

生成sign

除了所有未强制要求 sign 签名的方法外,请求其他方法都需要传递签名。
此外,通常我们还需要 tokentimestampnonce 这三个参数以及要 传递的数据 来保证请求的安全性、完整性与合法性。
timestamp 为当前时间戳
nonce 为随机字符串
需要传递的数据需要进行排序,生成 sign 的方法为以上所有参数的 MD5 值:

$sign = md5($timestamp.$nonce.$token._sign($data));

完整的示例

需要注意的地方:
tokentimestampnonce 这三个参数需要添加在 header 中,具体方法请看一个获取友情链接的示例:

define('__API__', 'https://api.ui.ac.cn/');

/* 核心文件 */
require_once("api.php");

function showLinks($isAdmin = FALSE) {
    $result = '';
    $url = __API__ . 'links/get';
    $res = request($url);
    $data = json_decode($res, true);
    if($data['statusCode'] != 200) {
        echo 'API接口请求失败,以下为服务器返回的提示信息:<br/><p class="color">' . $data['errMsg'] . '</p>';
        return;
    }
    $data = $data['data']['list'];
    foreach ($data as $var) {
        $result .= '<a class="list-item" href="'.$var['url'].'"><div class="list-item-avatar"><img src="'.$var['logo'].'"/></div><div class="list-item-content"><div class="list-item-title">'.$var['title'].'</div><div class="list-item-text list-item-one-line">'.$var['desc'].'</div></div></a>';
    }
    
    echo '<div class="list">' . $result . '</div>';
}

function request($url, $param = array()) {
    $signPackage = _getSignPackage($param);
    $prefix = strpos($url,'?') ? '&' : '?';
    return httpCurl($url.$prefix.'sign='. $signPackage['sign'], [
        'Header'=>[
        'Authorization: '.$signPackage['token'].'
Timestamp: '.$signPackage['timestamp'].'
Nonce: '.$signPackage['nonce'].'
cache-control: max-age=0'
    ]
    ]);
}

以下为 api.php 的内容:

<?php

/* 获取签名包 */
function _getSignPackage($data = array()) {
    $token = _getToken();
    $timestamp = time();
    $nonce = _createNonceStr();
    $sign = md5($timestamp.$nonce.$token._sign($data));
    $signPackage = array(
        'token' => $token,
        'timestamp' => $timestamp,
        'nonce' => $nonce,
        'sign' => $sign
    );
    return $signPackage; 
}

/* 获取Token */
function _getToken() {
    // token 应该全局存储与更新
    //$file = __TYPECHO_ROOT_DIR__ . __TYPECHO_THEME_DIR__ . '/soda/token.php';
    $data = json_decode(_getFile(Helper::options()->themeUrl . '/token.php'));
    if ($data->exp < time()) {
        $url = "https://api.ui.ac.cn/auth/config";
        $res = json_decode(httpCurl($url, [
            'post'=>[
                'domain'=>'ui.ac.cn',
                'secretkey'=>md5(Helper::options()->key)
            ]
        ]));
        $token = $res->data->token;
        if($token) {
            $data = new stdClass();
            $data->exp = time() + 7000;
            $data->token = $token;
            _setFile(Helper::options()->themeUrl . '/token.php', json_encode($data));
        } else {
            echo $res->errMsg . '<br/><br/>';
        }
    } else {
        $token = $data->token;
    }
    return $token;
}

/* 生成16位随机数 */
function _createNonceStr($length = 16) {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $str = "";
    for ($i = 0; $i < $length; $i++) {
        $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
    }
    return $str;
}

/* 对请求数据进行排序 */
function _sign($data) {
    ksort($data);
    
    $stringA = '';
    foreach ($data as $key => $value) {
        if (!$value||$key==='sign'||$key==='s'||$key==='service') continue;
        if ($stringA) $stringA .= '&' . $key . "=" . $value;
        else $stringA = $key . "=" . $value;
    }
    return $stringA;
}

/* 读取文件 */
function _getFile($filename) {
    return trim(substr(file_get_contents($filename), 15));
}

/* 写入文件 */
function _setFile($filename, $content) {
    file_put_contents($filename, "<?php exit();?>" . $content);
}

这样,就可以愉快地使用所有api接口了 ~