Hris.php 5.64 KB
<?php
/**
 * Hris.php
 * HRIS 系统接口服务
 * @author Deepseath
 * @version $Id$
 */
namespace deepseath\hris;

use Symfony\Component\Cache\Adapter\FilesystemAdapter;

class Hris
{
    /**
     * 缓存池
     * @var object
     */
    protected $_cache = null;

    /**
     * HRIS 系统原始 token
     * @var string
     */
    protected $_originToken = '';

    /**
     * token 过期时间,单位:秒
     * @var int
     */
    protected $_tokenExpire = 7200;

    /**
     * HRIS 接口服务根 URL
     * @var string
     */
    protected $_baseUrl = '';

    /**
     * 库版本号
     * @var string
     */
    protected $_libVersion = '1.0';

    /**
     * HTTP 请求对象
     * @var object
     */
    protected $_http = null;

    /**
     * 调试模式
     * @var boolean
     */
    protected $_debug = false;

    /**
     * 配置信息
     * @var array
     */
    public $config = [];

    /**
     * 单点实例
     * @param array $options
     * @return \deepseath\hris\Hris
     */
    public static function &instance(array $options)
    {
        static $instance = null;
        if (empty($instance)) {
            $instance = new self($options);
        }
        return $instance;
    }

    private function __construct(array $options = [])
    {
        $this->_cache = new FilesystemAdapter('hris', 86400, 'deepseath' . $this->_libVersion);
        if (function_exists('config')) {
            $config = config('hris');
            if (empty($options)) {
                $options = $config;
            } else {
                $options = array_merge($config, $options);
            }
            unset($config);
        }
        $this->config = $options;
        if (empty($options['originToken'])) {
            throw new \Exception('原始 TOKEN 未定义', 9001);
        }
        if (!empty($options['baseUrl'])) {
            $this->_baseUrl = $options['baseUrl'];
        }
        if (isset($options['debug'])) {
            $this->_debug = $options['debug'];
        }

        $this->_originToken= $options['originToken'];
        $this->_http = \Yurun\Util\HttpRequest::newSession();
    }

    /**
     * 获取 token 信息
     * @param $force bool 是否强制获取更新 token
     * @return array
     * <pre>
     * + access_token   String  Y   令牌
     * + token_type     String  Y   令牌类型
     * + expires_in     String  Y   token有效时间,时间单位秒
     * + scope          String  Y   授权作用域
     * </pre>
     */
    public function getTokenInfo(bool $force = false) : array
    {
        $token = $this->_cache->getItem('token');
        if ($token->isHit() || $force !== false) {
            return $token->get();
        }

        // 初始化 token 信息
        $newTokenInfo = [];
        // 构造 token 获取接口地址
        $url = $this->_baseUrl . 'tokenFlush';
        $params = [
            'token' => $this->_originToken
        ];
        // 请求接口
        $this->_http->headers([
            'Authorization' => $this->_originToken,
            'Content-Type' => 'application/json;charset=utf-8'
        ]);
        $response = $this->_http->post($url, $params, 'json');
        $newTokenInfo = $response->json(true);

        if (empty($newTokenInfo) || !isset($newTokenInfo['code'])) {
            throw new \Exception('request hris token error' . var_export($newTokenInfo, true) . '|' . $url . var_export($params, true), 9001);
        }
        if ($newTokenInfo['code'] != 200) {
            throw new \Exception('HRIS TOKEN GET ERROR:' . $newTokenInfo['msg'] . ':' . $newTokenInfo['code']);
        }

        $newTokenInfo['_datetime'] = date('Y-m-d H:i:s');
        // 将本次获取的 token 值写入到缓存
        $token->set($newTokenInfo);
        if (isset($newTokenInfo['expires_in'])) {
            $expire = $newTokenInfo['expires_in'];
        } else {
            $expire = $this->_tokenExpire;
        }
        $token->expiresAfter($expire - 60 * 5);
        $this->_cache->save($token);

        return $newTokenInfo;
    }

    /**
     * 接口 API POST
     * @param string $path  接口基于版本目录的路径
     * @param array $data   请求的数据
     * @param bool $flushToken  是否强制刷新 token
     * @throws \Exception
     * @return array|string
     */
    public function apiRequest($method, $path, $data, $flushToken = false)
    {
        static $tryCount;
        if ($tryCount === null || $flushToken === false) {
            $tryCount = 1;
        } else {
            $tryCount++;
        }
        if ($tryCount > 3) {
            throw new \Exception('hris SDK Error: Get token error, retry maximum number.');
        }
        $this->_http->headers([
            'Content-Type' => 'application/json;charset=utf-8',
            'Authorization' => $this->getTokenInfo($flushToken)['data']['token']
        ]);
        $url = $this->_baseUrl . $path;
        $method = strtolower($method);
        if ($method == 'post') {
            $dataString = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
            $response = $this->_http->post($url, $dataString, 'json');
        } elseif ($method == 'get') {
            $response = $this->_http->get($url, $data);
        }
        $result = $response->json(true);
        if (!isset($result['code']) || $result['code'] != 0) {
            if ($result['code'] == 3001) {
                // token 无效,尝试重新刷新 token
                return $this->apiRequest($method, $path, $data, true);
            }
            throw new \Exception('hris SDK Error: ' . $result['msg'] . ':' . $result['code'], $result['code']);
        }

        return isset($result['data']) ? $result['data'] : [];
    }
}