Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

eb's avatar
Level 7

Guzzle request fails when executed inside Job. cURL error 60: SSL certificate problem

Hi All

I have a strange problem. My Guzzle requests to an external server runs successfully when I test it using a Closure in my routes/web.php file (see below).

However, the same request fails with the following error when I make a request inside the handle() method of my Job:

[2019-02-26 20:02:50] local.DEBUG: GuzzleHttp\Exception\RequestException: cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) in ~/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:186

Here's the code in my Closure in my web.php file:

Route::get('guzzle-test', function () {

    $file_id  = 23;
    $base_uri = env('API_URL');
    $token    = env('PERSONAL_ACCESS_TOKEN');
    $client   = new GuzzleHttp\Client(['base_uri' => $base_uri]);

    try {
        $response = $client->get("files/{$file_id}", [
            'headers' => [
                "Authorization"   => "Bearer {$token}",
                "Accept-Encoding" => "application/json",
                "Content-Type"    => "application/json",
                "cache-control"   => "no-cache",
            ],
        ]);
    } catch (GuzzleHttp\Exception\GuzzleException $exception) {
        dump($exception);
    }

    return json_decode($response->getBody(), true);
});

And here's the code inside my Job's handle() method (notice I did add a "verify" param to my request):

class MyJob implements ShouldQueue
{
    // ... other code
   
    public function handle()
    {
        $file_id  = $this->file->download_file_id;
        $base_uri = env('API_URL');
        $token    = env('PERSONAL_ACCESS_TOKEN');
        $client   = new GuzzleHttp\Client(['base_uri' => $base_uri]);

        try {
            $response = $client->get("files/{$file_id}", [
                'verify'  => base_path('resources/assets/cacert.pem'), // This doesn't work either.
                'headers' => [
                    "Authorization"   => "Bearer {$token}",
                    "Accept-Encoding" => "application/json",
                    "Content-Type"    => "application/json",
                    "cache-control"   => "no-cache",
                ],
            ]);
        } catch (GuzzleHttp\Exception\GuzzleException $exception) {
            dump($exception);
        }

        return json_decode($response->getBody(), true);
    }
}

Any ideas how to get this to work in my Job?

Thanks Eric

0 likes
3 replies
jvahldick's avatar

Hi Eric,

Can you double check whether you are using the same version and libraries of PHP in the web server and in the php cli?

Especially on macOs, they usually install or change your PHP installation in some update or so, and then you are not sure what is the correct version your cli is using anymore unless you check it all the time.

If they are ok, it might be some kind of issue that I saw a lot some time ago, especially on Windows, in which there was a bug with the ca certificate. That could be solved by downloading the latest version: https://curl.haxx.se/ca/cacert.pem

Then add the path into curl.cainfo variable in the php.ini:

curl.cainfo=your-ca-certificate-path
1 like
eb's avatar
Level 7

@JVAHLDICK - I am running this site on Valet.

But I think the issue is related to the wrong cert being referenced.

When I run dump( openssl_get_cert_locations() ); in my routes/web.php file, I get this:

array:8 [
  "default_cert_file" => "/usr/local/etc/openssl/cert.pem"
  "default_cert_file_env" => "SSL_CERT_FILE"
  "default_cert_dir" => "/usr/local/etc/openssl/certs"
  "default_cert_dir_env" => "SSL_CERT_DIR"
  "default_private_dir" => "/usr/local/etc/openssl/private"
  "default_default_cert_area" => "/usr/local/etc/openssl"
  "ini_cafile" => ""
  "ini_capath" => ""
]

However, when I run that same command inside the handle() method of my Job, I get this:

array:8 [
  "default_cert_file" => "/Applications/MAMP/Library/OpenSSL/cert.pem"
  "default_cert_file_env" => "SSL_CERT_FILE"
  "default_cert_dir" => "/Applications/MAMP/Library/OpenSSL/certs"
  "default_cert_dir_env" => "SSL_CERT_DIR"
  "default_private_dir" => "/Applications/MAMP/Library/OpenSSL/private"
  "default_default_cert_area" => "/Applications/MAMP/Library/OpenSSL"
  "ini_cafile" => ""
  "ini_capath" => ""
]

Obviously it's picking up the cert in my MAMP app (which isn't currently running).

For now, I have implemented a workaround which checks the "ENV" and verifies only if not in "local".

$response = $client->get( "files/{$file_id}", [
    'verify'  => ( env( 'APP_ENV' ) === 'local' ) ? false : true,
    'headers' => [
        "Authorization"   => "Bearer {$token}",
        "Accept-Encoding" => "application/json",
        "Content-Type"    => "application/json",
        "cache-control"   => "no-cache",
    ],
] );

Do you think this cert issue will go away once both the client and API server are running on Forge?

commodoretim's avatar

This thread, especially the advice to check dump( openssl_get_cert_locations() ); provided helpful clues when researching trouble with in my dev environment. Thank you!

Though my situation is slightly different than the original question, I'll share what I learned to help others. I'm running Laragon 5.0.0 for development within Windows. I was receiving a similar error about not being able to verify the server's certificate (forgot the exact error message now).

The solution is to download the latest certificate authority bundle from https://curl.haxx.se/ca/cacert.pem and place that into the C:\laragon\etc\ssl folder, replacing the existing old CA bundle. Should work for both the Apache web server and the PHP CLI provided by Laragon (only tested the CLI so far).

Please or to participate in this conversation.