Created
September 4, 2024 06:21
-
-
Save nczz/e8eb354e891c33d831e0d4246f32d161 to your computer and use it in GitHub Desktop.
PHP 版本的 OAuth 1.0a 請求方法 ( For NetSuite TBA 請求 )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// 從 https://www.npmjs.com/package/oauth-1.0a 這邊改寫過來用 | |
class OAuth { | |
private $consumer; | |
private $nonce_length; | |
private $version; | |
private $parameter_seperator; | |
private $realm; | |
private $last_ampersand; | |
private $signature_method; | |
private $hash_function; | |
private $body_hash_function; | |
public function __construct($opts) { | |
if (!isset($opts['consumer'])) { | |
throw new Exception('consumer option is required'); | |
} | |
$this->consumer = $opts['consumer']; | |
$this->nonce_length = isset($opts['nonce_length']) ? $opts['nonce_length'] : 32; | |
$this->version = isset($opts['version']) ? $opts['version'] : '1.0'; | |
$this->parameter_seperator = isset($opts['parameter_seperator']) ? $opts['parameter_seperator'] : ', '; | |
$this->realm = isset($opts['realm']) ? $opts['realm'] : null; | |
$this->last_ampersand = isset($opts['last_ampersand']) ? $opts['last_ampersand'] : true; | |
$this->signature_method = isset($opts['signature_method']) ? $opts['signature_method'] : 'PLAINTEXT'; | |
if ($this->signature_method == 'PLAINTEXT' && !isset($opts['hash_function'])) { | |
$opts['hash_function'] = function ($base_string, $key) { | |
return $key; | |
}; | |
} | |
if (!isset($opts['hash_function'])) { | |
throw new Exception('hash_function option is required'); | |
} | |
$this->hash_function = $opts['hash_function']; | |
$this->body_hash_function = isset($opts['body_hash_function']) ? $opts['body_hash_function'] : $this->hash_function; | |
} | |
public function authorize($request, $token = null) { | |
$oauth_data = array( | |
'oauth_consumer_key' => $this->consumer['key'], | |
'oauth_nonce' => $this->getNonce(), | |
'oauth_signature_method' => $this->signature_method, | |
'oauth_timestamp' => $this->getTimeStamp(), | |
'oauth_version' => $this->version, | |
); | |
if ($token !== null && isset($token['key'])) { | |
$oauth_data['oauth_token'] = $token['key']; | |
} | |
if (!isset($request['data'])) { | |
$request['data'] = array(); | |
} | |
if (isset($request['includeBodyHash']) && $request['includeBodyHash']) { | |
$oauth_data['oauth_body_hash'] = $this->getBodyHash($request, isset($token['secret']) ? $token['secret'] : ''); | |
} | |
$oauth_data['oauth_signature'] = $this->getSignature($request, isset($token['secret']) ? $token['secret'] : '', $oauth_data); | |
return $oauth_data; | |
} | |
private function getSignature($request, $token_secret, $oauth_data) { | |
return call_user_func($this->hash_function, $this->getBaseString($request, $oauth_data), $this->getSigningKey($token_secret)); | |
} | |
private function getBodyHash($request, $token_secret) { | |
$body = is_string($request['data']) ? $request['data'] : json_encode($request['data']); | |
if (!$this->body_hash_function) { | |
throw new Exception('body_hash_function option is required'); | |
} | |
return call_user_func($this->body_hash_function, $body, $this->getSigningKey($token_secret)); | |
} | |
private function getBaseString($request, $oauth_data) { | |
return strtoupper($request['method']) . '&' . $this->percentEncode($this->getBaseUrl($request['url'])) . '&' . $this->percentEncode($this->getParameterString($request, $oauth_data)); | |
} | |
private function getParameterString($request, $oauth_data) { | |
if (isset($oauth_data['oauth_body_hash'])) { | |
$base_string_data = $this->sortObject($this->percentEncodeData($this->mergeObject($oauth_data, $this->deParamUrl($request['url'])))); | |
} else { | |
$base_string_data = $this->sortObject($this->percentEncodeData($this->mergeObject($oauth_data, $this->mergeObject($request['data'], $this->deParamUrl($request['url']))))); | |
} | |
$data_str = ''; | |
foreach ($base_string_data as $item) { | |
$key = $item['key']; | |
$value = $item['value']; | |
if (is_array($value)) { | |
sort($value); | |
$valString = ''; | |
foreach ($value as $i => $val) { | |
$valString .= $key . '=' . $val; | |
if ($i < count($value) - 1) { | |
$valString .= '&'; | |
} | |
} | |
$data_str .= $valString; | |
} else { | |
$data_str .= $key . '=' . $value . '&'; | |
} | |
} | |
return substr($data_str, 0, -1); | |
} | |
private function getSigningKey($token_secret) { | |
$token_secret = $token_secret ?: ''; | |
if (!$this->last_ampersand && !$token_secret) { | |
return $this->percentEncode($this->consumer['secret']); | |
} | |
return $this->percentEncode($this->consumer['secret']) . '&' . $this->percentEncode($token_secret); | |
} | |
private function getBaseUrl($url) { | |
return explode('?', $url)[0]; | |
} | |
private function deParam($string) { | |
$arr = explode('&', $string); | |
$data = array(); | |
foreach ($arr as $item) { | |
$parts = explode('=', $item); | |
$key = $parts[0]; | |
$value = isset($parts[1]) ? $parts[1] : ''; | |
if (isset($data[$key])) { | |
if (!is_array($data[$key])) { | |
$data[$key] = array($data[$key]); | |
} | |
$data[$key][] = urldecode($value); | |
} else { | |
$data[$key] = urldecode($value); | |
} | |
} | |
return $data; | |
} | |
private function deParamUrl($url) { | |
$tmp = explode('?', $url); | |
if (count($tmp) === 1) { | |
return array(); | |
} | |
return $this->deParam($tmp[1]); | |
} | |
private function percentEncode($str) { | |
return rawurlencode($str); | |
} | |
private function percentEncodeData($data) { | |
$result = array(); | |
foreach ($data as $key => $value) { | |
if (is_array($value)) { | |
$newValue = array(); | |
foreach ($value as $val) { | |
$newValue[] = $this->percentEncode($val); | |
} | |
$value = $newValue; | |
} else { | |
$value = $this->percentEncode($value); | |
} | |
$result[$this->percentEncode($key)] = $value; | |
} | |
return $result; | |
} | |
public function toHeader($oauth_data) { | |
$sorted = $this->sortObject($oauth_data); | |
$header_value = 'OAuth '; | |
if ($this->realm) { | |
$header_value .= 'realm="' . $this->realm . '"' . $this->parameter_seperator; | |
} | |
foreach ($sorted as $item) { | |
if (strpos($item['key'], 'oauth_') !== 0) { | |
continue; | |
} | |
$header_value .= $this->percentEncode($item['key']) . '="' . $this->percentEncode($item['value']) . '"' . $this->parameter_seperator; | |
} | |
return array('Authorization' => substr($header_value, 0, -strlen($this->parameter_seperator))); | |
} | |
private function getNonce() { | |
$word_characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; | |
$result = ''; | |
for ($i = 0; $i < $this->nonce_length; $i++) { | |
$result .= $word_characters[rand(0, strlen($word_characters) - 1)]; | |
} | |
return $result; | |
} | |
private function getTimeStamp() { | |
return time(); | |
} | |
private function mergeObject($obj1, $obj2) { | |
return array_merge($obj1, $obj2); | |
} | |
private function sortObject($data) { | |
$keys = array_keys($data); | |
sort($keys); | |
// ksort($keys); | |
$result = array(); | |
foreach ($keys as $key) { | |
$result[] = array( | |
'key' => $key, | |
'value' => $data[$key], | |
); | |
} | |
return $result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment