Commit 86126dd047fa8f191eed6bfc5aa719ff31695452

Authored by Chu Xiang
1 parent edfb902b

初始化项目

.gitignore 0 → 100644
  1 +/vendor
  2 +/composer.lock
  3 +/.idea
  4 +index.php
0 5 \ No newline at end of file
... ...
composer.json 0 → 100644
  1 +{
  2 + "require": {
  3 + "pimple/pimple": "^3.2",
  4 + "guzzlehttp/guzzle": "^6.3",
  5 + "symfony/http-kernel": "^4.3",
  6 + "symfony/http-foundation": "^4.3"
  7 + },
  8 + "require-dev":{
  9 + "symfony/var-dumper": "^4.3"
  10 + },
  11 + "autoload": {
  12 + "psr-4": {
  13 + "PgServiceSdk\\": "src/"
  14 + }
  15 + }
  16 +}
... ...
src/Application.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk;
  4 +
  5 +use PgServiceSdk\Kernel\ServiceContainer;
  6 +
  7 +/**
  8 + * Class Application
  9 + * @package PgServiceSdk
  10 + *
  11 + * @property \PgServiceSdk\Work\MemberClient $member
  12 + */
  13 +class Application extends ServiceContainer
  14 +{
  15 + /**
  16 + * 应用的服务提供者
  17 + *
  18 + * @var array
  19 + */
  20 + protected $providers = [
  21 + Work\ServiceProvider::class,
  22 + ];
  23 +}
... ...
src/Kernel/BaseClient.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel;
  4 +
  5 +use GuzzleHttp\Client;
  6 +use GuzzleHttp\Middleware;
  7 +use GuzzleHttp\Psr7\Request;
  8 +use GuzzleHttp\ClientInterface;
  9 +use PgServiceSdk\Kernel\Http\Response;
  10 +use Psr\Http\Message\RequestInterface;
  11 +use GuzzleHttp\Exception\ClientException;
  12 +use GuzzleHttp\Exception\ServerException;
  13 +use GuzzleHttp\Exception\RequestException;
  14 +use PgServiceSdk\Kernel\Support\Collection;
  15 +use PgServiceSdk\Kernel\Traits\HasHttpRequest;
  16 +use PgServiceSdk\Kernel\Library\Apim\ApimSign;
  17 +use GuzzleHttp\Psr7\Response as GuzzleResponse;
  18 +use PgServiceSdk\Kernel\Exceptions\ValidationException;
  19 +use PgServiceSdk\Kernel\Exceptions\BadRequestException;
  20 +use PgServiceSdk\Kernel\Exceptions\AuthorizationException;
  21 +use PgServiceSdk\Kernel\Exceptions\InvalidConfigException;
  22 +use PgServiceSdk\Kernel\Exceptions\ServiceInvalidException;
  23 +use PgServiceSdk\Kernel\Exceptions\ResourceNotFoundException;
  24 +
  25 +/**
  26 + * Class BaseClient
  27 + * @package PgServiceSdk\Kernel
  28 + */
  29 +class BaseClient
  30 +{
  31 + use HasHttpRequest {
  32 + request as performRequest;
  33 + }
  34 +
  35 + /**
  36 + * Pimple 容器
  37 + *
  38 + * @var ServiceContainer
  39 + */
  40 + protected $app;
  41 +
  42 + /**
  43 + * option 选项中 baseUri,子类可覆盖
  44 + *
  45 + * @var string
  46 + */
  47 + protected $baseUri;
  48 +
  49 + /**
  50 + * 是否处理 JSON 请求的空数组逻辑
  51 + *
  52 + * @var bool
  53 + */
  54 + protected $handleEmptyArray = true;
  55 +
  56 + /**
  57 + * BaseClient constructor.
  58 + * @param ServiceContainer $app
  59 + */
  60 + public function __construct(ServiceContainer $app)
  61 + {
  62 + $this->app = $app;
  63 + }
  64 +
  65 + /**
  66 + * 发送 GET 请求
  67 + *
  68 + * @param string $url
  69 + * @param array $query
  70 + *
  71 + * @return array|object|Collection|\Psr\Http\Message\ResponseInterface|string
  72 + *
  73 + * @throws AuthorizationException
  74 + * @throws InvalidConfigException
  75 + * @throws ResourceNotFoundException
  76 + * @throws ServiceInvalidException
  77 + * @throws ValidationException
  78 + */
  79 + public function httpGet($url, array $query = [])
  80 + {
  81 + return $this->request($url, 'GET', ['query' => $query]);
  82 + }
  83 +
  84 + /**
  85 + * 发送表单数据(application/x-www-form-urlencoded)
  86 + *
  87 + * @param string $url
  88 + * @param array $data
  89 + *
  90 + * @return array|object|Collection|\Psr\Http\Message\ResponseInterface|string
  91 + *
  92 + * @throws AuthorizationException
  93 + * @throws InvalidConfigException
  94 + * @throws ResourceNotFoundException
  95 + * @throws ServiceInvalidException
  96 + * @throws ValidationException
  97 + */
  98 + public function httpPost($url, array $data = [])
  99 + {
  100 + return $this->request($url, 'POST', ['form_params' => $data]);
  101 + }
  102 +
  103 + /**
  104 + * 发送 POST JSON 请求
  105 + *
  106 + * @param string $url
  107 + * @param array $data
  108 + * @param array $query
  109 + *
  110 + * @return array|object|Collection|\Psr\Http\Message\ResponseInterface|string
  111 + *
  112 + * @throws AuthorizationException
  113 + * @throws InvalidConfigException
  114 + * @throws ResourceNotFoundException
  115 + * @throws ServiceInvalidException
  116 + * @throws ValidationException
  117 + */
  118 + public function httpPostJson($url, array $data = [], array $query = [])
  119 + {
  120 + if ($this->handleEmptyArray) {
  121 + $data = $this->handleJsonEmptyArray($data);
  122 + }
  123 +
  124 + return $this->request($url, 'POST', ['query' => $query, 'json' => $data]);
  125 + }
  126 +
  127 + /**
  128 + * 发送 PUT JSON 请求
  129 + *
  130 + * @param string $url
  131 + * @param array $data
  132 + * @param array $query
  133 + *
  134 + * @return array|object|Collection|\Psr\Http\Message\ResponseInterface|string
  135 + *
  136 + * @throws AuthorizationException
  137 + * @throws InvalidConfigException
  138 + * @throws ResourceNotFoundException
  139 + * @throws ServiceInvalidException
  140 + * @throws ValidationException
  141 + */
  142 + public function httpPutJson($url, array $data = [], array $query = [])
  143 + {
  144 + if ($this->handleEmptyArray) {
  145 + $data = $this->handleJsonEmptyArray($data);
  146 + }
  147 +
  148 + return $this->request($url, 'PUT', ['query' => $query, 'json' => $data]);
  149 + }
  150 +
  151 + /**
  152 + * 发送 PATCH JSON 请求
  153 + *
  154 + * @param string $url
  155 + * @param array $data
  156 + * @param array $query
  157 + *
  158 + * @return array|object|Collection|\Psr\Http\Message\ResponseInterface|string
  159 + *
  160 + * @throws AuthorizationException
  161 + * @throws InvalidConfigException
  162 + * @throws ResourceNotFoundException
  163 + * @throws ServiceInvalidException
  164 + * @throws ValidationException
  165 + */
  166 + public function httpPatchJson($url, array $data = [], array $query = [])
  167 + {
  168 + if ($this->handleEmptyArray) {
  169 + $data = $this->handleJsonEmptyArray($data);
  170 + }
  171 +
  172 + return $this->request($url, 'PATCH', ['query' => $query, 'json' => $data]);
  173 + }
  174 +
  175 + /**
  176 + * 发送表单上传附件
  177 + *
  178 + * @param string $url
  179 + * @param array $files
  180 + * @param array $form
  181 + * @param array $query
  182 + *
  183 + * @return array|object|Collection|\Psr\Http\Message\ResponseInterface|string
  184 + *
  185 + * @throws AuthorizationException
  186 + * @throws InvalidConfigException
  187 + * @throws ResourceNotFoundException
  188 + * @throws ServiceInvalidException
  189 + * @throws ValidationException
  190 + */
  191 + public function httpUpload($url, array $files = [], array $form = [], array $query = [])
  192 + {
  193 + $multipart = [];
  194 +
  195 + foreach ($files as $name => $file) {
  196 + $multipart [] = [
  197 + 'name' => $name,
  198 + 'contents' => $file,
  199 + ];
  200 + }
  201 +
  202 + foreach ($form as $name => $contents) {
  203 + $multipart[] = compact('name', 'contents');
  204 + }
  205 +
  206 + return $this->request($url, 'POST', compact('multipart', 'query'));
  207 + }
  208 +
  209 + /**
  210 + * 发送请求
  211 + *
  212 + * @param string $url
  213 + * @param string $method
  214 + * @param array $options
  215 + * @param bool $returnRaw
  216 + *
  217 + * @return \Psr\Http\Message\ResponseInterface|\PgServiceSdk\Kernel\Support\Collection|array|object|string
  218 + *
  219 + * @throws AuthorizationException
  220 + * @throws InvalidConfigException
  221 + * @throws ResourceNotFoundException
  222 + * @throws ServiceInvalidException
  223 + * @throws ValidationException
  224 + */
  225 + public function request($url, $method = 'POST', array $options = [], $returnRaw = false)
  226 + {
  227 + if (empty($this->middlewares)) {
  228 + $this->registerMiddleware();
  229 + }
  230 +
  231 + try {
  232 + $response = $this->performRequest($url, $method, $options);
  233 + } catch (ClientException $e) {
  234 + $response = $e->getResponse();
  235 + $code = $response->getStatusCode();
  236 + $contents = $response->getBody()->getContents();
  237 + $content = json_decode($contents);
  238 + $message = property_exists($content, 'message') ? $content->message : '';
  239 +
  240 + switch ($code) {
  241 + case 404:
  242 + throw new ResourceNotFoundException($message, 404);
  243 + case 400:
  244 + case 422:
  245 + throw new ValidationException($message, 400);
  246 + break;
  247 + case 401:
  248 + throw new AuthorizationException($message, 401);
  249 + default:
  250 + throw new ServiceInvalidException($message ? $message : 'Service Invalid', 500);
  251 + }
  252 + } catch (ServerException $e) {
  253 + $response = $e->getResponse();
  254 + $contents = $response->getBody()->getContents();
  255 + $content = json_decode($contents);
  256 + $message = property_exists($content, 'message') ? $content->message : 'Service Invalid';
  257 +
  258 + throw new ServiceInvalidException($message, 500);
  259 + } catch (RequestException $e) {
  260 + // 在发送网络错误(连接超时、DNS错误等)时
  261 + throw new BadRequestException($e->getMessage(), 400);
  262 + }
  263 +
  264 + if ($returnRaw) {
  265 + return $response;
  266 + }
  267 +
  268 + $responseType = $this->app->config->get('response_type');
  269 + $result = $this->costResponseToType($response, $responseType);
  270 +
  271 + return $result;
  272 + }
  273 +
  274 + /**
  275 + * 自定义请求,响应对象
  276 + *
  277 + * @param string $url
  278 + * @param string $method
  279 + * @param array $options
  280 + *
  281 + * @return \GuzzleHttp\Psr7\Response
  282 + *
  283 + * @throws AuthorizationException
  284 + * @throws InvalidConfigException
  285 + * @throws ResourceNotFoundException
  286 + * @throws ServiceInvalidException
  287 + * @throws ValidationException
  288 + */
  289 + public function requestRaw($url, $method = 'POST', array $options = [])
  290 + {
  291 + return Response::buildFromPsrResponse($this->request($url, $method, $options, true));
  292 + }
  293 +
  294 + /**
  295 + * 重写获取客户端,通过 Pimple 容器获取
  296 + *
  297 + * @return \GuzzleHttp\Client
  298 + */
  299 + public function getClient()
  300 + {
  301 + if (!($this->httpClient instanceof ClientInterface)) {
  302 + $this->httpClient = $this->app['http_client'] ?: new Client();
  303 + }
  304 +
  305 + return $this->httpClient;
  306 + }
  307 +
  308 + /**
  309 + * 处理空的数据
  310 + *
  311 + * @param array $data
  312 + *
  313 + * @return array|object
  314 + */
  315 + protected function handleJsonEmptyArray(array $data)
  316 + {
  317 + count($data) == 0 && $data = (object)$data;
  318 + return $data;
  319 + }
  320 +
  321 + /**
  322 + * 注册中间件
  323 + */
  324 + protected function registerMiddleware()
  325 + {
  326 + $this->pushMiddleware($this->appVerificationMiddleware(), 'appVerification');
  327 + $this->pushMiddleware($this->retryMiddleware(), 'retry');
  328 + }
  329 +
  330 + /**
  331 + * 重试中间件
  332 + *
  333 + * @return callable
  334 + */
  335 + protected function retryMiddleware()
  336 + {
  337 + return Middleware::retry(function ($retries,
  338 + Request $request,
  339 + GuzzleResponse $response = null,
  340 + RequestException $exception = null) {
  341 + if ($retries <= $this->app->config->get('http.retries', 1) && $response) {
  342 + return true;
  343 + }
  344 +
  345 + return false;
  346 + }, function () {
  347 + return abs($this->app->config->get('http.retry_delay', 500));
  348 + });
  349 + }
  350 +
  351 + /**
  352 + * appVerificationHandler
  353 + *
  354 + * @return \Closure
  355 + */
  356 + private function appVerificationMiddleware()
  357 + {
  358 + return function (callable $handler) {
  359 + return function (RequestInterface $request, array $options) use ($handler) {
  360 + $request = $this->appVerificationHandler($request);
  361 + return $handler($request, $options);
  362 + };
  363 + };
  364 + }
  365 +
  366 + /**
  367 + * appVerification 中间件具体实现
  368 + *
  369 + * @param RequestInterface $request
  370 + *
  371 + * @return RequestInterface
  372 + *
  373 + * @throws InvalidConfigException
  374 + */
  375 + protected function appVerificationHandler(RequestInterface $request)
  376 + {
  377 + $key = $this->app->config->get('apim.uc.subscription_key', '');
  378 + $nonceStr = $this->app->config->get('apim.uc.nonce_str', md5(rand()));
  379 + $secret = $this->app->config->get('apim.secret', '');
  380 + $apiKey = $this->app->config->get('apim.api_key', '');
  381 + $timeStamp = date('Y-m-d H:i:s');
  382 + $queryArray = \GuzzleHttp\Psr7\parse_query($request->getUri()->getQuery());
  383 +
  384 + if ($key == '' || $secret == '' || $nonceStr == '' || $apiKey == '') {
  385 + throw new InvalidConfigException('Config key "apim.uc.*" and "apim.secret" and "apim.api_key" not be empty ');
  386 + }
  387 +
  388 + if (!isset($queryArray['sign'])) {
  389 + if ($request->getMethod() == 'GET') {
  390 + $sign = ApimSign::getQuerySign($secret, $apiKey, $nonceStr, $timeStamp, $queryArray);
  391 + } else {
  392 + $body = $request->getBody()->getContents();
  393 +
  394 + if (in_array('application/json', $request->getHeader('Content-Type'))) {
  395 + $sign = ApimSign::postBodySign($secret, $apiKey, $nonceStr, $timeStamp, json_decode($body, true), $queryArray);
  396 + }
  397 +
  398 + if (in_array('application/x-www-form-urlencoded', $request->getHeader('Content-Type'))) {
  399 + parse_str($body, $bodyArray);
  400 + $sign = ApimSign::postBodySign($secret, $apiKey, $nonceStr, $timeStamp, $bodyArray, $queryArray);
  401 + }
  402 +
  403 + //TODO 其他请求方式应抛出异常
  404 + }
  405 +
  406 + $request = $request->withUri(
  407 + $request->getUri()->withQuery(
  408 + \GuzzleHttp\Psr7\build_query(array_merge($queryArray, [
  409 + 'api_key' => $apiKey,
  410 + 'nonce_str' => $nonceStr,
  411 + 'timestamp' => $timeStamp,
  412 + 'sign' => $sign
  413 + ])
  414 + )
  415 + )
  416 + );
  417 +
  418 + }
  419 +
  420 + // 设置请求头
  421 + if (!$request->hasHeader('Ocp-Apim-Subscription-Key')) {
  422 + $request = $request->withHeader('Ocp-Apim-Subscription-Key', $key);
  423 + }
  424 +
  425 + return $request;
  426 + }
  427 +}
