带签名认证的API请求方法
作者:杨锦龙时间:2026-05-28点击量:0次
/**
* 带签名认证的API请求方法
* @param string $url 请求URL
* @param string $appId 分配的应用ID
* @param string $secret 分配的密钥
* @return array|null
*/
public function getJson($url, $appId = '', $secret = '', $data = '')
{
// 1. 生成签名参数(使用(int)确保毫秒时间戳为纯整数字符串)
$timestamp = (string)((int)(microtime(true) * 1000));
$nonce = md5(uniqid(mt_rand(), true));
// 2. 计算签名
$raw = $appId . $timestamp . $nonce . $secret;
$sign = strtolower(md5($raw));
// 3. 构建请求头
$headers = [
'X-AppId: ' . $appId,
'X-Timestamp: ' . $timestamp,
'X-Nonce: ' . $nonce,
'X-Sign: ' . $sign,
];
// 4. 初始化 cURL
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_CONNECTTIMEOUT => 10, // 新增:连接超时,防止DNS卡死
CURLOPT_HTTPHEADER => $headers,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
]);
if (!empty($data)) {
curl_setopt($ch, CURLOPT_POST, true);
// 如果data是数组且需要JSON发送,或已经是JSON字符串
if (is_array($data)) {
$jsonData = json_encode($data, JSON_UNESCAPED_UNICODE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
$headers[] = 'Content-Type: application/json; charset=utf-8';
} else {
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
// 若传入的是已编码的form字符串,按需添加:
// $headers[] = 'Content-Type: application/x-www-form-urlencoded';
}
// 重新设置header(因为可能追加了Content-Type)
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$output = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr = curl_error($ch); // 新增:捕获cURL底层错误
curl_close($ch);
if ($output === false || !empty($curlErr)) {
trace('API请求失败[cURL]: ' . $curlErr, 'error');
return null;
}
if ($httpCode === 401) {
$error = json_decode($output, true);
trace('API签名校验失败: ' . ($error['msg'] ?? $output), 'error');
return null;
}
if ($httpCode >= 400) {
trace("API请求异常[HTTP {$httpCode}]: " . mb_substr($output, 0, 500), 'error');
return null;
}
//dump($output);
$result = json_decode($output, true);
return $result;
}