长话短说,这是我生成 OAuth 1.0 签名的函数,只要 URL 中没有添加任何参数,它就可以正常工作。即使添加单个参数也会导致我使用此函数连接的 API 发出“签名无效”响应。
function generateSignature($request, $timestamp, $nonce) {
$parameters = array();
ksort($request['params']);
foreach($request['params'] as $key=>$value){
$parameters[] = "$key=".rawurlencode($value);
}
$base = $request['method']."&".rawurlencode($request['url'])."&".rawurlencode(implode('&', $parameters))."&"
.rawurlencode("oauth_consumer_key=".rawurlencode(consumer_key)
."&oauth_nonce=".rawurlencode($nonce)
."&oauth_signature_method=".rawurlencode("HMAC-SHA1")
."&oauth_timestamp=". rawurlencode($timestamp)
."&oauth_token=".rawurlencode(token)
."&oauth_version=".rawurlencode("1.0"));
$key = rawurlencode(consumer_secret).'&'.rawurlencode(token_secret);
$signature = base64_encode(hash_hmac('SHA1', $base, $key, true));
return $signature;
}
该函数的使用如下。同样,当参数不存在时,这可以完美地工作:
$ch = curl_init();
$request = array();
$request['method'] = 'GET';
$request['url'] = base_url.'/orders';
$params = array();
$params['status'] = 'pending';
$request['params'] = $params;
$parameters = (empty($request['params'])) ? "" : "?".http_build_query($request['params']);
curl_setopt($ch, CURLOPT_URL, $request['url'].$parameters);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request['method']);
$timestamp = time();
$nonce = generateNonce($timestamp);
$signature = generateSignature($request, $timestamp, $nonce);
$headers = array();
$headers[] = 'Authorization: OAuth realm="",oauth_version="1.0",oauth_consumer_key="'.consumer_key.'",oauth_token="'.token.'",oauth_timestamp="'.$timestamp.'",oauth_nonce="'.$nonce.'",oauth_signature_method="HMAC-SHA1",oauth_signature="'.$signature.'"';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
我做错了什么?我检查了 OAuth 1.0 文档和 StackOverflow 的示例,但无法识别问题。
好的,找到问题了。包含参数的字符串应添加到基本字符串的末尾:
function generateSignature($request, $timestamp, $nonce) {
$base = $request['method']."&".rawurlencode($request['url'])."&"
.rawurlencode("oauth_consumer_key=".rawurlencode(consumer_key)
."&oauth_nonce=".rawurlencode($nonce)
."&oauth_signature_method=".rawurlencode("HMAC-SHA1")
."&oauth_timestamp=". rawurlencode($timestamp)
."&oauth_token=".rawurlencode(token)
."&oauth_version=".rawurlencode("1.0"));
if (!empty($request['params'])) {
$base .= rawurlencode("&".http_build_query($request['params']));
}
$key = rawurlencode(consumer_secret).'&'.rawurlencode(token_secret);
$signature = base64_encode(hash_hmac('SHA1', $base, $key, true));
return $signature;
}
感谢您提供的这个示例,即使如此,我还是挣扎了几个小时才弄清楚,如果您的查询参数按字母顺序小于“oauth”,那么您需要将查询参数移至更靠近基数开头的位置。就我而言,查询参数是“id”。似乎基本字符串中的所有参数都需要按字母顺序排列,因此您可能在 oauth 参数之前和之后有一些查询参数。
$base = $request['method']."&".rawurlencode($request['url'])."&"
.rawurlencode(http_build_query($request['params']))
.rawurlencode("&oauth_consumer_key=".rawurlencode($consumer_key)
."&oauth_nonce=".rawurlencode($nonce)
."&oauth_signature_method=".rawurlencode("HMAC-SHA1")
."&oauth_timestamp=". rawurlencode($timestamp)
."&oauth_token=".rawurlencode($token)
."&oauth_version=".rawurlencode("1.0"));