... ...
src/Kernel/Config.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel;
  4 +
  5 +use PgServiceSdk\Kernel\Support\Collection;
  6 +
  7 +class Config extends Collection
  8 +{
  9 +
  10 +}
... ...
src/Kernel/Contracts/Arrayable.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Contracts;
  4 +
  5 +use ArrayAccess;
  6 +
  7 +/**
  8 + * Interface Arrayable.
  9 + */
  10 +interface Arrayable extends ArrayAccess
  11 +{
  12 + /**
  13 + * Get the instance as an array.
  14 + *
  15 + * @return array
  16 + */
  17 + public function toArray();
  18 +}
... ...
src/Kernel/Contracts/ResponseFormatted.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Contracts;
  4 +
  5 +use Psr\Http\Message\ResponseInterface;
  6 +
  7 +/**
  8 + * Class ResponseFormatted
  9 + * @package PgServiceSdk\Kernel\Contacts
  10 + */
  11 +abstract class ResponseFormatted
  12 +{
  13 + /**
  14 + * @var \Psr\Http\Message\ResponseInterface
  15 + */
  16 + protected $response;
  17 +
  18 + /**
  19 + * ResponseFormatted constructor.
  20 + * @param ResponseInterface $response
  21 + */
  22 + public function __construct(ResponseInterface $response)
  23 + {
  24 + $this->response = $response;
  25 + }
  26 +
  27 + /**
  28 + * 格式化资源
  29 + *
  30 + * @return mixed
  31 + */
  32 + public abstract function format();
  33 +}
0 34 \ No newline at end of file
... ...
src/Kernel/Exceptions/AuthorizationException.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Exceptions;
  4 +
  5 +/**
  6 + * Class AuthorizationException
  7 + * @package PgServiceSdk\Kernel\Exceptions
  8 + */
  9 +class AuthorizationException extends \Exception
  10 +{
  11 +
  12 +}
0 13 \ No newline at end of file
... ...
src/Kernel/Exceptions/BadRequestException.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: ChuXiang
  5 + * Date: 2019/8/15
  6 + * Time: 10:33
  7 + */
  8 +
  9 +namespace PgServiceSdk\Kernel\Exceptions;
  10 +
  11 +
  12 +class BadRequestException extends \Exception
  13 +{
  14 +
  15 +}
0 16 \ No newline at end of file
... ...
src/Kernel/Exceptions/Exception.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Exceptions;
  4 +
  5 +use Exception as BaseException;
  6 +
  7 +/**
  8 + * Class Exception.
  9 + */
  10 +class Exception extends BaseException
  11 +{
  12 +}
... ...
src/Kernel/Exceptions/InvalidArgumentException.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Exceptions;
  4 +
  5 +/**
  6 + * Class InvalidArgumentException.
  7 + */
  8 +class InvalidArgumentException extends Exception
  9 +{
  10 +}
... ...
src/Kernel/Exceptions/InvalidConfigException.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Exceptions;
  4 +
  5 +/**
  6 + * Class InvalidConfigException.
  7 + */
  8 +class InvalidConfigException extends Exception
  9 +{
  10 +}
... ...
src/Kernel/Exceptions/PgServiceSdkException.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Exceptions;
  4 +
  5 +/**
  6 + * Class PgServiceSdkException
  7 + * @package PgServiceSdk\Kernel\Exceptions
  8 + */
  9 +class PgServiceSdkException extends \Exception
  10 +{
  11 +
  12 +}
... ...
src/Kernel/Exceptions/ResourceNotFoundException.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Exceptions;
  4 +
  5 +/**
  6 + * Class ResourceNotFoundException
  7 + * @package PgServiceSdk\Kernel\Exceptions
  8 + */
  9 +class ResourceNotFoundException extends \Exception
  10 +{
  11 +
  12 +}
0 13 \ No newline at end of file
... ...
src/Kernel/Exceptions/ServiceInvalidException.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Exceptions;
  4 +
  5 +/**
  6 + * Class ServiceInvalidException
  7 + * @package PgServiceSdk\Kernel\Exceptions
  8 + */
  9 +class ServiceInvalidException extends \Exception
  10 +{
  11 +
  12 +}
0 13 \ No newline at end of file
... ...
src/Kernel/Exceptions/ValidationException.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Exceptions;
  4 +
  5 +/**
  6 + * Class ValidationException
  7 + * @package PgServiceSdk\Kernel\Exceptions
  8 + */
  9 +class ValidationException extends \Exception
  10 +{
  11 +
  12 +}
0 13 \ No newline at end of file
... ...
src/Kernel/Http/Response.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Http;
  4 +
  5 +use Psr\Http\Message\ResponseInterface;
  6 +use PgServiceSdk\Kernel\Support\Collection;
  7 +use GuzzleHttp\Psr7\Response as GuzzleResponse;
  8 +
  9 +/**
  10 + * Class Response
  11 + * @package PgServiceSdk\Kernel\Http
  12 + */
  13 +class Response extends GuzzleResponse
  14 +{
  15 + /**
  16 + * 将 ResponseInterface 类型实例 new 自身,这样就可使用父类(\GuzzleHttp\Psr7\Response)的方法
  17 + *
  18 + * @param ResponseInterface $response
  19 + *
  20 + * @return \PgServiceSdk\Kernel\Http\Response
  21 + */
  22 + public static function buildFromPsrResponse(ResponseInterface $response)
  23 + {
  24 + return new static(
  25 + $response->getStatusCode(),
  26 + $response->getHeaders(),
  27 + $response->getBody(),
  28 + $response->getReasonPhrase()
  29 + );
  30 + }
  31 +
  32 + /**
  33 + * 将响应正文转化为JSON
  34 + *
  35 + * @return string
  36 + */
  37 + public function toJson()
  38 + {
  39 + return json_encode($this->toArray());
  40 + }
  41 +
  42 + /**
  43 + * 将响应正文转化为数组
  44 + *
  45 + * @return array
  46 + */
  47 + public function toArray()
  48 + {
  49 + $array = json_decode($this->getBodyContents(), true);
  50 +
  51 + if (JSON_ERROR_NONE === json_last_error()) {
  52 + return (array)$array;
  53 + }
  54 +
  55 + return [];
  56 + }
  57 +
  58 + /**
  59 + * 将响应正文转化为集合
  60 + *
  61 + * @return Collection
  62 + */
  63 + public function toCollection()
  64 + {
  65 + return new Collection($this->toArray());
  66 + }
  67 +
  68 + /**
  69 + * 将响应正文转化为对象
  70 + *
  71 + * @return object
  72 + */
  73 + public function toObject()
  74 + {
  75 + return (object)json_decode($this->getBodyContents());
  76 + }
  77 +
  78 + /**
  79 + * 获取响应的正文内容
  80 + *
  81 + * @return string
  82 + */
  83 + public function getBodyContents()
  84 + {
  85 + $this->getBody()->rewind();
  86 + $contents = $this->getBody()->getContents();
  87 + $this->getBody()->rewind();
  88 +
  89 + return $contents;
  90 + }
  91 +
  92 + /**
  93 + * 直接输出响应正文
  94 + *
  95 + * @return string
  96 + */
  97 + public function __toString()
  98 + {
  99 + return $this->getBodyContents();
  100 + }
  101 +}
