first commit

This commit is contained in:
2024-04-01 09:54:43 +08:00
commit 899d816bc3
795 changed files with 130040 additions and 0 deletions

View File

@@ -0,0 +1,201 @@
<?php
namespace Yeepay\Yop\Sdk\Http;
use Yeepay\Yop\Sdk\Utils\Http\Region;
use Yeepay\Yop\Sdk\Utils\YopConstants;
class ClientConfiguration
{
const DEFAULT_CONNECTION_TIMEOUT_IN_MILLIS = 50000;
const DEFAULT_SOCKET_TIMEOUT_IN_MILLIS = 50000;
private static $defaultUserAgent;
private static $defaultRegion = Region::CN_N1;
/**
* ClientConfiguration constructor.
* @param int $connectionTimeoutInMillis
* @param int $socketTimeoutInMillis
* @param null $userAgent
* @param null $proxyUrl
*/
public function __construct(
$connectionTimeoutInMillis = self::DEFAULT_CONNECTION_TIMEOUT_IN_MILLIS,
$socketTimeoutInMillis = self::DEFAULT_SOCKET_TIMEOUT_IN_MILLIS,
$userAgent = null,
$region = null,
$proxyUrl = null
) {
$this->connectionTimeoutInMillis = $connectionTimeoutInMillis;
$this->socketTimeoutInMillis = $socketTimeoutInMillis;
$this->userAgent = isset($userAgent) ? $userAgent : self::$defaultUserAgent;
$this->region = isset($region) ? $region : self::$defaultRegion;
$this->proxyUrl = $proxyUrl;
}
public static function __init()
{
self::$defaultUserAgent = YopConstants::LANG.'/'.YopConstants::VERSION.'/'.php_uname('s').'/'.php_uname('r').'/m/m/'.phpversion();
}
/**
* @var string
*/
private $userAgent;
/**
* @var string
*/
private $proxyUrl;
/**
* @var float
*/
private $connectionTimeoutInMillis;
/**
* @var float
*/
private $socketTimeoutInMillis;
/**
* @var string
*/
private $region;
/**
* @return mixed
*/
public static function getDefaultUserAgent()
{
return self::$defaultUserAgent;
}
/**
* @param mixed $defaultUserAgent
*/
public static function setDefaultUserAgent($defaultUserAgent)
{
self::$defaultUserAgent = $defaultUserAgent;
}
/**
* @return string
*/
public static function getDefaultRegion()
{
return self::$defaultRegion;
}
/**
* @param string $defaultRegion
*/
public static function setDefaultRegion($defaultRegion)
{
self::$defaultRegion = $defaultRegion;
}
/**
* @return mixed
*/
public function getUserAgent()
{
return $this->userAgent;
}
/**
* @param mixed $userAgent
* @return ClientConfiguration
*/
public function setUserAgent($userAgent)
{
$this->userAgent = $userAgent;
return $this;
}
/**
* @return string
*/
public function getProxyUrl()
{
return $this->proxyUrl;
}
/**
* @param string $proxyUrl
* @return ClientConfiguration
*/
public function setProxyUrl($proxyUrl)
{
$this->proxyUrl = $proxyUrl;
return $this;
}
/**
* @return float
*/
public function getConnectionTimeoutInMillis()
{
return $this->connectionTimeoutInMillis;
}
/**
* @param float $connectionTimeoutInMillis
* @return ClientConfiguration
*/
public function setConnectionTimeoutInMillis($connectionTimeoutInMillis)
{
$this->connectionTimeoutInMillis = $connectionTimeoutInMillis;
return $this;
}
/**
* @return float
*/
public function getSocketTimeoutInMillis()
{
return $this->socketTimeoutInMillis;
}
/**
* @param float $socketTimeoutInMillis
* @return ClientConfiguration
*/
public function setSocketTimeoutInMillis($socketTimeoutInMillis)
{
$this->socketTimeoutInMillis = $socketTimeoutInMillis;
return $this;
}
/**
* @return string
*/
public function getRegion()
{
return $this->region;
}
/**
* @param string $region
* @return ClientConfiguration
*/
public function setRegion($region)
{
$this->region = $region;
return $this;
}
}
ClientConfiguration::__init();

