PHP火山引擎API签名方法
一、前置准备
在开始签名之前,需要准备以下信息:
- Access Key ID(AK):请求火山引擎OpenAPI的安全凭证之一。
- Secret Access Key(SK):与AK成对使用,用于签名计算。
- 请求参数:包括HTTP请求方法、URI、查询参数、请求头等。
二、签名流程(文档地址)
火山引擎API签名流程大致分为以下几个步骤:
- 创建规范请求:将请求参数进行规范化处理,形成CanonicalRequest。
- 创建待签名字符串:基于CanonicalRequest和其他元数据信息,构建StringToSign。
- 派生签名密钥:从SK派生出签名密钥(signing key)。
- 计算签名:使用HMAC-SHA256算法和签名密钥,计算StringToSign的签名。
- 构建Authorization头:将签名和其他必要信息添加到请求头中。
三、具体实现
以下是一个PHP示例代码,火山引擎API请求生成签名:
/**
*
* Author:刘星麟
* @param $ak Access Key ID
* @param $sk Secret Access Key
* @param $region 服务Region
* @param $service 服务名称
* @param $body 请求参数 没有给空
* @param $query 接口请求参数
* @param $method 请求方法 GET|POST
* @param $path 服务路径
* @param $headers 服务请求header 签名必要 https://www.volcengine.com/docs/6369/67268#_2-%E7%AD%BE%E5%90%8D%E5%8F%82%E6%95%B0
* @return mixed
*/
function signv4($ak, $sk, $region, $service, $body, $query, $method, $path, $headers)
{
if ($path === '') {
$path = '/';
}
$ldt = gmdate('Ymd\THis\Z');
$sdt = substr($ldt, 0, 8);
$headers['X-Date'] = $ldt;
$bodyHash = hash('sha256', $body);
$headers['X-Content-Sha256'] = $bodyHash;
$credentialScope = "$sdt/$region/$service/request";
$signedHeaders = [];
foreach ($headers as $key => $value) {
if ($key == "Host" || $key == "Content-Md5" || $key == "Content-Type" || substr($key, 0, 2) == "X-") {
$key = strtolower($key);
$signedHeaders[$key] = $value;
}
}
ksort($signedHeaders);
$signed_str = '';
foreach ($signedHeaders as $k => $v) {
$signed_str .= $k . ':' . $v . "\n";
}
$signedHeadersString = implode(';', array_keys($signedHeaders));
$canon = implode("\n", array($method, $path, $query, $signed_str, $signedHeadersString, $bodyHash));
$hash = hash('sha256', $canon);
$toSign = implode("\n", array("HMAC-SHA256", $ldt, $credentialScope, $hash));
$signingKey = getSigningKey($sdt, $region, $service, $sk);
$signature = hash_hmac('sha256', $toSign, $signingKey);
$credential = $ak . '/' . $credentialScope;
$headers['Authorization'] = "HMAC-SHA256 Credential={$credential}, SignedHeaders={$signedHeadersString}, Signature={$signature}";
return $headers;
}
function getSigningKey($date, $region, $service, $sk)
{
$dateKey = hash_hmac('sha256', $date, $sk, true);
$regionKey = hash_hmac('sha256', $region, $dateKey, true);
$serviceKey = hash_hmac('sha256', $service, $regionKey, true);
return hash_hmac('sha256', 'request', $serviceKey, true);
}
四:演示:获取余额
function curl_data($url, $header = [])
{
//初始化
$ch = curl_init();
// 请求头,可以传数组
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10); //最大相应超时时间
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 不从证书中检查SSL加密算法是否存在
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
$host = 'open.volcengineapi.com';
$service = 'billing'; // 服务名称
$region = 'cn-beijing'; // 区域
$version = '2022-01-01'; // API版本
$action = 'QueryBalanceAcct'; // 操作名称
$path = '/';
$method = 'GET';
$httpBody = ''; //请求的参数
$ak = 'AKLTM***************************TI';
$sk = 'TV*************************************bE9XVQ==';
//查询参数
$query = http_build_query([
'Action' => $action,
'Version' => $version
]);
$url = 'https://' . $host . $path . ($query ? "?{$query}" : ''); //组装请求的地址
//请求header
$headers = [
'Host' => $host
];
$headerArr = signv4($ak, $sk, $region, $service, $httpBody, $query, $method, $path, $headers);
$header = [];
foreach ($headerArr as $k => $v) {
$header[] = $k . ":" . $v;
}
$resString = curl_data($url, $header);
正常数据返回格式
{
"ResponseMetadata": {
"RequestId": "202308231151163C400BE8545DED89B87D",
"Action": "QueryBalanceAcct",
"Version": "2022-01-01",
"Service": "billing"
},
"Result": {
"AccountID": 210xxxxxxx,
"ArrearsBalance": "1.01",
"AvailableBalance": "77.01",
"CashBalance": "83.01",
"CreditLimit": "0.01",
"FreezeAmount": "5.01",
}
}
五、注意事项
- 时间戳:X-Date头必须使用UTC时间,并遵循ISO 8601标准格式。
- 请求头排序:参与签名的请求头必须按照ASCII码顺序排序。
- 密钥安全:SK是敏感信息,必须妥善保管,避免泄露。
- 签名算法:火山引擎目前仅支持HMAC-SHA256算法进行签名。
- $body:请求参数 没有一定要给空