... ...
src/Kernel/Library/Apim/ApimSign.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: ChuXiang
  5 + * Date: 2019/8/15
  6 + * Time: 14:29
  7 + */
  8 +
  9 +namespace PgServiceSdk\Kernel\Library\Apim;
  10 +
  11 +
  12 +class ApimSign
  13 +{
  14 + /**
  15 + * GET 请求生产签名
  16 + *
  17 + * @param string $secret
  18 + * @param string $apiKey
  19 + * @param string $nonceStr
  20 + * @param string $timeStamp
  21 + * @param array $query
  22 + *
  23 + * @return string
  24 + */
  25 + public static function getQuerySign($secret, $apiKey, $nonceStr, $timeStamp, array $query = [])
  26 + {
  27 + return self::getSign($query, $secret, $apiKey, $nonceStr, $timeStamp);
  28 + }
  29 +
  30 + /**
  31 + * 表单请求生产签名
  32 + *
  33 + * @param string $secret
  34 + * @param string $apiKey
  35 + * @param string $nonceStr
  36 + * @param string $timeStamp
  37 + * @param array $from
  38 + * @param array $query
  39 + *
  40 + * @return string
  41 + */
  42 + public static function postFromSign($secret, $apiKey, $nonceStr, $timeStamp, array $from = [], array $query = [])
  43 + {
  44 + return self::getSign(array_merge($from, $query), $secret, $apiKey, $nonceStr, $timeStamp);
  45 + }
  46 +
  47 +
  48 + /**
  49 + * JSON POST 请求生产签名
  50 + *
  51 + * @param string $secret
  52 + * @param string $apiKey
  53 + * @param string $nonceStr
  54 + * @param string $timeStamp
  55 + * @param array $data
  56 + * @param array $query
  57 + *
  58 + * @return string
  59 + */
  60 + public static function postBodySign($secret, $apiKey, $nonceStr, $timeStamp, array $data = [], array $query = [])
  61 + {
  62 + $jsonRequestData = json_encode(empty($data) ? (object)$data : $data, 320);
  63 + $query['body'] = $jsonRequestData;
  64 + return self::getSign($query, $secret, $apiKey, $nonceStr, $timeStamp);
  65 + }
  66 +
  67 + /**
  68 + * 生产签名
  69 + *
  70 + * @param array $params
  71 + * @param string $secret
  72 + * @param string $apiKey
  73 + * @param string $nonceStr
  74 + * @param string $timeStamp
  75 + *
  76 + * @return string
  77 + */
  78 + public static function getSign(array $params, $secret, $apiKey, $nonceStr, $timeStamp)
  79 + {
  80 + $defaultParams = [
  81 + 'api_key' => $apiKey,
  82 + 'nonce_str' => $nonceStr,
  83 + 'timestamp' => $timeStamp,
  84 + ];
  85 +
  86 + $signParams = array_merge($params, $defaultParams);
  87 + // 按照字典排序
  88 + ksort($signParams, SORT_STRING);
  89 + // 以 & 链接并且前后拼接 secret
  90 + $tmp = $secret . urldecode(http_build_query($signParams)) . $secret;
  91 + // SHA 256 加密后,全部转大写
  92 + return strtoupper(hash('sha256', $tmp));
  93 + }
  94 +}
0 95 \ No newline at end of file
... ...
src/Kernel/Providers/ConfigProvider.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Providers;
  4 +
  5 +use Pimple\Container;
  6 +use PgServiceSdk\Kernel\Config;
  7 +use Pimple\ServiceProviderInterface;
  8 +
  9 +/**
  10 + * Class ConfigProvider
  11 + * @package PgServiceSdk\Kernel\Providers
  12 + */
  13 +class ConfigProvider implements ServiceProviderInterface
  14 +{
  15 +
  16 + /**
  17 + * Registers services on the given container.
  18 + *
  19 + * This method should only be used to configure services and parameters.
  20 + * It should not get services.
  21 + *
  22 + * @param Container $pimple A container instance
  23 + */
  24 + public function register(Container $pimple)
  25 + {
  26 + $pimple['config'] = function ($app) {
  27 + return new Config($app->getConfig());
  28 + };
  29 + }
  30 +}
0 31 \ No newline at end of file
... ...
src/Kernel/Providers/HttpClientProvider.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Providers;
  4 +
  5 +use Pimple\Container;
  6 +use GuzzleHttp\Client;
  7 +use Pimple\ServiceProviderInterface;
  8 +
  9 +class HttpClientProvider implements ServiceProviderInterface
  10 +{
  11 +
  12 + /**
  13 + * Registers services on the given container.
  14 + *
  15 + * This method should only be used to configure services and parameters.
  16 + * It should not get services.
  17 + *
  18 + * @param Container $pimple A container instance
  19 + */
  20 + public function register(Container $pimple)
  21 + {
  22 + $pimple['http_client'] = function ($app) {
  23 + return new Client($app->config->get('http', []));
  24 + };
  25 + }
  26 +}
0 27 \ No newline at end of file
... ...
src/Kernel/Providers/RequestProvider.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Providers;
  4 +
  5 +use Pimple\Container;
  6 +use Pimple\ServiceProviderInterface;
  7 +use Symfony\Component\HttpFoundation\Request;
  8 +
  9 +class RequestProvider implements ServiceProviderInterface
  10 +{
  11 +
  12 + /**
  13 + * Registers services on the given container.
  14 + *
  15 + * This method should only be used to configure services and parameters.
  16 + * It should not get services.
  17 + *
  18 + * @param Container $pimple A container instance
  19 + */
  20 + public function register(Container $pimple)
  21 + {
  22 + $pimple['request'] = function () {
  23 + return Request::createFromGlobals();
  24 + };
  25 + }
  26 +}
0 27 \ No newline at end of file
... ...
src/Kernel/ServiceContainer.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel;
  4 +
  5 +use Pimple\Container;
  6 +use PgServiceSdk\Kernel\Providers\ConfigProvider;
  7 +use PgServiceSdk\Kernel\Providers\RequestProvider;
  8 +use PgServiceSdk\Kernel\Providers\HttpClientProvider;
  9 +
  10 +/**
  11 + * Class ServiceContainer
  12 + * @package PgServiceSdk\Kernel
  13 + *
  14 + * @property \PgServiceSdk\Kernel\Config $config
  15 + * @property \GuzzleHttp\Client $http_client
  16 + * @property \Symfony\Component\HttpFoundation\Request $request
  17 + */
  18 +class ServiceContainer extends Container
  19 +{
  20 + /**
  21 + * 服务提供者容器
  22 + *
  23 + * @var array
  24 + */
  25 + protected $providers = [];
  26 +
  27 + /**
  28 + * 用户自定义配置
  29 + *
  30 + * @var array
  31 + */
  32 + protected $userConfig = [];
  33 +
  34 + /**
  35 + * 默认的配置,子类可覆盖
  36 + *
  37 + * @var array
  38 + */
  39 + protected $defaultConfig = [];
  40 +
  41 + /**
  42 + * @var null|string
  43 + */
  44 + protected $requestId = null;
  45 +
  46 + /**
  47 + * ServiceContainer constructor.
  48 + * @param array $config
  49 + * @param array $values
  50 + * @param string $id
  51 + */
  52 + public function __construct(array $config = [], array $values = array(), $id = null)
  53 + {
  54 + $this->registerProviders($this->getProviders());
  55 +
  56 + parent::__construct($values);
  57 +
  58 + $this->userConfig = $config;
  59 + $this->requestId = $id;
  60 + }
  61 +
  62 + /**
  63 + * 获取请求 requestId
  64 + *
  65 + * @return string
  66 + */
  67 + public function getRequestId()
  68 + {
  69 + return $this->requestId = ($this->requestId ?: md5(json_encode($this->userConfig)));
  70 + }
  71 +
  72 + /**
  73 + * 获取配置
  74 + *
  75 + * @return array
  76 + */
  77 + public function getConfig()
  78 + {
  79 + $base = [
  80 + // http://docs.guzzlephp.org/en/stable/request-options.html
  81 + 'http' => [
  82 + 'timeout' => 10.0,
  83 + 'headers' => ['Accept' => 'application/json']
  84 + ],
  85 + ];
  86 +
  87 + return array_replace_recursive($base, $this->defaultConfig, $this->userConfig['default']);
  88 + }
  89 +
  90 + /**
  91 + * 获取服务提供者
  92 + *
  93 + * @return array
  94 + */
  95 + public function getProviders()
  96 + {
  97 + return array_merge([
  98 + ConfigProvider::class,
  99 + HttpClientProvider::class,
  100 + RequestProvider::class
  101 + ], $this->providers);
  102 +
  103 + }
  104 +
  105 + /**
  106 + * 注册服务提供者
  107 + *
  108 + * @param array $providers
  109 + */
  110 + public function registerProviders(array $providers)
  111 + {
  112 + foreach ($providers as $provider) {
  113 + parent::register(new $provider());
  114 + }
  115 + }
  116 +
  117 + /**
  118 + * @param string $name
  119 + *
  120 + * @return mixed
  121 + */
  122 + public function __get($name)
  123 + {
  124 + return $this->offsetGet($name);
  125 + }
  126 +
  127 + /**
  128 + * @param string $name
  129 + * @param mixed $value
  130 + */
  131 + public function __set($name, $value)
  132 + {
  133 + $this->offsetSet($name, $value);
  134 + }
  135 +}
