调用第三方接口、模拟登录、抓取页面,cURL 都是 PHP 里最可靠的选择。把它封装成一个通用函数,让 GET、POST 表单、POST JSON 与失败重试共用一套逻辑,代码复用率会高很多。

实现思路

用 curl_init 创建句柄,按请求类型组装 CURLOPT 选项:POST 时若数据是数组则自动 http_build_query 转表单,若传字符串则按原始 body 发送并补上 JSON 请求头;循环内执行请求,失败且未超过重试次数时短暂休眠再试。

完整代码

<?php
/**
 * 通用 HTTP 请求:支持 GET / POST(表单) / POST(JSON),自动重试
 * 失败返回 false,调用方自行判断
 */
function httpRequest(string $url, string $method = "GET", $data = null, array $headers = [], int $retry = 2)
{
    $ch = curl_init();
    $options = [
        CURLOPT_URL            => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 15,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_SSL_VERIFYPEER => false,   // 本地调试用,生产建议配置 CA 证书
    ];

    if ($method === "POST") {
        $options[CURLOPT_POST] = true;
        if (is_array($data)) {
            $options[CURLOPT_POSTFIELDS] = http_build_query($data);
        } else {
            $options[CURLOPT_POSTFIELDS] = (string)$data;
            $headers[] = "Content-Type: application/json";
        }
    }

    if ($headers) {
        $options[CURLOPT_HTTPHEADER] = $headers;
    }

    for ($i = 0; $i <= $retry; $i++) {
        curl_setopt_array($ch, $options);
        $response = curl_exec($ch);
        if ($response !== false) {
            curl_close($ch);
            return $response;
        }
        usleep(300 * 1000);   // 300ms 后重试
    }

    curl_close($ch);
    return false;
}

// GET 示例
echo httpRequest("https://api.example.com/version");

// POST JSON 示例
$result = httpRequest(
    "https://api.example.com/login",
    "POST",
    json_encode(["name" => "admin", "pass" => "secret"], JSON_UNESCAPED_UNICODE),
    ["Content-Type: application/json"]
);
print_r(json_decode($result, true));
?>

使用建议

  • 带 Cookie 会话时把 CURLOPT_COOKIEJAR 与 CURLOPT_COOKIEFILE 指向同一文件,即可保持登录态;
  • 重试只对网络层失败生效,业务层返回错误码时需另做判断;
  • 生产环境应开启 SSL 校验并把证书路径配到 CURLOPT_CAINFO,避免中间人风险。

小结

把超时、跟随跳转、失败重试统一收敛后,业务代码只需一行调用,是接入支付、短信、AI 接口时的标准做法。