16
lib/Http/ContentType.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
namespace Yeepay\Yop\Sdk\Http;
class ContentType
{
const APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded";
const APPLICATION_JSON = "application/json";
const APPLICATION_OCTET_STREAM = "application/octet-stream";
const MULTIPART_FORM_DATA = "multipart/form-data";
}

View File

@@ -0,0 +1,133 @@
<?php
namespace Yeepay\Yop\Sdk\Http;
use Yeepay\Yop\Sdk\Auth\Encryptor;
use Yeepay\Yop\Sdk\Auth\Signer;
use Yeepay\Yop\Sdk\Auth\SignOptions;
use Yeepay\Yop\Sdk\Auth\YopRsaCredentials;
class ExecutionContext
{
/**
* @var Signer
*/
private $signer;
/**
* @var SignOptions
*/
private $signOptions;
/**
* @var bool
*/
private $needEncrypt;
/**
* @var Encryptor
*/
private $encryptor;
/**
* @var YopRsaCredentials
*/
private $credentials;
/**
* @return Signer
*/
public function getSigner()
{
return $this->signer;
}
/**
* @param Signer $signer
* @return ExecutionContext
*/
public function setSigner($signer)
{
$this->signer = $signer;
return $this;
}
/**
* @return SignOptions
*/
public function getSignOptions()
{
return $this->signOptions;
}
/**
* @param SignOptions $signOptions
* @return ExecutionContext
*/
public function setSignOptions($signOptions)
{
$this->signOptions = $signOptions;
return $this;
}
/**
* @return bool
*/
public function isNeedEncrypt()
{
return $this->needEncrypt;
}
/**
* @param bool $needEncrypt
* @return ExecutionContext
*/
public function setNeedEncrypt($needEncrypt)
{
$this->needEncrypt = $needEncrypt;
return $this;
}
/**
* @return Encryptor
*/
public function getEncryptor()
{
return $this->encryptor;
}
/**
* @param Encryptor $encryptor
* @return ExecutionContext
*/
public function setEncryptor($encryptor)
{
$this->encryptor = $encryptor;
return $this;
}
/**
* @return YopRsaCredentials
*/
public function getCredentials()
{
return $this->credentials;
}
/**
* @param YopRsaCredentials $credentials
* @return ExecutionContext
*/
public function setCredentials($credentials)
{
$this->credentials = $credentials;
return $this;
}
}

100
lib/Http/Headers.php Normal file
View File

@@ -0,0 +1,100 @@
<?php
namespace Yeepay\Yop\Sdk\Http;
class Headers
{
/*
* Standard HTTP Headers
*/
const AUTHORIZATION = "Authorization";
const CACHE_CONTROL = "Cache-Control";
const CONTENT_DISPOSITION = "Content-Disposition";
const CONTENT_ENCODING = "Content-Encoding";
const CONTENT_LENGTH = "Content-Length";
const CONTENT_MD5 = "Content-MD5";
const CONTENT_RANGE = "Content-Range";
const CONTENT_TYPE = "Content-Type";
const DATE = "Date";
const ETAG = "ETag";
const EXPIRES = "Expires";
const HOST = "Host";
const LAST_MODIFIED = "Last-Modified";
const LOCATION = "Location";
const RANGE = "Range";
const SERVER = "Server";
const TRANSFER_ENCODING = "Transfer-Encoding";
const USER_AGENT = "User-Agent";
/*
* YOP Common HTTP Headers
*/
const YOP_ACL = "x-yop-acl";
const YOP_CONTENT_SHA256 = "x-yop-content-sha256";
/**
* 签名
*/
const YOP_SIGN = "x-yop-sign";
const YOP_HASH_CRC64ECMA = "x-yop-hash-crc64ecma";
const YOP_COPY_METADATA_DIRECTIVE = "x-yop-metadata-directive";
const YOP_COPY_SOURCE_IF_MATCH = "x-yop-copy-source-if-match";
const YOP_DATE = "x-yop-date";
const YOP_APPKEY = "x-yop-appkey";
const YOP_PREFIX = "x-yop-";
const YOP_REQUEST_ID = "x-yop-request-id";
const YOP_SECURITY_TOKEN = "x-yop-security-token";
const YOP_USER_METADATA_PREFIX = "x-yop-meta-";
const YOP_VIA = "x-yop-via";
const YOP_ENCRYPT_TYPE = "x-yop-encrypt-type";
/*
* YOS HTTP Headers
*/
const YOP_COPY_SOURCE = "x-yop-copy-source";
const YOP_COPY_SOURCE_IF_MODIFIED_SINCE = "x-yop-copy-source-if-modified-since";
const YOP_COPY_SOURCE_IF_NONE_MATCH = "x-yop-copy-source-if-none-match";
const YOP_COPY_SOURCE_IF_UNMODIFIED_SINCE = "x-yop-copy-source-if-unmodified-since";
const YOP_DEBUG_ID = "x-yop-debug-id";
const YOP_NEXT_APPEND_OFFSET = "x-yop-next-append-offset";
const YOP_OBJECT_TYPE = "x-yop-object-type";
}

