📞 09318539889 📧 yxp@gansuwangzhan.cn

带签名认证的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;
}