Php curl error 60 ssl certificate problem unable to get local issuer certificate

I am trying to send an API request using Stripe but get the error message: cURL error 60: SSL certificate problem: unable to get local issuer certificate This is the code I am running: public fun...

For WAMP, this is what finally worked for me.
While it is similar to others, the solutions mentioned on this page, and other locations on the web did not work. Some «minor» detail differed.
Either the location to save the PEM file mattered, but was not specified clearly enough.
Or WHICH php.ini file to be edited was incorrect. Or both.
I’m running a 2020 installation of WAMP 3.2.0 on a Windows 10 machine.

Link to get the pem file:

http://curl.haxx.se/ca/cacert.pem
Copy the entire page and save it as: cacert.pem, in the location mentioned below.

Save the PEM file in this location

<wamp install directory>binphpphp<version>extrasssl
eg saved file and path: «T:wamp64binphpphp7.3.12extrassslcacert.pem»

*(I had originally saved it elsewhere (and indicated the saved location in the php.ini file, but that did not work).
There might, or might not be, other locations also work. This was the recommended location — I do not know why.)

WHERE
<wamp install directory> = path to your WAMP installation.
eg: T:wamp64

<php version> of php that WAMP is running: (to find out, goto: WAMP icon tray -> PHP <version number>
if the version number shown is 7.3.12, then the directory would be: php7.3.12)
eg: php7.3.12

Which php.ini file to edit

To open the proper php.ini file for editing, goto: WAMP icon tray -> PHP -> php.ini.
eg: T:wamp64binapacheapache2.4.41binphp.ini
NOTE: it is NOT the file in the php directory!

Update:
While it looked like I was editing the file: T:wamp64binapacheapache2.4.41binphp.ini,
it was actually editing that file’s symlink target: T:/wamp64/bin/php/php7.3.12/phpForApache.ini.

Note that if you follow the above directions, you are NOT editing a php.ini file directly. You are actually editing a phpForApache.ini file. (a post with info about symlinks)

If you read the comments at the top of some of the php.ini files in various WAMP directories, it specifically states to NOT EDIT that particular file.
Make sure that the file you do open for editing does not include this warning.

Installing the extension Link Shell Extension allowed me to see the target of the symlink in the file Properites window, via an added tab. here is an SO answer of mine with more info about this extension.

If you run various versions of php at various times, you may need to save the PEM file in each relevant php directory.

The edits to make in your php.ini file:

Paste the path to your PEM file in the following locations.

  • uncomment ;curl.cainfo = and paste in the path to your PEM file.
    eg: curl.cainfo = "T:wamp64binphpphp7.3.12extrassslcacert.pem"

  • uncomment ;openssl.cafile= and paste in the path to your PEM file.
    eg: openssl.cafile="T:wamp64binphpphp7.3.12extrassslcacert.pem"

Credits:

While not an official resource, here is a link back to the YouTube video that got the last of the details straightened out for me: https://www.youtube.com/watch?v=Fn1V4yQNgLs.

If you are using PHP’s cURL functions to connect to an HTTPS URL, then you might come across the following error:

SSL certificate problem: unable to get local issuer certificate.  (cURL error code 60)

This is a common error that occurs whenever you attempt to use cURL functions to connect to an HTTPS website.

In plain English, it means that you have not configured cURL to connect to SSL-enabled websites.

The quick fix.

If you do not care about security and are looking for a quick fix, then you can simply disable the following cURL options:

  • CURLOPT_SSL_VERIFYHOST: This option tells cURL that it must verify the host name in the server cert.
  • CURLOPT_SSL_VERIFYPEER: This option tells cURL to verify the authenticity of the SSL cert on the server.

Disabling these two options disables SSL verification.

To disable these two options, you can use the curl_setopt function like so:

//The URL we are connecting to.
$url = 'https://google.com';

//Initiate cURL.
$ch = curl_init($url);

//Disable CURLOPT_SSL_VERIFYHOST and CURLOPT_SSL_VERIFYPEER by
//setting them to false.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

//Execute the request.
curl_exec($ch);