0 136 \ No newline at end of file
... ...
src/Kernel/Support/Arr.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Support;
  4 +
  5 +/**
  6 + * Array helper from Illuminate\Support\Arr.
  7 + */
  8 +class Arr
  9 +{
  10 + /**
  11 + * Add an element to an array using "dot" notation if it doesn't exist.
  12 + *
  13 + * @param array $array
  14 + * @param string $key
  15 + * @param mixed $value
  16 + *
  17 + * @return array
  18 + */
  19 + public static function add(array $array, $key, $value)
  20 + {
  21 + if (is_null(static::get($array, $key))) {
  22 + static::set($array, $key, $value);
  23 + }
  24 +
  25 + return $array;
  26 + }
  27 +
  28 + /**
  29 + * Cross join the given arrays, returning all possible permutations.
  30 + *
  31 + * @param array ...$arrays
  32 + *
  33 + * @return array
  34 + */
  35 + public static function crossJoin(...$arrays)
  36 + {
  37 + $results = [[]];
  38 +
  39 + foreach ($arrays as $index => $array) {
  40 + $append = [];
  41 +
  42 + foreach ($results as $product) {
  43 + foreach ($array as $item) {
  44 + $product[$index] = $item;
  45 +
  46 + $append[] = $product;
  47 + }
  48 + }
  49 +
  50 + $results = $append;
  51 + }
  52 +
  53 + return $results;
  54 + }
  55 +
  56 + /**
  57 + * Divide an array into two arrays. One with keys and the other with values.
  58 + *
  59 + * @param array $array
  60 + *
  61 + * @return array
  62 + */
  63 + public static function divide(array $array)
  64 + {
  65 + return [array_keys($array), array_values($array)];
  66 + }
  67 +
  68 + /**
  69 + * Flatten a multi-dimensional associative array with dots.
  70 + *
  71 + * @param array $array
  72 + * @param string $prepend
  73 + *
  74 + * @return array
  75 + */
  76 + public static function dot(array $array, $prepend = '')
  77 + {
  78 + $results = [];
  79 +
  80 + foreach ($array as $key => $value) {
  81 + if (is_array($value) && !empty($value)) {
  82 + $results = array_merge($results, static::dot($value, $prepend.$key.'.'));
  83 + } else {
  84 + $results[$prepend.$key] = $value;
  85 + }
  86 + }
  87 +
  88 + return $results;
  89 + }
  90 +
  91 + /**
  92 + * Get all of the given array except for a specified array of items.
  93 + *
  94 + * @param array $array
  95 + * @param array|string $keys
  96 + *
  97 + * @return array
  98 + */
  99 + public static function except(array $array, $keys)
  100 + {
  101 + static::forget($array, $keys);
  102 +
  103 + return $array;
  104 + }
  105 +
  106 + /**
  107 + * Determine if the given key exists in the provided array.
  108 + *
  109 + * @param \ArrayAccess|array $array
  110 + * @param string|int $key
  111 + *
  112 + * @return bool
  113 + */
  114 + public static function exists(array $array, $key)
  115 + {
  116 + return array_key_exists($key, $array);
  117 + }
  118 +
  119 + /**
  120 + * Return the first element in an array passing a given truth test.
  121 + *
  122 + * @param array $array
  123 + * @param callable|null $callback
  124 + * @param mixed $default
  125 + *
  126 + * @return mixed
  127 + */
  128 + public static function first(array $array, callable $callback = null, $default = null)
  129 + {
  130 + if (is_null($callback)) {
  131 + if (empty($array)) {
  132 + return $default;
  133 + }
  134 +
  135 + foreach ($array as $item) {
  136 + return $item;
  137 + }
  138 + }
  139 +
  140 + foreach ($array as $key => $value) {
  141 + if (call_user_func($callback, $value, $key)) {
  142 + return $value;
  143 + }
  144 + }
  145 +
  146 + return $default;
  147 + }
  148 +
  149 + /**
  150 + * Return the last element in an array passing a given truth test.
  151 + *
  152 + * @param array $array
  153 + * @param callable|null $callback
  154 + * @param mixed $default
  155 + *
  156 + * @return mixed
  157 + */
  158 + public static function last(array $array, callable $callback = null, $default = null)
  159 + {
  160 + if (is_null($callback)) {
  161 + return empty($array) ? $default : end($array);
  162 + }
  163 +
  164 + return static::first(array_reverse($array, true), $callback, $default);
  165 + }
  166 +
  167 + /**
  168 + * Flatten a multi-dimensional array into a single level.
  169 + *
  170 + * @param array $array
  171 + * @param int $depth
  172 + *
  173 + * @return array
  174 + */
  175 + public static function flatten(array $array, $depth = INF)
  176 + {
  177 + return array_reduce($array, function ($result, $item) use ($depth) {
  178 + $item = $item instanceof Collection ? $item->all() : $item;
  179 +
  180 + if (!is_array($item)) {
  181 + return array_merge($result, [$item]);
  182 + } elseif (1 === $depth) {
  183 + return array_merge($result, array_values($item));
  184 + }
  185 +
  186 + return array_merge($result, static::flatten($item, $depth - 1));
  187 + }, []);
  188 + }
  189 +
  190 + /**
  191 + * Remove one or many array items from a given array using "dot" notation.
  192 + *
  193 + * @param array $array
  194 + * @param array|string $keys
  195 + */
  196 + public static function forget(array &$array, $keys)
  197 + {
  198 + $original = &$array;
  199 +
  200 + $keys = (array) $keys;
  201 +
  202 + if (0 === count($keys)) {
  203 + return;
  204 + }
  205 +
  206 + foreach ($keys as $key) {
  207 + // if the exact key exists in the top-level, remove it
  208 + if (static::exists($array, $key)) {
  209 + unset($array[$key]);
  210 +
  211 + continue;
  212 + }
  213 +
  214 + $parts = explode('.', $key);
  215 +
  216 + // clean up before each pass
  217 + $array = &$original;
  218 +
  219 + while (count($parts) > 1) {
  220 + $part = array_shift($parts);
  221 +
  222 + if (isset($array[$part]) && is_array($array[$part])) {
  223 + $array = &$array[$part];
  224 + } else {
  225 + continue 2;
  226 + }
  227 + }
  228 +
  229 + unset($array[array_shift($parts)]);
  230 + }
  231 + }
  232 +
  233 + /**
  234 + * Get an item from an array using "dot" notation.
  235 + *
  236 + * @param \ArrayAccess|array $array
  237 + * @param string $key
  238 + * @param mixed $default
  239 + *
  240 + * @return mixed
  241 + */
  242 + public static function get(array $array, $key, $default = null)
  243 + {
  244 + if (is_null($key)) {
  245 + return $array;
  246 + }
  247 +
  248 + if (static::exists($array, $key)) {
  249 + return $array[$key];
  250 + }
  251 +
  252 + foreach (explode('.', $key) as $segment) {
  253 + if (static::exists($array, $segment)) {
  254 + $array = $array[$segment];
  255 + } else {
  256 + return $default;
  257 + }
  258 + }
  259 +
  260 + return $array;
  261 + }
  262 +
  263 + /**
  264 + * Check if an item or items exist in an array using "dot" notation.
  265 + *
  266 + * @param \ArrayAccess|array $array
  267 + * @param string|array $keys
  268 + *
  269 + * @return bool
  270 + */
  271 + public static function has(array $array, $keys)
  272 + {
  273 + if (is_null($keys)) {
  274 + return false;
  275 + }
  276 +
  277 + $keys = (array) $keys;
  278 +
  279 + if (empty($array)) {
  280 + return false;
  281 + }
  282 +
  283 + if ($keys === []) {
  284 + return false;
  285 + }
  286 +
  287 + foreach ($keys as $key) {
  288 + $subKeyArray = $array;
  289 +
  290 + if (static::exists($array, $key)) {
  291 + continue;
  292 + }
  293 +
  294 + foreach (explode('.', $key) as $segment) {
  295 + if (static::exists($subKeyArray, $segment)) {
  296 + $subKeyArray = $subKeyArray[$segment];
  297 + } else {
  298 + return false;
  299 + }
  300 + }
  301 + }
  302 +
  303 + return true;
  304 + }
  305 +
  306 + /**
  307 + * Determines if an array is associative.
  308 + *
  309 + * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
  310 + *
  311 + * @param array $array
  312 + *
  313 + * @return bool
  314 + */
  315 + public static function isAssoc(array $array)
  316 + {
  317 + $keys = array_keys($array);
  318 +
  319 + return array_keys($keys) !== $keys;
  320 + }
  321 +
  322 + /**
  323 + * Get a subset of the items from the given array.
  324 + *
  325 + * @param array $array
  326 + * @param array|string $keys
  327 + *
  328 + * @return array
  329 + */
  330 + public static function only(array $array, $keys)
  331 + {
  332 + return array_intersect_key($array, array_flip((array) $keys));
  333 + }
  334 +
  335 + /**
  336 + * Push an item onto the beginning of an array.
  337 + *
  338 + * @param array $array
  339 + * @param mixed $value
  340 + * @param mixed $key
  341 + *
  342 + * @return array
  343 + */
  344 + public static function prepend(array $array, $value, $key = null)
  345 + {
  346 + if (is_null($key)) {
  347 + array_unshift($array, $value);
  348 + } else {
  349 + $array = [$key => $value] + $array;
  350 + }
  351 +
  352 + return $array;
  353 + }
  354 +
  355 + /**
  356 + * Get a value from the array, and remove it.
  357 + *
  358 + * @param array $array
  359 + * @param string $key
  360 + * @param mixed $default
  361 + *
  362 + * @return mixed
  363 + */
  364 + public static function pull(array &$array, $key, $default = null)
  365 + {
  366 + $value = static::get($array, $key, $default);
  367 +
  368 + static::forget($array, $key);
  369 +
  370 + return $value;
  371 + }
  372 +
  373 + /**
  374 + * Get a 1 value from an array.
  375 + *
  376 + * @param array $array
  377 + * @param int|null $amount
  378 + *
  379 + * @return mixed
  380 + *
  381 + * @throws \InvalidArgumentException
  382 + */
  383 + public static function random(array $array, $amount = null)
  384 + {
  385 + if (is_null($amount)) {
  386 + return $array[array_rand($array)];
  387 + }
  388 +
  389 + $keys = array_rand($array, $amount);
  390 +
  391 + $results = [];
  392 +
  393 + foreach ((array) $keys as $key) {
  394 + $results[] = $array[$key];
  395 + }
  396 +
  397 + return $results;
  398 + }
  399 +
  400 + /**
  401 + * Set an array item to a given value using "dot" notation.
  402 + *
  403 + * If no key is given to the method, the entire array will be replaced.
  404 + *
  405 + * @param array $array
  406 + * @param string $key
  407 + * @param mixed $value
  408 + *
  409 + * @return array
  410 + */
  411 + public static function set(array &$array, $key, $value)
  412 + {
  413 + $keys = explode('.', $key);
  414 +
  415 + while (count($keys) > 1) {
  416 + $key = array_shift($keys);
  417 +
  418 + // If the key doesn't exist at this depth, we will just create an empty array
  419 + // to hold the next value, allowing us to create the arrays to hold final
  420 + // values at the correct depth. Then we'll keep digging into the array.
  421 + if (!isset($array[$key]) || !is_array($array[$key])) {
  422 + $array[$key] = [];
  423 + }
  424 +
  425 + $array = &$array[$key];
  426 + }
  427 +
  428 + $array[array_shift($keys)] = $value;
  429 +
  430 + return $array;
  431 + }
  432 +
  433 + /**
  434 + * Filter the array using the given callback.
  435 + *
  436 + * @param array $array
  437 + * @param callable $callback
  438 + *
  439 + * @return array
  440 + */
  441 + public static function where(array $array, callable $callback)
  442 + {
  443 + return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
  444 + }
  445 +
  446 + /**
  447 + * If the given value is not an array, wrap it in one.
  448 + *
  449 + * @param mixed $value
  450 + *
  451 + * @return array
  452 + */
  453 + public static function wrap($value)
  454 + {
  455 + return !is_array($value) ? [$value] : $value;
  456 + }
  457 +}
