Files
apimacro/vendor/automattic/woocommerce/src/WooCommerce/HttpClient/OAuth.php
2024-05-07 12:17:25 +02:00

269 lines
6.5 KiB
PHP

<?php
/**
* WooCommerce oAuth1.0
*
* @category HttpClient
* @package Automattic/WooCommerce
*/
namespace Automattic\WooCommerce\HttpClient;
/**
* oAuth1.0 class.
*
* @package Automattic/WooCommerce
*/
class OAuth
{
/**
* OAuth signature method algorithm.
*/
public const HASH_ALGORITHM = 'SHA256';
/**
* API endpoint URL.
*
* @var string
*/
protected $url;
/**
* Consumer key.
*
* @var string
*/
protected $consumerKey;
/**
* Consumer secret.
*
* @var string
*/
protected $consumerSecret;
/**
* API version.
*
* @var string
*/
protected $apiVersion;
/**
* Request method.
*
* @var string
*/
protected $method;
/**
* Request parameters.
*
* @var array
*/
protected $parameters;
/**
* Timestamp.
*
* @var string
*/
protected $timestamp;
/**
* Initialize oAuth class.
*
* @param string $url Store URL.
* @param string $consumerKey Consumer key.
* @param string $consumerSecret Consumer Secret.
* @param string $method Request method.
* @param string $apiVersion API version.
* @param array $parameters Request parameters.
* @param string $timestamp Timestamp.
*/
public function __construct(
$url,
$consumerKey,
$consumerSecret,
$apiVersion,
$method,
$parameters = [],
$timestamp = ''
) {
$this->url = $url;
$this->consumerKey = $consumerKey;
$this->consumerSecret = $consumerSecret;
$this->apiVersion = $apiVersion;
$this->method = $method;
$this->parameters = $parameters;
$this->timestamp = $timestamp;
}
/**
* Encode according to RFC 3986.
*
* @param string|array $value Value to be normalized.
*
* @return string
*/
protected function encode($value)
{
if (is_array($value)) {
return array_map([$this, 'encode'], $value);
} else {
return str_replace(['+', '%7E'], [' ', '~'], rawurlencode($value));
}
}
/**
* Normalize parameters.
*
* @param array $parameters Parameters to normalize.
*
* @return array
*/
protected function normalizeParameters($parameters)
{
$normalized = [];
foreach ($parameters as $key => $value) {
// Percent symbols (%) must be double-encoded.
$key = $this->encode($key);
$value = $this->encode($value);
$normalized[$key] = $value;
}
return $normalized;
}
/**
* Process filters.
*
* @param array $parameters Request parameters.
*
* @return array
*/
protected function processFilters($parameters)
{
if (isset($parameters['filter'])) {
$filters = $parameters['filter'];
unset($parameters['filter']);
foreach ($filters as $filter => $value) {
$parameters['filter[' . $filter . ']'] = $value;
}
}
return $parameters;
}
/**
* Get secret.
*
* @return string
*/
protected function getSecret()
{
$secret = $this->consumerSecret;
// Fix secret for v3 or later.
if (!\in_array($this->apiVersion, ['v1', 'v2'])) {
$secret .= '&';
}
return $secret;
}
/**
* Generate oAuth1.0 signature.
*
* @param array $parameters Request parameters including oauth.
*
* @return string
*/
protected function generateOauthSignature($parameters)
{
$baseRequestUri = \rawurlencode($this->url);
// Extract filters.
$parameters = $this->processFilters($parameters);
// Normalize parameter key/values and sort them.
$parameters = $this->normalizeParameters($parameters);
$parameters = $this->getSortedParameters($parameters);
// Set query string.
$queryString = \implode('%26', $this->joinWithEqualsSign($parameters)); // Join with ampersand.
$stringToSign = $this->method . '&' . $baseRequestUri . '&' . $queryString;
$secret = $this->getSecret();
return \base64_encode(\hash_hmac(self::HASH_ALGORITHM, $stringToSign, $secret, true));
}
/**
* Creates an array of urlencoded strings out of each array key/value pairs.
*
* @param array $params Array of parameters to convert.
* @param array $queryParams Array to extend.
* @param string $key Optional Array key to append
* @return string Array of urlencoded strings
*/
protected function joinWithEqualsSign($params, $queryParams = [], $key = '')
{
foreach ($params as $paramKey => $paramValue) {
if ($key) {
$paramKey = $key . '%5B' . $paramKey . '%5D'; // Handle multi-dimensional array.
}
if (is_array($paramValue)) {
$queryParams = $this->joinWithEqualsSign($paramValue, $queryParams, $paramKey);
} else {
$string = $paramKey . '=' . $paramValue; // Join with equals sign.
$queryParams[] = $this->encode($string);
}
}
return $queryParams;
}
/**
* Sort parameters.
*
* @param array $parameters Parameters to sort in byte-order.
*
* @return array
*/
protected function getSortedParameters($parameters)
{
\uksort($parameters, 'strcmp');
foreach ($parameters as $key => $value) {
if (\is_array($value)) {
\uksort($parameters[$key], 'strcmp');
}
}
return $parameters;
}
/**
* Get oAuth1.0 parameters.
*
* @return string
*/
public function getParameters()
{
$parameters = \array_merge($this->parameters, [
'oauth_consumer_key' => $this->consumerKey,
'oauth_timestamp' => $this->timestamp,
'oauth_nonce' => \sha1(\microtime()),
'oauth_signature_method' => 'HMAC-' . self::HASH_ALGORITHM,
]);
// The parameters above must be included in the signature generation.
$parameters['oauth_signature'] = $this->generateOauthSignature($parameters);
return $this->getSortedParameters($parameters);
}
}