//Check for errors.
if(curl_errno($ch)){
    throw new Exception(curl_error($ch));
}

The PHP code above essentially tells cURL that we don’t care if the server has a valid SSL cert or not. We want to connect to it anyway.

The problem with this method is that it is insecure and it leaves you open to man-in-the-middle attacks. Simply put, this means that an attacker could potentially intercept the data that you are sending in your cURL requests.

Using a cert with PHP’s cURL functions.

To use a certificate with PHP’s cURL functions, you can download the cacert.pem certificate bundle from the official cURL website.

Once you have downloaded the cacert.pem file, you should move it to whatever directory makes the most sense for you and your setup.

For example, on Windows, I moved my bundle to C:wampcacert.pem

Then, you can simply tell cURL where your certificate bundle is located by using the curl_setopt function:

//Tell cURL where our certificate bundle is located.
$certificate = "C:wampcacert.pem";
curl_setopt($ch, CURLOPT_CAINFO, $certificate);
curl_setopt($ch, CURLOPT_CAPATH, $certificate);

This allows us to make a secure request to the server and prevent any man-in-the-middle attacks.

Adding the cert to your php.ini file.

If you don’t like the thought of having to specify the location of the certificate bundle in your PHP code, then you can add its path information to your php.ini file like so:

curl.cainfo="C:wampcacert.pem" 
openssl.cafile="C:wampcacert.pem"

Once you add the above lines to your php.ini file, make sure that you reload the web server / PHP process so that the changes take effect.

Enabling mod_ssl and php_openssl.dll.

If you are using Apache and PHP on Windows, then you might need to enable both mod_ssl and php_openssl.dll.

To enable mod_ssl, you can add the following to your Apache configuration file:

LoadModule ssl_module /usr/lib/httpd/modules/mod_ssl.so

The configuration line above presumes that a file called mod_ssl.so exists in a Linux directory called “/usr/lib/httpd/modules/”.

On Windows, this directory might be something like “C:wampbinapacheapache2.4.9modules“.

You will need to change this line to match your own Apache setup.

To enable php_openssl.dll, you will need to uncomment the following line in your php.ini file:

extension=php_openssl.dll

As always, you should test your configurations and then reload your server for any changes to take effect.

Hi, I am getting the SSL exception while uploading file to S3 , Strange thing is i have specified the certificate in the config/filesystems.php in s3 block but it still gives this error.
I tried uploading file to s3 using Curl command line it works fine with the cacerts which i am providing in the filesystem.

Any help will be greatly appreciated, I am not able to pin point the issue as curl command line able to upload file to s3.

Below is Stack Trace

