<?php /** * Hris.php * HRIS 系统接口服务 * @author Deepseath * @version $Id$ */ namespace deepseath\hris; use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Contracts\Cache\ItemInterface; class Hris { /** * 缓存池 * @var \Symfony\Component\Cache\Adapter\FilesystemAdapter */ 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 \Yurun\Util\HttpRequest */ 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, null); 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']; } if (!isset($this->config['mapping_expire'])) { $this->config['mapping_expire'] = 86400 * 7; } $this->_originToken= $options['originToken']; $this->_http = \Yurun\Util\HttpRequest::newSession(); } /** * 缓存对象 * @return \Symfony\Component\Cache\Adapter\FilesystemAdapter */ public function cache() { return $this->_cache; } /** * 获取 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 { if ($force !== false) { return $this->_getTokenInfoWithoutCache(); } else { return $this->_cache->get('hris_token', function (ItemInterface $item) { $tokenInfo = $this->_getTokenInfoWithoutCache(); $item->expiresAfter($tokenInfo['expires_in']); return $tokenInfo; }); } } /** * 获取 token 信息,无缓存 */ private function _getTokenInfoWithoutCache() { // 初始化 token 信息 $newTokenInfo = []; // 构造 token 获取接口地址 $url = $this->_baseUrl . 'tokenFlush'; $params = [ 'token' => $this->_originToken ]; // 请求接口 $headers = [ 'Authorization' => $this->_originToken, 'Content-Type' => 'application/json;charset=utf-8' ]; $this->_http->headers($headers); $this->log($url, 'Get Token'); $this->log($params, 'Request'); $this->log($headers, 'Header'); $response = $this->_http->post($url, $params, 'json'); $newTokenInfo = $response->json(true); $this->log($newTokenInfo, 'Result'); 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']); } if (!isset($newTokenInfo['expires_in'])) { $newTokenInfo['expires_in'] = $this->_tokenExpire; } return $newTokenInfo; } /** * 接口 API POST * @param string $path 接口基于版本目录的路径 * @param array $data 请求的数据 * @param bool $flushToken 是否强制刷新 token * @throws \Exception * @return array */ 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.'); } $headers = [ 'Content-Type' => 'application/json;charset=utf-8', 'Authorization' => $this->getTokenInfo($flushToken)['data']['token'] ]; $this->_http->headers($headers); $url = $this->_baseUrl . $path; $method = strtolower($method); $this->log($url, 'Url'); $this->log($method, 'Method'); $this->log($headers, 'Header'); $this->log($data, 'Request'); 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); } $body = $response->body(); $this->log($response->getStatusCode(), 'StatusCode'); $this->log($body, 'Body'); $result = $response->json(true); $this->log($result, 'Result'); if (!isset($result['code']) || $result['code'] != 200) { if (isset($result['code']) && ($result['code'] == '3001')) { // token 无效,尝试重新刷新 token $this->log($tryCount, 'Try count'); return $this->apiRequest($method, $path, $data, true); } if (isset($result['msg']) && isset($result['code'])) { throw new \Exception(json_encode([ 'url' => $url, 'title' => 'hris SDK request error', 'msg' => $result['msg'], 'code' => $result['code'], 'request' => $data, 'result' => $result, ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), $result['code']); } else { throw new \Exception(json_encode([ 'url' => $url, 'title' => 'hris SDK response error', 'msg' => $result, 'result' => $result, 'response' => $body, ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE), 90001); } } return isset($result['data']) ? $result['data'] : ($result['msg'] ?? []); } /** * 打印调试日志 * @param mixed $info */ public function log($info, $title = '', $level = 'hris') { if ($this->_debug) { $info = is_scalar($info) ? $info : json_encode($info, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); $title = $title ? "[{$title}]" : ''; \think\facade\Log::write($title . $info, 'hris'); } } }