Laravel HTTP 客户端实战:用 Guzzle 调第三方接口,超时、重试与中间件一把抓

test12026-10-051 次阅读

为什么用 HTTP Facade

调用支付、物流、开放平台等第三方接口时,直接用 curl 或裸 Guzzle 写起来啰嗦,错误处理也散。Laravel 的 Illuminate\Support\Facades\Http 在 Guzzle 之上包了一层流畅的 API,超时、重试、请求头、异常处理都能链式表达,还能用 macro 把某个合作方的通用配置固化下来。

一次带超时与重试的调用

timeout 控制整体耗时,retry(次数, 间隔毫秒) 在连接失败或 5xx 时自动重放;throw:false 表示不要抛异常,由我们手动判断成败,便于写补偿逻辑。

use Illuminate\Support\Facades\Http;

$response = Http::withHeaders(['Authorization' => "Bearer {$token}"])
    ->timeout(5)
    ->retry(3, 200, throw: false)
    ->get('https://api.partner.com/orders', ['status' => 'paid']);

if ($response->failed()) {
    report(new \Exception('第三方订单同步失败: ' . $response->body()));
    return;
}

foreach ($response->json('data') as $order) {
    OrderSync::updateOrCreate(['no' => $order['no']], $order);
}

用 middleware 做退避重试

HTTP::macro 能封装一整个合作方的通用配置。下面用 Illuminate\Http\Client\Middleware::retry 实现指数退避:只在连接异常时重试,并随次数延长等待。

use Illuminate\Http\Client\Middleware;
use Illuminate\Support\Facades\Http;

Http::macro('partner', function () {
    return Http::withMiddleware(
        Middleware::retry(
            retryDecider: fn ($response, $e) => $e instanceof \Illuminate\Http\Client\ConnectionException,
            sleepMilliseconds: fn ($attempt) => 200 * $attempt
        )
    )
    ->withHeaders(['Accept' => 'application/json'])
    ->timeout(5);
});

// 使用
$res = Http::partner()->get('https://api.partner.com/orders');

统一加签名与日志

需要给每个请求加时间戳签名,或记录耗时,也可以用 push 中间件插入闭包。下面在请求前注入签名头,响应后打到日志。

Http::macro('signed', function () {
    return Http::withMiddleware(
        Middleware::mapRequest(function ($request) {
            $ts = time();
            $sign = hash_hmac('sha256', (string) $ts, config('services.partner.secret'));
            return $request->withHeader('X-Timestamp', $ts)
                           ->withHeader('X-Sign', $sign);
        })
    );
});

三个注意点

  • retry 默认对 5xx 和连接异常重放,对 4xx(如 401/403)不会重试,那是配置或鉴权问题。
  • macro 定义放在服务提供者的 boot 里或单独的 ServiceProvider,避免每次请求重复注册。
  • throw:true 适合"调用失败即视为业务失败"的场景,配合 report 与事务回滚更稳;能自愈的瞬时错误再交给 retry。
T

test1

文章作者

为什么用 HTTP Facade 调用支付、物流、开放平台等第三方接口时,直接用 curl 或裸 Guzzle 写起来...

分类
技术
发布时间
2026-10-05
字数
约 2034 字
阅读
1 次