GuzzleHttpExceptionRequestException: cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) in /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php:187
Stack trace:
#0 /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(150): GuzzleHttpHandlerCurlFactory::createRejection(Object(GuzzleHttpHandlerEasyHandle), Array)
#1 /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php(103): GuzzleHttpHandlerCurlFactory::finishError(Object(GuzzleHttpHandlerCurlMultiHandler), Object(GuzzleHttpHandlerEasyHandle), Object(GuzzleHttpHandlerCurlFactory))
#2 /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(179): GuzzleHttpHandlerCurlFactory::finish(Object(GuzzleHttpHandlerCurlMultiHandler), Object(GuzzleHttpHandlerEasyHandle), Object(GuzzleHttpHandlerCurlFactory))
#3 /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(108): GuzzleHttpHandlerCurlMultiHandler->processMessages()
#4 /var/www/laravel/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php(123): GuzzleHttpHandlerCurlMultiHandler->tick()
#5 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(246): GuzzleHttpHandlerCurlMultiHandler->execute(true)
#6 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(223): GuzzleHttpPromisePromise->invokeWaitFn()
#7 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(267): GuzzleHttpPromisePromise->waitIfPending()
#8 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(225): GuzzleHttpPromisePromise->invokeWaitList()
#9 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(267): GuzzleHttpPromisePromise->waitIfPending()
#10 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(225): GuzzleHttpPromisePromise->invokeWaitList()
#11 /var/www/laravel/vendor/guzzlehttp/promises/src/Promise.php(62): GuzzleHttpPromisePromise->waitIfPending()
#12 /var/www/laravel/vendor/aws/aws-sdk-php/src/S3/S3ClientTrait.php(33): GuzzleHttpPromisePromise->wait()
#13 /var/www/laravel/vendor/league/flysystem-aws-s3-v3/src/AwsS3Adapter.php(583): AwsS3S3Client->upload(‘elevatecds’, ‘4/mampleInitial…’, Resource id #8, ‘private’, Array)
#14 /var/www/laravel/vendor/league/flysystem-aws-s3-v3/src/AwsS3Adapter.php(368): LeagueFlysystemAwsS3v3AwsS3Adapter->upload(‘4/mampleInitial…’, Resource id #8, Object(LeagueFlysystemConfig))
#15 /var/www/laravel/vendor/league/flysystem/src/Filesystem.php(122): LeagueFlysystemAwsS3v3AwsS3Adapter->writeStream(‘4/mampleInitial…’, Resource id #8, Object(LeagueFlysystemConfig))
#16 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php(132): LeagueFlysystemFilesystem->putStream(‘4/mampleInitial…’, Resource id #8, Object(LeagueFlysystemConfig))
#17 /var/www/laravel/app/Http/Controllers/WorkspacesController.php(621): IlluminateFilesystemFilesystemAdapter->put(‘4/mampleInitial…’, Resource id #8, Array)
#18 [internal function]: AppHttpControllersWorkspacesController->uploadFile(Object(IlluminateHttpRequest))
#19 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Controller.php(55): call_user_func_array(Array, Array)
#20 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(44): IlluminateRoutingController->callAction(‘uploadFile’, Array)
#21 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Route.php(203): IlluminateRoutingControllerDispatcher->dispatch(Object(IlluminateRoutingRoute), Object(AppHttpControllersWorkspacesController), ‘uploadFile’)
#22 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Route.php(160): IlluminateRoutingRoute->runController()
#23 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(572): IlluminateRoutingRoute->run()
#24 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): IlluminateRoutingRouter->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#25 /var/www/laravel/app/Http/Middleware/Authenticate.php(27): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#26 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): AppHttpMiddlewareAuthenticate->handle(Object(IlluminateHttpRequest), Object(Closure))
#27 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#28 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php(65): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#29 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateFoundationHttpMiddlewareVerifyCsrfToken->handle(Object(IlluminateHttpRequest), Object(Closure))
#30 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#31 /var/www/laravel/vendor/laravel/framework/src/Illuminate/View/Middleware/ShareErrorsFromSession.php(49): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#32 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateViewMiddlewareShareErrorsFromSession->handle(Object(IlluminateHttpRequest), Object(Closure))
#33 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#34 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php(64): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#35 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateSessionMiddlewareStartSession->handle(Object(IlluminateHttpRequest), Object(Closure))
#36 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#37 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php(37): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#38 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateCookieMiddlewareAddQueuedCookiesToResponse->handle(Object(IlluminateHttpRequest), Object(Closure))
#39 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#40 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php(59): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#41 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateCookieMiddlewareEncryptCookies->handle(Object(IlluminateHttpRequest), Object(Closure))
#42 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#43 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(102): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#44 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(574): IlluminatePipelinePipeline->then(Object(Closure))
#45 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(533): IlluminateRoutingRouter->runRouteWithinStack(Object(IlluminateRoutingRoute), Object(IlluminateHttpRequest))
#46 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php(511): IlluminateRoutingRouter->dispatchToRoute(Object(IlluminateHttpRequest))
#47 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): IlluminateRoutingRouter->dispatch(Object(IlluminateHttpRequest))
#48 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): IlluminateFoundationHttpKernel->IlluminateFoundationHttp{closure}(Object(IlluminateHttpRequest))
#49 /var/www/laravel/vendor/barryvdh/laravel-debugbar/src/Middleware/Debugbar.php(51): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#50 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): BarryvdhDebugbarMiddlewareDebugbar->handle(Object(IlluminateHttpRequest), Object(Closure))
#51 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#52 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(46): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#53 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): IlluminateFoundationHttpMiddlewareCheckForMaintenanceMode->handle(Object(IlluminateHttpRequest), Object(Closure))
#54 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): IlluminatePipelinePipeline->IlluminatePipeline{closure}(Object(IlluminateHttpRequest))
#55 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(102): IlluminateRoutingPipeline->IlluminateRouting{closure}(Object(IlluminateHttpRequest))
#56 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(151): IlluminatePipelinePipeline->then(Object(Closure))
#57 /var/www/laravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(116): IlluminateFoundationHttpKernel->sendRequestThroughRouter(Object(IlluminateHttpRequest))
#58 /var/www/laravel/public/index.php(53): IlluminateFoundationHttpKernel->handle(Object(IlluminateHttpRequest))
#59 {main}