29
lib/Http/HttpMethod.php Normal file
View File

@@ -0,0 +1,29 @@
<?php
/*
* Copyright 2014 Baidu, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* Http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
namespace Yeepay\Yop\Sdk\Http;
class HttpMethod
{
const GET = 'GET';
const PUT = 'PUT';
const POST = 'POST';
const DELETE = 'DELETE';
const HEAD = 'HEAD';
}

16
lib/Http/HttpStatus.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
namespace Yeepay\Yop\Sdk\Http;
class HttpStatus
{
const SC_OK = 200;
const SC_NO_CONTENT = 204;
const SC_INTERNAL_SERVER_ERROR = 500;
const SC_BAD_GATEWAY = 502;
}

144
lib/Http/YopHttpClient.php Normal file
View File

@@ -0,0 +1,144 @@
<?php
namespace Yeepay\Yop\Sdk\Http;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\ServerException;
use GuzzleHttp\RequestOptions;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;
use Yeepay\Yop\Sdk\Exception\YopClientException;
use Yeepay\Yop\Sdk\Internal\MultiPartFile;
use Yeepay\Yop\Sdk\Internal\Request;
use Yeepay\Yop\Sdk\Log\LogFactory;
use Yeepay\Yop\Sdk\Utils\Http\HttpUtils;
class YopHttpClient
{
/**
* @var ClientConfiguration
*/
private $clientConfiguration;
/**
* @var Client
*/
private $guzzleClient;
/**
* @var LoggerInterface
*/
private $logger;
/**
* YopHttpClient constructor.
* @param ClientConfiguration $clientConfiguration
*/
public function __construct(ClientConfiguration $clientConfiguration)
{
$this->logger = LogFactory::getLogger(get_class($this));
$this->clientConfiguration = $clientConfiguration;
$guzzleClientConfig = [
RequestOptions::CONNECT_TIMEOUT => $clientConfiguration->getConnectionTimeoutInMillis() / 1000,
RequestOptions::TIMEOUT, $clientConfiguration->getSocketTimeoutInMillis() / 1000,
];
if (!empty($clientConfiguration->getProxyUrl())) {
$guzzleClientConfig[RequestOptions::PROXY] = $clientConfiguration->getProxyUrl();
}
$this->guzzleClient = new Client($guzzleClientConfig);
}
/**
* @param Request $request
* @param ExecutionContext $executionContext
* @return YopHttpResponse
* @throws YopClientException
*/
public function execute(Request $request, ExecutionContext $executionContext)
{
$credentials = $executionContext->getCredentials();
$request->addHeader(Headers::YOP_APPKEY, $credentials->getAppKey());
$request->addHeader(Headers::USER_AGENT, $this->clientConfiguration->getUserAgent());
if ($executionContext->isNeedEncrypt()) {
$executionContext->getEncryptor()->encrypt($request);
}
$executionContext->getSigner()
->sign($request, $executionContext->getCredentials(), $executionContext->getSignOptions());
try {
$guzzleResponse = $this->sendRequest($request);
} catch (ServerException $e) {
$guzzleResponse = $e->getResponse();
} catch (\Throwable $e) {
throw new YopClientException("execute request failed:".$e->getMessage());
}
return new YopHttpResponse($guzzleResponse);
}
/**
* @param Request $request
* @return mixed|ResponseInterface
* @throws GuzzleException
* @throws YopClientException
*/
private function sendRequest(Request $request)
{
$uri = $request->getEndpoint().HttpUtils::urlEncodeExceptSlash($request->getResourcePath());
if (!empty($request->getMultipartFiles())) {
if ($request->getHttpMethod() == HttpMethod::POST) {
$body = [];
if (!empty($request->getParameters())) {
foreach ($request->getParameters() as $k => $v) {
if (!empty($v)) {
foreach ($v as $value) {
$body[] = ['name' => $k, 'contents' => $value];
}
}
}
}
foreach ($request->getMultipartFiles() as $k => $v) {
$part = ['name' => $k];
if (!empty($v)) {
foreach ($v as $value) {
/** @var MultiPartFile $value */
$part['contents'] = $value->getContent();
$part['filename'] = $value->getFileName();
$body[] = $part;
}
}
}
return $this->guzzleClient->request($request->getHttpMethod(), $uri,
[
RequestOptions::MULTIPART => $body,
RequestOptions::HEADERS => $request->getHeaders(),
]);
} else {
throw new YopClientException("contentType:multipart/form-data only support post request.");
}
}
$requestIsPostOrPut = $request->getHttpMethod() == HttpMethod::POST || $request->getHttpMethod() == HttpMethod::PUT;
$requestHasPayload = !empty($request->getContent());
$putParamsInUri = !$requestIsPostOrPut || $requestHasPayload;
if ($putParamsInUri) {
$encodedParameters = \GuzzleHttp\Psr7\Query::build(HttpUtils::encodedParameters($request->getParameters()));
if (!empty($encodedParameters)) {
$uri = $uri.'?'.$encodedParameters;
}
}
$requestOptions = [RequestOptions::HEADERS => $request->getHeaders()];
if ($requestHasPayload) {
$requestOptions[RequestOptions::BODY] = $request->getContent();
} else {
if ($requestIsPostOrPut) {
$requestOptions[RequestOptions::BODY] = \GuzzleHttp\Psr7\Query::build(HttpUtils::encodedParameters($request->getParameters()));
}
}
return $this->guzzleClient->request($request->getHttpMethod(), $uri, $requestOptions);
}
}