... ...
src/Kernel/Support/Collection.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Kernel\Support;
  4 +
  5 +use Countable;
  6 +use ArrayAccess;
  7 +use Serializable;
  8 +use ArrayIterator;
  9 +use JsonSerializable;
  10 +use IteratorAggregate;
  11 +use PgServiceSdk\Kernel\Contracts\Arrayable;
  12 +
  13 +/**
  14 + * Class Collection.
  15 + */
  16 +class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable, Serializable, Arrayable
  17 +{
  18 + /**
  19 + * The collection data.
  20 + *
  21 + * @var array
  22 + */
  23 + protected $items = [];
  24 +
  25 + /**
  26 + * set data.
  27 + *
  28 + * @param mixed $items
  29 + */
  30 + public function __construct(array $items = [])
  31 + {
  32 + foreach ($items as $key => $value) {
  33 + $this->set($key, $value);
  34 + }
  35 + }
  36 +
  37 + /**
  38 + * Return all items.
  39 + *
  40 + * @return array
  41 + */
  42 + public function all()
  43 + {
  44 + return $this->items;
  45 + }
  46 +
  47 + /**
  48 + * Return specific items.
  49 + *
  50 + * @param array $keys
  51 + *
  52 + * @return \PgServiceSdk\Kernel\Support\Collection
  53 + */
  54 + public function only(array $keys)
  55 + {
  56 + $return = [];
  57 +
  58 + foreach ($keys as $key) {
  59 + $value = $this->get($key);
  60 +
  61 + if (!is_null($value)) {
  62 + $return[$key] = $value;
  63 + }
  64 + }
  65 +
  66 + return new static($return);
  67 + }
  68 +
  69 + /**
  70 + * Get all items except for those with the specified keys.
  71 + *
  72 + * @param mixed $keys
  73 + *
  74 + * @return static
  75 + */
  76 + public function except($keys)
  77 + {
  78 + $keys = is_array($keys) ? $keys : func_get_args();
  79 +
  80 + return new static(Arr::except($this->items, $keys));
  81 + }
  82 +
  83 + /**
  84 + * Merge data.
  85 + *
  86 + * @param Collection|array $items
  87 + *
  88 + * @return \PgServiceSdk\Kernel\Support\Collection
  89 + */
  90 + public function merge($items)
  91 + {
  92 + foreach ($items as $key => $value) {
  93 + $this->set($key, $value);
  94 + }
  95 +
  96 + return new static($this->all());
  97 + }
  98 +
  99 + /**
  100 + * To determine Whether the specified element exists.
  101 + *
  102 + * @param string $key
  103 + *
  104 + * @return bool
  105 + */
  106 + public function has($key)
  107 + {
  108 + return !is_null(Arr::get($this->items, $key));
  109 + }
  110 +
  111 + /**
  112 + * Retrieve the first item.
  113 + *
  114 + * @return mixed
  115 + */
  116 + public function first()
  117 + {
  118 + return reset($this->items);
  119 + }
  120 +
  121 + /**
  122 + * Retrieve the last item.
  123 + *
  124 + * @return bool
  125 + */
  126 + public function last()
  127 + {
  128 + $end = end($this->items);
  129 +
  130 + reset($this->items);
  131 +
  132 + return $end;
  133 + }
  134 +
  135 + /**
  136 + * add the item value.
  137 + *
  138 + * @param string $key
  139 + * @param mixed $value
  140 + */
  141 + public function add($key, $value)
  142 + {
  143 + Arr::set($this->items, $key, $value);
  144 + }
  145 +
  146 + /**
  147 + * Set the item value.
  148 + *
  149 + * @param string $key
  150 + * @param mixed $value
  151 + */
  152 + public function set($key, $value)
  153 + {
  154 + Arr::set($this->items, $key, $value);
  155 + }
  156 +
  157 + /**
  158 + * Retrieve item from Collection.
  159 + *
  160 + * @param string $key
  161 + * @param mixed $default
  162 + *
  163 + * @return mixed
  164 + */
  165 + public function get($key, $default = null)
  166 + {
  167 + return Arr::get($this->items, $key, $default);
  168 + }
  169 +
  170 + /**
  171 + * Remove item form Collection.
  172 + *
  173 + * @param string $key
  174 + */
  175 + public function forget($key)
  176 + {
  177 + Arr::forget($this->items, $key);
  178 + }
  179 +
  180 + /**
  181 + * Build to array.
  182 + *
  183 + * @return array
  184 + */
  185 + public function toArray()
  186 + {
  187 + return $this->all();
  188 + }
  189 +
  190 + /**
  191 + * Build to json.
  192 + *
  193 + * @param int $option
  194 + *
  195 + * @return string
  196 + */
  197 + public function toJson($option = JSON_UNESCAPED_UNICODE)
  198 + {
  199 + return json_encode($this->all(), $option);
  200 + }
  201 +
  202 + /**
  203 + * To string.
  204 + *
  205 + * @return string
  206 + */
  207 + public function __toString()
  208 + {
  209 + return $this->toJson();
  210 + }
  211 +
  212 + /**
  213 + * (PHP 5 &gt;= 5.4.0)<br/>
  214 + * Specify data which should be serialized to JSON.
  215 + *
  216 + * @see http://php.net/manual/en/jsonserializable.jsonserialize.php
  217 + *
  218 + * @return mixed data which can be serialized by <b>json_encode</b>,
  219 + * which is a value of any type other than a resource
  220 + */
  221 + public function jsonSerialize()
  222 + {
  223 + return $this->items;
  224 + }
  225 +
  226 + /**
  227 + * (PHP 5 &gt;= 5.1.0)<br/>
  228 + * String representation of object.
  229 + *
  230 + * @see http://php.net/manual/en/serializable.serialize.php
  231 + *
  232 + * @return string the string representation of the object or null
  233 + */
  234 + public function serialize()
  235 + {
  236 + return serialize($this->items);
  237 + }
  238 +
  239 + /**
  240 + * (PHP 5 &gt;= 5.0.0)<br/>
  241 + * Retrieve an external iterator.
  242 + *
  243 + * @see http://php.net/manual/en/iteratoraggregate.getiterator.php
  244 + *
  245 + * @return \ArrayIterator An instance of an object implementing <b>Iterator</b> or
  246 + * <b>Traversable</b>
  247 + */
  248 + public function getIterator()
  249 + {
  250 + return new ArrayIterator($this->items);
  251 + }
  252 +
  253 + /**
  254 + * (PHP 5 &gt;= 5.1.0)<br/>
  255 + * Count elements of an object.
  256 + *
  257 + * @see http://php.net/manual/en/countable.count.php
  258 + *
  259 + * @return int The custom count as an integer.
  260 + * </p>
  261 + * <p>
  262 + * The return value is cast to an integer
  263 + */
  264 + public function count()
  265 + {
  266 + return count($this->items);
  267 + }
  268 +
  269 + /**
  270 + * (PHP 5 &gt;= 5.1.0)<br/>
  271 + * Constructs the object.
  272 + *
  273 + * @see http://php.net/manual/en/serializable.unserialize.php
  274 + *
  275 + * @param string $serialized <p>
  276 + * The string representation of the object.
  277 + * </p>
  278 + *
  279 + * @return mixed|void
  280 + */
  281 + public function unserialize($serialized)
  282 + {
  283 + return $this->items = unserialize($serialized);
  284 + }
  285 +
  286 + /**
  287 + * Get a data by key.
  288 + *
  289 + * @param string $key
  290 + *
  291 + * @return mixed
  292 + */
  293 + public function __get($key)
  294 + {
  295 + return $this->get($key);
  296 + }
  297 +
  298 + /**
  299 + * Assigns a value to the specified data.
  300 + *
  301 + * @param string $key
  302 + * @param mixed $value
  303 + */
  304 + public function __set($key, $value)
  305 + {
  306 + $this->set($key, $value);
  307 + }
  308 +
  309 + /**
  310 + * Whether or not an data exists by key.
  311 + *
  312 + * @param string $key
  313 + *
  314 + * @return bool
  315 + */
  316 + public function __isset($key)
  317 + {
  318 + return $this->has($key);
  319 + }
  320 +
  321 + /**
  322 + * Unset an data by key.
  323 + *
  324 + * @param string $key
  325 + */
  326 + public function __unset($key)
  327 + {
  328 + $this->forget($key);
  329 + }
  330 +
  331 + /**
  332 + * var_export.
  333 + *
  334 + * @return array
  335 + */
  336 + public function __set_state()
  337 + {
  338 + return $this->all();
  339 + }
  340 +
  341 + /**
  342 + * (PHP 5 &gt;= 5.0.0)<br/>
  343 + * Whether a offset exists.
  344 + *
  345 + * @see http://php.net/manual/en/arrayaccess.offsetexists.php
  346 + *
  347 + * @param mixed $offset <p>
  348 + * An offset to check for.
  349 + * </p>
  350 + *
  351 + * @return bool true on success or false on failure.
  352 + * The return value will be casted to boolean if non-boolean was returned
  353 + */
  354 + public function offsetExists($offset)
  355 + {
  356 + return $this->has($offset);
  357 + }
  358 +
  359 + /**
  360 + * (PHP 5 &gt;= 5.0.0)<br/>
  361 + * Offset to unset.
  362 + *
  363 + * @see http://php.net/manual/en/arrayaccess.offsetunset.php
  364 + *
  365 + * @param mixed $offset <p>
  366 + * The offset to unset.
  367 + * </p>
  368 + */
  369 + public function offsetUnset($offset)
  370 + {
  371 + if ($this->offsetExists($offset)) {
  372 + $this->forget($offset);
  373 + }
  374 + }
  375 +
  376 + /**
  377 + * (PHP 5 &gt;= 5.0.0)<br/>
  378 + * Offset to retrieve.
  379 + *
  380 + * @see http://php.net/manual/en/arrayaccess.offsetget.php
  381 + *
  382 + * @param mixed $offset <p>
  383 + * The offset to retrieve.
  384 + * </p>
  385 + *
  386 + * @return mixed Can return all value types
  387 + */
  388 + public function offsetGet($offset)
  389 + {
  390 + return $this->offsetExists($offset) ? $this->get($offset) : null;
  391 + }
  392 +
  393 + /**
  394 + * (PHP 5 &gt;= 5.0.0)<br/>
  395 + * Offset to set.
  396 + *
  397 + * @see http://php.net/manual/en/arrayaccess.offsetset.php
  398 + *
  399 + * @param mixed $offset <p>
  400 + * The offset to assign the value to.
  401 + * </p>
  402 + * @param mixed $value <p>
  403 + * The value to set.
  404 + * </p>
  405 + */
  406 + public function offsetSet($offset, $value)
  407 + {
  408 + $this->set($offset, $value);
  409 + }
  410 +}