Home » cURL error 60: SSL certificate problem: unable to get local issuer certificate

Last updated on June 17, 2022 by

Often, cURL error 60: SSL certificate problem: unable to get local issuer certificate error occurs when we try to call the API with the secure https:// protocol in the request URL. In this article, we will discuss why does this error occur? how to resolve: unable to get local issuer certificate error occurs? Let’s jump into it.

Why Does This Error Occur?

Just go to your API call code and try to run the request URL with only http:// protocol. You can’t see the error anymore because secure API calls require an SSL certificate.

This error occurs because the API call makes a secure connection request using the self-signed certificate. When it does not find a valid certificate, it throws an error.

It has a very very simple solution. We just need to download the certificate and set the path. Are you ready? Then let’s set up an SSL certificate step by step as below:

How To Resolve: unable to get local issuer certificate error?

  1. Download the “cacert.pem” free certificate file from the official website here: http://curl.haxx.se/docs/caextract.html
  2. Move the cacert.pem file in a reachable destination for the PHP. It is advisable to move the file for the WAMP user to C:wamp64binphpcacert.pem, for XAMPP user to C:xamppphpextrassslcacert.pem, for the AMPPS user to C:Program Files (x86)Amppsphpextrassslcacert.pem
  3. Now, open your php.ini file and find the “curl.cainfo” option. You will see something like the following:
  1. After that, we need to add the path of the certificate to “curl.cainfo” and remove semicolon(;) as follow:
curl.cainfo = "C:wamp64binphpcacert.pem"
  1. The very very most important step is to save and close your php.ini. Restart your web server and try your request again. If you do not set the right path, then you will experience a CURL 77 error.

Hurray! we have completed all steps to solve unable to get local issuer certificate error.

Additionally, read our guide:

  1. Specified Key Was Too Long Error In Laravel
  2. Run PHP Artisan Commands On Shared Hosting Servers
  3. How To Calculate Age From Birthdate
  4. Active Directory Using LDAP in PHP or Laravel
  5. How To Use The Laravel Soft Delete
  6. How To Add Laravel Next Prev Pagination
  7. Best Way to Remove Public from URL in Laravel
  8. Difference Between Factory And Seeders In Laravel
  9. Difference Between Events and Observers In Laravel
  10. Session Not Working In Laravel
  11. How To Install Vue In Laravel 8 Step By Step
  12. How To Handle Failed Jobs In Laravel
  13. Best Ways To Define Global Variable In Laravel
  14. How To Get Latest Records In Laravel
  15. Laravel Twilio Send SMS Tutorial With Example
  16. How To Pass Laravel URL Parameter
  17. Laravel 9 Resource Controller And Route With Example
  18. Laravel 9 File Upload Tutorial With Example
  19. How To Schedule Tasks In Laravel With Example
  20. Laravel Collection Push() And Put() With Example

That’s it from our end. We hope this article helped you to resolve cURL error 60: SSL certificate problem: unable to get local issuer certificate error.

Please let us know in the comments if everything worked as expected, your issues, or any questions. If you think this article saved your time & money, please do comment, share, like & subscribe. Thank you for reading this post. 🙂 Keep Smiling! Happy Coding!

Понравилась статья? Поделить с друзьями:
  • Php curl 500 error
  • Phpstorm как изменить размер шрифта
  • Php curl 400 error
  • Phpstorm git error
  • Philips hd9020 ошибка eee