| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- <?php
- namespace AlibabaCloud\OpenApiUtil;
- use AlibabaCloud\Tea\Model;
- use AlibabaCloud\Tea\Request;
- use AlibabaCloud\Tea\Utils\Utils;
- use OneSm\Sm3;
- use Psr\Http\Message\StreamInterface;
- /**
- * This is for OpenApi Util.
- */
- class OpenApiUtilClient
- {
- /**
- * Convert all params of body other than type of readable into content.
- *
- * @param Model $body source Model
- * @param Model $content target Model
- */
- public static function convert($body, $content)
- {
- $class = new \ReflectionClass($body);
- foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
- $name = $property->getName();
- if (!$property->isStatic()) {
- $value = $property->getValue($body);
- if ($value instanceof StreamInterface) {
- continue;
- }
- $content->{$name} = $value;
- }
- }
- }
- /**
- * Get the string to be signed according to request.
- *
- * @param Request $request which contains signed messages
- *
- * @return string the signed string
- */
- public static function getStringToSign($request)
- {
- $pathname = $request->pathname ?: '';
- $query = $request->query ?: [];
- $accept = isset($request->headers['accept']) ? $request->headers['accept'] : '';
- $contentMD5 = isset($request->headers['content-md5']) ? $request->headers['content-md5'] : '';
- $contentType = isset($request->headers['content-type']) ? $request->headers['content-type'] : '';
- $date = isset($request->headers['date']) ? $request->headers['date'] : '';
- $result = $request->method . "\n" .
- $accept . "\n" .
- $contentMD5 . "\n" .
- $contentType . "\n" .
- $date . "\n";
- $canonicalizedHeaders = self::getCanonicalizedHeaders($request->headers);
- $canonicalizedResource = self::getCanonicalizedResource($pathname, $query);
- return $result . $canonicalizedHeaders . $canonicalizedResource;
- }
- /**
- * Get signature according to stringToSign, secret.
- *
- * @param string $stringToSign the signed string
- * @param string $secret accesskey secret
- *
- * @return string the signature
- */
- public static function getROASignature($stringToSign, $secret)
- {
- return base64_encode(hash_hmac('sha1', $stringToSign, $secret, true));
- }
- /**
- * Parse filter into a form string.
- *
- * @param array $filter object
- *
- * @return string the string
- */
- public static function toForm($filter)
- {
- $query = $filter;
- if (null === $query) {
- return '';
- }
- if ($query instanceof Model) {
- $query = $query->toMap();
- }
- $tmp = [];
- foreach ($query as $k => $v) {
- if (0 !== strpos($k, '_')) {
- $tmp[$k] = $v;
- }
- }
- $res = self::flatten($tmp);
- ksort($res);
- return http_build_query($res);
- }
- /**
- * Get timestamp.
- *
- * @return string the timestamp string
- */
- public static function getTimestamp()
- {
- return gmdate('Y-m-d\\TH:i:s\\Z');
- }
- /**
- * Parse filter into a object which's type is map[string]string.
- *
- * @param array $filter query param
- *
- * @return array the object
- */
- public static function query($filter)
- {
- if (null === $filter) {
- return [];
- }
- $dict = $filter;
- if ($dict instanceof Model) {
- $dict = $dict->toMap();
- }
- $tmp = [];
- foreach ($dict as $k => $v) {
- if (0 !== strpos($k, '_')) {
- $tmp[$k] = $v;
- }
- }
- return self::flatten($tmp);
- }
- /**
- * Get signature according to signedParams, method and secret.
- *
- * @param array $signedParams params which need to be signed
- * @param string $method http method e.g. GET
- * @param string $secret AccessKeySecret
- *
- * @return string the signature
- */
- public static function getRPCSignature($signedParams, $method, $secret)
- {
- $secret .= '&';
- $strToSign = self::getRpcStrToSign($method, $signedParams);
- $signMethod = 'HMAC-SHA1';
- return self::encode($signMethod, $strToSign, $secret);
- }
- /**
- * Parse object into a string with specified style.
- *
- * @style specified style e.g. repeatList
- *
- * @param mixed $object the object
- * @param string $prefix the prefix string
- * @param string $style
- *
- * @return string the string
- */
- public static function arrayToStringWithSpecifiedStyle($object, $prefix, $style)
- {
- if (null === $object) {
- return '';
- }
- if ('repeatList' === $style) {
- return self::toForm([$prefix => $object]);
- }
- if ('simple' == $style || 'spaceDelimited' == $style || 'pipeDelimited' == $style) {
- $strs = self::flatten($object);
- switch ($style) {
- case 'spaceDelimited':
- return implode(' ', $strs);
- case 'pipeDelimited':
- return implode('|', $strs);
- default:
- return implode(',', $strs);
- }
- } elseif ('json' === $style) {
- self::parse($object, $parsed);
- return json_encode($parsed);
- }
- return '';
- }
- /**
- * Transform input as array.
- *
- * @param mixed $input
- *
- * @return array
- */
- public static function parseToArray($input)
- {
- self::parse($input, $result);
- return $result;
- }
- /**
- * Transform input as map.
- *
- * @param mixed $input
- *
- * @return array
- */
- public static function parseToMap($input)
- {
- self::parse($input, $result);
- return $result;
- }
- public static function getEndpoint($endpoint, $useAccelerate, $endpointType = 'public')
- {
- if ('internal' == $endpointType) {
- $tmp = explode('.', $endpoint);
- $tmp[0] .= '-internal';
- $endpoint = implode('.', $tmp);
- }
- if ($useAccelerate && 'accelerate' == $endpointType) {
- return 'oss-accelerate.aliyuncs.com';
- }
- return $endpoint;
- }
- /**
- * Encode raw with base16.
- *
- * @param int[] $raw encoding data
- *
- * @return string encoded string
- */
- public static function hexEncode($raw)
- {
- if (is_array($raw)) {
- $raw = Utils::toString($raw);
- }
- return bin2hex($raw);
- }
- /**
- * Hash the raw data with signatureAlgorithm.
- *
- * @param int[] $raw hashing data
- * @param string $signatureAlgorithm the autograph method
- *
- * @return array hashed bytes
- */
- public static function hash($raw, $signatureAlgorithm)
- {
- $str = Utils::toString($raw);
- switch ($signatureAlgorithm) {
- case 'ACS3-HMAC-SHA256':
- case 'ACS3-RSA-SHA256':
- $res = hash('sha256', $str, true);
- return Utils::toBytes($res);
- case 'ACS3-HMAC-SM3':
- $res = self::sm3($str);
- return Utils::toBytes(hex2bin($res));
- }
- return [];
- }
- /**
- * Get the authorization.
- *
- * @param Request $request request params
- * @param string $signatureAlgorithm the autograph method
- * @param string $payload the hashed request
- * @param string $accesskey the accessKey string
- * @param string $accessKeySecret the accessKeySecret string
- *
- * @return string authorization string
- * @throws \ErrorException
- *
- */
- public static function getAuthorization($request, $signatureAlgorithm, $payload, $accesskey, $accessKeySecret)
- {
- $canonicalURI = $request->pathname ? $request->pathname : '/';
- $query = $request->query ?: [];
- $method = strtoupper($request->method);
- $canonicalQueryString = self::getCanonicalQueryString($query);
- $signHeaders = [];
- foreach ($request->headers as $k => $v) {
- $k = strtolower($k);
- if (0 === strpos($k, 'x-acs-') || 'host' === $k || 'content-type' === $k) {
- $signHeaders[$k] = $v;
- }
- }
- ksort($signHeaders);
- $headers = [];
- foreach ($request->headers as $k => $v) {
- $k = strtolower($k);
- if (0 === strpos($k, 'x-acs-') || 'host' === $k || 'content-type' === $k) {
- $headers[$k] = trim($v);
- }
- }
- $canonicalHeaderString = '';
- ksort($headers);
- foreach ($headers as $k => $v) {
- $canonicalHeaderString .= $k . ':' . trim(self::filter($v)) . "\n";
- }
- if (empty($canonicalHeaderString)) {
- $canonicalHeaderString = "\n";
- }
- $canonicalRequest = $method . "\n" . $canonicalURI . "\n" . $canonicalQueryString . "\n" .
- $canonicalHeaderString . "\n" . implode(';', array_keys($signHeaders)) . "\n" . $payload;
- $strtosign = $signatureAlgorithm . "\n" . self::hexEncode(self::hash(Utils::toBytes($canonicalRequest), $signatureAlgorithm));
- $signature = self::sign($accessKeySecret, $strtosign, $signatureAlgorithm);
- $signature = self::hexEncode($signature);
- return $signatureAlgorithm .
- ' Credential=' . $accesskey .
- ',SignedHeaders=' . implode(';', array_keys($signHeaders)) .
- ',Signature=' . $signature;
- }
- public static function sign($secret, $str, $algorithm)
- {
- $result = '';
- switch ($algorithm) {
- case 'ACS3-HMAC-SHA256':
- $result = hash_hmac('sha256', $str, $secret, true);
- break;
- case 'ACS3-HMAC-SM3':
- $result = self::hmac_sm3($str, $secret, true);
- break;
- case 'ACS3-RSA-SHA256':
- $privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" . $secret . "\n-----END RSA PRIVATE KEY-----";
- @openssl_sign($str, $result, $privateKey, OPENSSL_ALGO_SHA256);
- }
- return Utils::toBytes($result);
- }
- /**
- * Get encoded path.
- *
- * @param string $path the raw path
- *
- * @return string encoded path
- */
- public static function getEncodePath($path)
- {
- $tmp = explode('/', $path);
- foreach ($tmp as &$t) {
- $t = rawurlencode($t);
- }
- return implode('/', $tmp);
- }
- /**
- * Get encoded param.
- *
- * @param string $param the raw param
- *
- * @return string encoded param
- */
- public static function getEncodeParam($param)
- {
- return rawurlencode($param);
- }
- private static function getRpcStrToSign($method, $query)
- {
- ksort($query);
- $params = [];
- foreach ($query as $k => $v) {
- if (null !== $v) {
- $k = rawurlencode($k);
- $v = rawurlencode($v);
- $params[] = $k . '=' . (string)$v;
- }
- }
- $str = implode('&', $params);
- return $method . '&' . rawurlencode('/') . '&' . rawurlencode($str);
- }
- private static function encode($signMethod, $strToSign, $secret)
- {
- switch ($signMethod) {
- case 'HMAC-SHA256':
- return base64_encode(hash_hmac('sha256', $strToSign, $secret, true));
- default:
- return base64_encode(hash_hmac('sha1', $strToSign, $secret, true));
- }
- }
- /**
- * @param array $items
- * @param string $delimiter
- * @param string $prepend
- *
- * @return array
- */
- private static function flatten($items = [], $delimiter = '.', $prepend = '')
- {
- $flatten = [];
- foreach ($items as $key => $value) {
- $pos = \is_int($key) ? $key + 1 : $key;
- if ($value instanceof Model) {
- $value = $value->toMap();
- } elseif (\is_object($value)) {
- $value = get_object_vars($value);
- }
- if (\is_array($value) && !empty($value)) {
- $flatten = array_merge(
- $flatten,
- self::flatten($value, $delimiter, $prepend . $pos . $delimiter)
- );
- } else {
- if (\is_bool($value)) {
- $value = true === $value ? 'true' : 'false';
- }
- $flatten[$prepend . $pos] = $value;
- }
- }
- return $flatten;
- }
- private static function getCanonicalizedHeaders($headers, $prefix = 'x-acs-')
- {
- ksort($headers);
- $str = '';
- foreach ($headers as $k => $v) {
- if (0 === strpos(strtolower($k), $prefix)) {
- $str .= $k . ':' . trim(self::filter($v)) . "\n";
- }
- }
- return $str;
- }
- private static function getCanonicalizedResource($pathname, $query)
- {
- if (0 === \count($query)) {
- return $pathname;
- }
- ksort($query);
- $tmp = [];
- foreach ($query as $k => $v) {
- if (!empty($v)) {
- $tmp[] = $k . '=' . $v;
- } else {
- $tmp[] = $k;
- }
- }
- return $pathname . '?' . implode('&', $tmp);
- }
- private static function parse($input, &$output)
- {
- if (null === $input || '' === $input) {
- $output = [];
- }
- $recursive = function ($input) use (&$recursive) {
- if ($input instanceof Model) {
- $input = $input->toMap();
- } elseif (\is_object($input)) {
- $input = get_object_vars($input);
- }
- if (!\is_array($input)) {
- return $input;
- }
- $data = [];
- foreach ($input as $k => $v) {
- $data[$k] = $recursive($v);
- }
- return $data;
- };
- $output = $recursive($input);
- if (!\is_array($output)) {
- $output = [$output];
- }
- }
- private static function filter($str)
- {
- return str_replace(["\t", "\n", "\r", "\f"], '', $str);
- }
- private static function hmac_sm3($data, $key, $raw_output = false)
- {
- $pack = 'H' . \strlen(self::sm3('test'));
- $blocksize = 64;
- if (\strlen($key) > $blocksize) {
- $key = pack($pack, self::sm3($key));
- }
- $key = str_pad($key, $blocksize, \chr(0x00));
- $ipad = $key ^ str_repeat(\chr(0x36), $blocksize);
- $opad = $key ^ str_repeat(\chr(0x5C), $blocksize);
- $hmac = self::sm3($opad . pack($pack, self::sm3($ipad . $data)));
- return $raw_output ? pack($pack, $hmac) : $hmac;
- }
- private static function sm3($message)
- {
- return (new Sm3())->sign($message);
- }
- private static function getCanonicalQueryString($query)
- {
- ksort($query);
- $params = [];
- foreach ($query as $k => $v) {
- if (null === $v) {
- continue;
- }
- $str = rawurlencode($k);
- if ('' !== $v && null !== $v) {
- $str .= '=' . rawurlencode($v);
- } else {
- $str .= '=';
- }
- $params[] = $str;
- }
- return implode('&', $params);
- }
- }
|