<?php
const FORM_URLENCODED = "application/x-www-form-urlencoded";
/**
* Generate a sorted query parameter string from parameter array.
* such as array('b' => 1, 'a' => 2) to "a=1&b=2"
*
* @param array $paramArr
* @return string sorted query string
*/
function getSortedParameterStr($paramArr)
{
ksort($paramArr);
$tmpArr = array();
foreach ($paramArr as $k => $v) {
$tmp = $k;
if (!empty($v)) {
$tmp .= ("=" . $v);
}
array_push($tmpArr, $tmp);
}
return join('&', $tmpArr);
}
/**
* Send a HTTP request with App Authorization
*
* @param $apiAppKey string API App Key
* @param $apiAppSecret string API App Secret
* @param $method string HTTP Method of API
* @param $url string Request URL of API, note that environment path (/release) is not allowed
* @param $contentType string Request Content-Type header, set empty if request body is not needed
* @param $acceptHeader string Accept HTTP request header
* @param $reqBody string Request Body, set null if request body is not needed
* @param $formParam array form parameters array, set null if not form request
* @param $algorithm string Encryption algorithm: sha1, sha256, sha384, sha512, SM3, default to sha1
* @param $customHeaders array Custom HTTP Headers, such as `array('x-header-a' => 1)`
*/
function sendRequestWithAppAuth($apiAppKey, $apiAppSecret, $method, $url, $contentType, $acceptHeader,
$reqBody=null, $formParam=null, $algorithm=null, $customHeaders=null)
{
$contentMD5 = "";
$isForm = ($contentType == FORM_URLENCODED);
// Note: ContentMd5 is empty for application/x-www-form-urlencoded request
if ($isForm) {
assert(!is_null($formParam), "formParam is required for form request");
// generate request body from form parameters
$reqBody = getSortedParameterStr($formParam);
} elseif (!is_null($reqBody)) {
// get content md5 for signing the request later
$contentMD5 = base64_encode(md5($reqBody));
}
if (null === $algorithm) {
$algorithm = "sha1";
}
// ===================================
// STEP 1: Generate the string to sign
// ===================================
echo "1. URL:\\n $url\\n";
// Note:
// 1. parameters needs to be sorted in alphabetical order
// 2. parameters include both query parameters and form parameters
$paramArr = array();
$parsedUrl = parse_url($url);
if (!is_null($parsedUrl['query']) && !empty($parsedUrl['query'])) {
parse_str($parsedUrl['query'], $paramArr);
}
if (!empty($formParam)) {
$paramArr = array_merge($paramArr, $formParam);
}
$pathAndParam = $parsedUrl['path'];
if (!empty($paramArr)){
$pathAndParam = $pathAndParam . '?' . getSortedParameterStr($paramArr);
}
$xDateHeader = gmstrftime('%a, %d %b %Y %T %Z', time());
$strToSign = sprintf("x-date: %s\\n%s\\n%s\\n%s\\n%s\\n%s",
$xDateHeader, $method, $acceptHeader, $contentType, $contentMD5, $pathAndParam);
// Print stringToSign for debugging if authorization failed with 401
$strToSignDebug = str_replace("\\n", "#", $strToSign);
echo "2. StringToSign:\\n $strToSignDebug\\n";
// ===============================================================================
// STEP 2: Generate the signature (Authorization header) based on the stringToSign
// ===============================================================================
// Encode the string with HMAC and base64.
$sign = base64_encode(hash_hmac($algorithm, $strToSign, $apiAppSecret, TRUE));
$authHeader = sprintf(
'hmac id="%s", algorithm="hmac-%s", headers="x-date", signature="%s"',
$apiAppKey, $algorithm, $sign
);
$headers = array(
'Host:' . $parsedUrl['host'],
'Accept:' . $acceptHeader,
'X-Date:' . $xDateHeader,
'Authorization:' . $authHeader,
);
if (!empty($contentType)) {
array_push($headers, "Content-Type:" . $contentType);
}
if (!empty($contentMD5)) {
array_push($headers, "Content-MD5:" . $contentMD5);
}
if (!is_null($customHeaders) && is_array($customHeaders)) {
foreach ($customHeaders as $k => $v) {
array_push($headers, $k . ":" . $v);
}
}
echo "3. Request Headers:\\n";
var_dump($headers);
// ============================
// STEP 3: Send the API request
// ============================
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
if (!empty($reqBody)) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $reqBody); // only required if request body is present
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
$data = curl_exec($ch);
if (curl_errno($ch)) {
print "Error: " . curl_error($ch);
} else {
echo "Response: \\n";
var_dump($data);
curl_close($ch);
}
}
Was this page helpful?