... ...
src/Kernel/Traits/HasHttpRequest.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: ChuXiang
  5 + * Date: 2019/8/12
  6 + * Time: 15:09
  7 + */
  8 +
  9 +namespace PgServiceSdk\Kernel\Traits;
  10 +
  11 +
  12 +use GuzzleHttp\Client;
  13 +use GuzzleHttp\HandlerStack;
  14 +use GuzzleHttp\ClientInterface;
  15 +
  16 +trait HasHttpRequest
  17 +{
  18 + /**
  19 + * 增加格式化响应的功能
  20 + */
  21 + use ResponseCastable;
  22 +
  23 + /**
  24 + * 请求的 HTTP 客户端
  25 + *
  26 + * @var \GuzzleHttp\Client
  27 + */
  28 + protected $httpClient;
  29 +
  30 + /**
  31 + * 设置的中间件集合
  32 + *
  33 + * @var array
  34 + */
  35 + protected $middlewares = [];
  36 +
  37 + /**
  38 + * @var \GuzzleHttp\HandlerStack
  39 + */
  40 + protected $handlerStack;
  41 +
  42 + /**
  43 + * 默认的 option 设置
  44 + *
  45 + * @var array
  46 + */
  47 + protected static $default = [
  48 + 'curl' => [
  49 + CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4
  50 + ]
  51 + ];
  52 +
  53 + /**
  54 + * 获取默认的 option 选项
  55 + *
  56 + * @return array
  57 + */
  58 + public static function getDefaultOption()
  59 + {
  60 + return static::$default;
  61 + }
  62 +
  63 + /**
  64 + * 设置默认的 option 选项
  65 + *
  66 + * @param array $defaultOption
  67 + */
  68 + public static function setDefaultOption(array $defaultOption)
  69 + {
  70 + static::$default = $defaultOption;
  71 + }
  72 +
  73 + /**
  74 + * 获取 HTTP 客户端
  75 + *
  76 + * @return ClientInterface
  77 + */
  78 + public function getClient()
  79 + {
  80 + if (!($this->httpClient instanceof ClientInterface)) {
  81 + $this->httpClient = new Client();
  82 + }
  83 +
  84 + return $this->httpClient;
  85 + }
  86 +
  87 + /**
  88 + * 设置请求的客户端
  89 + *
  90 + * @param ClientInterface $client
  91 + * @return $this
  92 + */
  93 + public function setClient(ClientInterface $client)
  94 + {
  95 + $this->httpClient = $client;
  96 +
  97 + return $this;
  98 + }
  99 +
  100 + /**
  101 + * 发送请求
  102 + *
  103 + * @param string $url
  104 + * @param string $method
  105 + * @param array $option
  106 + * @return \Psr\Http\Message\ResponseInterface
  107 + * @throws \GuzzleHttp\Exception\GuzzleException
  108 + */
  109 + public function request($url, $method = 'POST', $option = [])
  110 + {
  111 + $method = strtoupper($method);
  112 +
  113 + $options = array_merge(static::$default, $option, ['handler' => $this->getHandlerStack()]);
  114 +
  115 + if (property_exists($this, 'baseUri') && !is_null($this->baseUri)) {
  116 + $options['base_uri'] = $this->baseUri;
  117 + }
  118 +
  119 + $response = $this->getClient()->request($method, $url, $options);
  120 +
  121 + $response->getBody()->rewind();
  122 + return $response;
  123 + }
  124 +
  125 + /**
  126 + * 构建 HandlerStack
  127 + *
  128 + * @return \GuzzleHttp\HandlerStack
  129 + */
  130 + public function getHandlerStack()
  131 + {
  132 + if ($this->handlerStack) {
  133 + return $this->handlerStack;
  134 + }
  135 +
  136 + $this->handlerStack = HandlerStack::create();
  137 +
  138 + foreach ($this->middlewares as $name => $middleware) {
  139 + $this->handlerStack->push($middleware, $name);
  140 + }
  141 +
  142 + return $this->handlerStack;
  143 + }
  144 +
  145 + /**
  146 + * @param \GuzzleHttp\HandlerStack $handlerStack
  147 + *
  148 + * @return $this
  149 + */
  150 + public function setHandlerStack(HandlerStack $handlerStack)
  151 + {
  152 + $this->handlerStack = $handlerStack;
  153 +
  154 + return $this;
  155 + }
  156 +
  157 + /**
  158 + * 添加一个中间件
  159 + *
  160 + * @param callable $middleware
  161 + * @param string $name
  162 + *
  163 + * @return $this
  164 + */
  165 + public function pushMiddleware(callable $middleware, $name = null)
  166 + {
  167 + if (is_null($name)) {
  168 + array_push($this->middlewares, $middleware);
  169 + } else {
  170 + $this->middlewares[$name] = $middleware;
  171 + }
  172 +
  173 + return $this;
  174 + }
  175 +
  176 + /**
  177 + * 获取所有的中间件
  178 + *
  179 + * @return array
  180 + */
  181 + public function getMiddlewares()
  182 + {
  183 + return $this->middlewares;
  184 + }
  185 +}