View File

@@ -0,0 +1,140 @@
<?php
namespace Yeepay\Yop\Sdk\Http;
use DateTime;
use Exception;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\StreamInterface;
use Psr\Log\LoggerInterface;
use Yeepay\Yop\Sdk\Log\LogFactory;
use Yeepay\Yop\Sdk\Utils\DateUtils;
class YopHttpResponse
{
/**
* @var LoggerInterface
*/
private static $logger;
/**
* @var Response
*/
private $httpResponse;
/**
* @var StreamInterface
*/
private $stream;
/**
* @var string
*/
private $content;
public static function __init()
{
self::$logger = LogFactory::getLogger(self::class);
}
/**
* YopHttpResponse constructor.
* @param Response $response
*/
public function __construct(Response $response)
{
$this->httpResponse = $response;
$this->stream = $response->getBody();
}
/**
* @param string $name
* @return null | string
*/
public function getHeader($name)
{
$values = $this->httpResponse->getHeader($name);
if (empty($values)) {
return null;
} else {
return $values[0];
}
}
/**
* @param string $name
* @return float
*/
public function getHeaderAsLong($name)
{
$values = $this->httpResponse->getHeader($name);
if (empty($values)) {
return -1;
} else {
return floatval($values[0]);
}
}
/**
* @param $name
* @return DateTime|null
*/
public function getHeaderAsRFC822Date($name)
{
$values = $this->httpResponse->getHeader($name);
if (empty($values)) {
return null;
} else {
try {
return DateUtils::parseRfc822Date($values[0]);
} catch (Exception $e) {
self::$logger->warning('Invalid '.$name.':'.$values[0]);
}
}
}
/**
* @return StreamInterface
*/
public function getContent()
{
return $this->stream;
}
/**
* @return string
*/
public function readContent()
{
if (isset($this->content)) {
return $this->content;
}
$this->content = $this->stream->__toString();
$this->stream->close();
return $this->content;
}
/**
* @return int
*/
public function getStatusCode()
{
return $this->httpResponse->getStatusCode();
}
/**
* @return string
*/
public function getStatusText()
{
return implode(' ', [
$this->httpResponse->getProtocolVersion(), $this->httpResponse->getStatusCode(),
$this->httpResponse->getReasonPhrase(),
]);
}
}
YopHttpResponse::__init();