0 186 \ No newline at end of file
... ...
src/Kernel/Traits/ResponseCastable.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: ChuXiang
  5 + * Date: 2019/8/14
  6 + * Time: 11:17
  7 + */
  8 +
  9 +namespace PgServiceSdk\Kernel\Traits;
  10 +
  11 +
  12 +use PgServiceSdk\Kernel\Contracts\ResponseFormatted;
  13 +use PgServiceSdk\Kernel\Exceptions\InvalidConfigException;
  14 +use PgServiceSdk\Kernel\Http\Response;
  15 +use Psr\Http\Message\ResponseInterface;
  16 +
  17 +trait ResponseCastable
  18 +{
  19 + /**
  20 + * 将响应转化为响应格式
  21 + *
  22 + * @param ResponseInterface $response
  23 + * @param null $type
  24 + * @return \Psr\Http\Message\ResponseInterface|\PgServiceSdk\Kernel\Support\Collection|array|object|string
  25 + *
  26 + * @throws InvalidConfigException
  27 + */
  28 + protected function costResponseToType(ResponseInterface $response, $type = null)
  29 + {
  30 + $guzzleResponse = Response::buildFromPsrResponse($response);
  31 + $guzzleResponse->getBody()->rewind();
  32 +
  33 + switch ($type ? $type : 'array') {
  34 + case 'collection':
  35 + return $guzzleResponse->toCollection();
  36 + break;
  37 + case 'array':
  38 + return $guzzleResponse->toArray();
  39 + break;
  40 + case 'object':
  41 + return $guzzleResponse->toObject();
  42 + break;
  43 + case 'raw':
  44 + return $guzzleResponse;
  45 + break;
  46 + default :
  47 + if (!is_subclass_of($type, ResponseFormatted::class)) {
  48 + throw new InvalidConfigException(sprintf(
  49 + 'Config key "response_type" classname must be an instanceof %s',
  50 + ResponseFormatted::class
  51 + ));
  52 + }
  53 +
  54 + return (new $type($response))->format();
  55 + }
  56 + }
  57 +}
0 58 \ No newline at end of file
... ...
src/Work/BaseClient.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Work;
  4 +
  5 +use \PgServiceSdk\Kernel\BaseClient as KernelBaseClient;
  6 +
  7 +abstract class BaseClient extends KernelBaseClient
  8 +{
  9 +
  10 +}
0 11 \ No newline at end of file
... ...
src/Work/MemberClient.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Work;
  4 +
  5 +
  6 +class MemberClient extends BaseClient
  7 +{
  8 +
  9 + public function lists(array $params = [])
  10 + {
  11 + $url = '/weconnect-uc-organization/b/707236020AE959C2124DD5EEA00EB63A/ensetting/query';
  12 + //return $this->httpGet($url, $params);
  13 + return $this->httpPostJson($url, $params);
  14 + }
  15 +}
0 16 \ No newline at end of file
... ...
src/Work/ServiceProvider.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace PgServiceSdk\Work;
  4 +
  5 +use Pimple\Container;
  6 +use Pimple\ServiceProviderInterface;
  7 +
  8 +/**
  9 + * Class ServiceProvider
  10 + * @package PgServiceSdk\Work
  11 + */
  12 +class ServiceProvider implements ServiceProviderInterface
  13 +{
  14 +
  15 + /**
  16 + * UC 企业微信相关接口
  17 + *
  18 + * @param Container $pimple
  19 + */
  20 + public function register(Container $pimple)
  21 + {
  22 + $pimple['member'] = function ($app) {
  23 + return new MemberClient($app);
  24 + };
  25 + }
  26 +}
0 27 \ No newline at end of file
... ...
src/config.php 0 → 100644
  1 +<?php
  2 +
  3 +return [
  4 +
  5 + 'default' => [
  6 + /*
  7 + * 指定 API 调用返回结果的类型:collection(default)/array/object/raw/自定义类名
  8 + */
  9 + 'response_type' => 'array',
  10 +
  11 + /*
  12 + * 接口请求相关配置,超时时间等,具体可用参数请参考:
  13 + * http://docs.guzzlephp.org/en/stable/request-config.html
  14 + *
  15 + * - retries: 重试次数,默认 1,指定当 http 请求失败时重试的次数。
  16 + * - retry_delay: 重试延迟间隔(单位:ms),默认 500
  17 + * - log_template: 指定 HTTP 日志模板,请参考:https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php
  18 + */
  19 + 'http' => [
  20 + 'retries' => 1,
  21 + 'retry_delay' => 500,
  22 + 'timeout' => 10.0,
  23 + 'base_uri' => 'https://transitsharedqaapim0.azure-api.cn',
  24 + 'debug' => true,
  25 + 'http_errors' => false
  26 + ],
  27 +
  28 + 'apim' => [
  29 + 'api_key' => 'weconnect-3820',
  30 + 'secret' => 'QeJJJnjNdG5g',
  31 + 'uc' => [
  32 + 'subscription_key' => '5e44068303654121b93b66f6c1754426',
  33 + 'nonce_str' => '58x2aagn'
  34 + ]
  35 + ]
  36 + ],
  37 +];
0 38 \ No newline at end of file
... ...