I use WAMP on a local development environment and am trying to charge a credit card but get the error message:

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

I searched a lot on Google and lots of people are suggesting that I download this file: cacert.pem, put it somewhere and reference it in my php.ini. This is the part in my php.ini:

curl.cainfo = "C:\Windows\cacert.pem"

Yet, even after restarting my server several times and changing the path, I get the same error message.

I use WAMP from the Apache Modules and have the ssl_module enabled. And from the PGP extensions I have php_curl enabled.

Still the same error message. Why is that happening?

Now I am following this fix: How to fix PHP CURL Error 60 SSL

Which suggests that I add these lines to my cURL options:

curl_setopt($process, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
curl_setopt($process, CURLOPT_SSL_VERIFYPEER, true);

Where do I add options to my cURL? Apparently not through the command line, since my CLI doesn't find the command "curl_setopt"

EDIT

This is the code I am running:

public function chargeStripe()
{
    $stripe = new Stripe;
    $stripe = Stripe::make(env('STRIPE_PUBLIC_KEY'));

    $charge = $stripe->charges()->create([
        'amount'   => 2900,
        'customer' => Input::get('stripeEmail'),
        'currency' => 'EUR',
    ]);

    dd($charge);

    // echo $charge[Input::get('stripeToken')];


    return Redirect::route('step1');
}
upvote
  flag
Assuming there are no issues with your code, it could be your firewall. Try disabling your firewall to test. – Waqar ul islam
upvote
  flag
did't I gave you answer to this question here? :) – Limon Monte
upvote
  flag
@limonte possible, had to switch projects and have probably the same problem with the new project. Will switch back to the guzzle problem and maybe it is the same fix. brb – LoveAndHappiness
upvote
  flag
@Waqarulislam firewall always down – LoveAndHappiness
upvote
  flag
I don't get it, do you have cURL in a PHP script, as in curl_init() etc, or are you running curl from the command line. It doesn't really help to change the PHP settings if you're not using PHP cURL, and those two lines at the bottom of the question are settings for PHP cURL. – adeneo
1 upvote
  flag
Have you tried the latest version of stripe? I see a commit message that changed something to do with certs... github.com/stripe/stripe-php/commit/… – thelastshadow
1 upvote
  flag
@LoveAndHappiness have you got the solution for this problem? I am facing the same error with stripe. Please let me know if you have any solution. – Dev
upvote
  flag
@thelastshadow That's a different stripe library than the one OP is using :) – Ja͢ck
upvote
  flag
This solved the issue for me: //allinonescript.com/a/32095378/178163 – George Kagan

11 Answers 11

As you are using Windows, I think your path separator is '\' (and '/' on Linux). Try using the constant DIRECTORY_SEPARATOR. Your code will be more portable.

Try:

curl_setopt($process, CURLOPT_CAINFO, dirname(__FILE__) . DIRECTORY_SEPARATOR . 'cacert.pem');

EDIT: and write the full path. I had some issues with relative paths (perhaps curl is executed from another base directory?)

upvote
  flag
This wouldn't make a difference, because the actual cURL settings are out of your control when you use that particular Stripe library. – Ja͢ck

Have you tried..

curl_setopt($process, CURLOPT_SSL_VERIFYPEER, false);

If you are consuming a trusted source arguably you dont need to verify the SSL cert.

Guzzle, which is used by cartalyst/stripe, will do the following to find a proper certificate archive to check a server certificate against:

  1. Check if openssl.cafile is set in your php.ini file.
  2. Check if curl.cainfo is set in your php.ini file.
  3. Check if /etc/pki/tls/certs/ca-bundle.crt exists (Red Hat, CentOS, Fedora; provided by the ca-certificates package)
  4. Check if /etc/ssl/certs/ca-certificates.crt exists (Ubuntu, Debian; provided by the ca-certificates package)
  5. Check if /usr/local/share/certs/ca-root-nss.crt exists (FreeBSD; provided by the ca_root_nss package)
  6. Check if /usr/local/etc/openssl/cert.pem (OS X; provided by homebrew)
  7. Check if C:\windows\system32\curl-ca-bundle.crt exists (Windows)
  8. Check if C:\windows\curl-ca-bundle.crt exists (Windows)

You will want to make sure that the values for the first two settings are properly defined by doing a simple test:

echo "openssl.cafile: ", ini_get('openssl.cafile'), "\n";
echo "curl.cainfo: ", ini_get('curl.cainfo'), "\n";

Alternatively, try to write the file into the locations indicated by #7 or #8.

I found a solution that worked for me. I downgraded from the latest guzzle to version ~4.0 and it worked.

In composer.json add "guzzlehttp/guzzle": "~4.0"

Hope it helps someone

upvote
  flag
That will also prevent you using any version 5/6 features. Instead just set verify to false in a param array (3rd param of request method): $client->request('GET', '/', ['verify' => false]); – Sam

If you are using PHP 5.6 with Guzzle, Guzzle has switched to using the PHP libraries autodetect for certificates rather than it's process (ref). PHP outlines the changes here.

Finding out Where PHP/Guzzle is Looking for Certificates

You can to dump where PHP is looking using:

 var_dump(openssl_get_cert_locations());

Getting a Certificate Bundle

For OS X testing, you can use homebrew to install openssl brew install openssl and then use openssl.cafile=/usr/local/etc/openssl/cert.pem in your php.ini or Zend Server settings (under OpenSSL).

A certificate bundle is also available from curl/Mozilla on the curl website: https://curl.haxx.se/docs/caextract.html

Telling PHP Where the Certificates Are

Once you have a bundle, either place it where PHP is already looking (which you found out above) or update openssl.cafile in php.ini. (Generally, /etc/php.ini or /etc/php/7.0/cli/php.ini or /etc/php/php.ini on Unix.)

2 upvote
  flag
YES. After seeing too many people suggest the obviously wrong approach of downgrading by multiple version numbers, this stands as the correct approach imho. I had followed others' advice about the cafile but didn't have a means of testing why it still didn't load. This openssl_get_cert_locations() function really did the job in identifying my problem. Thanks! – Web and Flow
up vote 308 down vote accepted

working solution:

  • Assuming On windows

XAMPP server

similar for other environment - download and extract for cacert.pem here (a clean file format/data)

https://curl.haxx.se/docs/caextract.html

  • put it here

C:\xampp\php\extras\ssl\cacert.pem

  • in your php.ini put this line in this section ("c:\xampp\php\php.ini"):
;;;;;;;;;;;;;;;;;;;;
; php.ini Options  ;
;;;;;;;;;;;;;;;;;;;;

curl.cainfo = "C:\xampp\php\extras\ssl\cacert.pem"
  • restart your webserver/apache

Problem solved!

(source: https://laracasts.com/discuss/channels/general-discussion/curl-error-60-ssl-certificate-problem-unable-to-get-local-issuer-certificate)

1 upvote
  flag
Thanks a lot @Dung This is working fine – UWU_SANDUN
3 upvote
  flag
This message is coming because of your PHP version. If it is upper from PHP 5.5 then coming this error because of PHP 5.6 new feature. PHP 5.6 check certificates if you are using cURL. – UWU_SANDUN
6 upvote
  flag
Thanks for the answer! Although I would recommend using the cacert.pem from the official curl-page: curl.haxx.se/docs/caextract.html – dieBeiden
upvote
  flag
This should be a perfect answer........ – Shanka SMS
1 upvote
  flag
hell yeah!!! :) works. – Kabkee
upvote
  flag
This works. Thanks so much. Cheers! – Anjana Silva
upvote
  flag
i love this kind of an answer, thanks! – messerbill
upvote
  flag
Works as a charm!! Wish I can double up vote. Thanks again :) – Anjana Silva
upvote
  flag
thank you ...great guy you are – lalithkumar
upvote
  flag
you, sir, deserves a medal. thanks for that answer – Pierre Le Bot
upvote
  flag
it Worked for me. – Oussaki
upvote
  flag
worked perfectly :) – Frank
upvote
  flag
Just wanted to point out for anyone that can't get this to work - I used forward slashes curl.cainfo = "C:/cacert.pem" and also had to restart my computer in order to get it to work. Just restarting the web server was not enough. Hopefully that helps :] – space_food_

I had this problem appear out-of-the-blue one day, when a Guzzle(5) script was attempting to connect to a host over SSL. Sure, I could disable the VERIFY option in Guzzle/Curl, but that's clearly not the correct way to go.

I tried everything listed here and in similar threads, then eventually went to terminal with openssl to test against the domain with which I was trying to connect:

openssl s_client -connect example.com:443 

... and received first few lines indicating:

CONNECTED(00000003)
depth=0 CN = example.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = example.com
verify error:num=21:unable to verify the first certificate
verify return:1 

... while everything worked fine when trying other destinations (ie: google.com, etc)

This prompted me to contact the domain I had been trying to connect to, and indeed, they had a problem on THEIR END that had crept up. It was resolved and my script went back to working.

So... if you're pulling your hair out, give openssl a shot and see if there's anything up with the response from the location you are attempting to connect. Maybe the issue isn't so 'local' after all sometimes.

If you're unable to change php.ini you could also point to the cacert.pem file from code like this:

$http = new GuzzleHttp\Client(['verify' => '/path/to/cacert.pem']);
$client = new Google_Client();
$client->setHttpClient($http);
upvote
  flag
Thanks. Your a life saver :) – robertmylne
upvote
  flag
This is cool it works !!! – Vinod Kumar
upvote
  flag
This answer only works for me. – Sithu

What i did was use var_dump(openssl_get_cert_locations()); die; in any php script, which gave me the information about defaults that my local php was using:

array (size=8)
  'default_cert_file' => string 'c:/openssl-1.0.1c/ssl/cert.pem' (length=30)
  'default_cert_file_env' => string 'SSL_CERT_FILE' (length=13)
  'default_cert_dir' => string 'c:/openssl-1.0.1c/ssl/certs' (length=27)
  'default_cert_dir_env' => string 'SSL_CERT_DIR' (length=12)
  'default_private_dir' => string 'c:/openssl-1.0.1c/ssl/private' (length=29)
  'default_default_cert_area' => string 'c:/openssl-1.0.1c/ssl' (length=21)
  'ini_cafile' => string 'E:\xampp\php\extras\ssl\cacert.pem' (length=34)
  'ini_capath' => string '' (length=0)

As you can notice, i have set the ini_cafile or the ini option curl.cainfo. But in my case, curl would try to use the "default_cert_file" which did not exist.

I copied the file from https://curl.haxx.se/ca/cacert.pem into the location for "default_cert_file" (c:/openssl-1.0.1c/ssl/cert.pem) and i was able to get it to work.

This was the only solution for me.

upvote
  flag
I have similar problem and my location is something like c:/usr/local/ssl/cert.pem but this location does not exists, do you what what it could be, further the same project is used by my coluge on mac machine could that be reason, I have tried everything else, that is adding cert location in .ini file but it doesn't work, it looks like your solution should work as it makes sense but can't change that location and can't put certificate in location which doesn't exists. – AbdulMueed
upvote
  flag
You can try an create the folders and put certificate at your specified path? – George Donev

Be sure that you open the php.ini file directly by your Window Explorer. (in my case: C:\DevPrograms\wamp64\bin\php\php5.6.25).

Don't use the shortcut to php.ini in the Wamp/Xamp icon's menu in the System Tray. This shortcut doesn't work in this case.

Then edit that php.ini :

curl.cainfo ="C:/DevPrograms/wamp64/bin/php/cacert.pem" 

and

openssl.cafile="C:/DevPrograms/wamp64/bin/php/cacert.pem"

After saving php.ini you don't need to "Restart All Services" in Wamp icon or close/re-open CMD.

if you use WAMP you should also add the certificate line in php.ini for Apache (besides the default php.ini file):

[curl]
curl.cainfo = C:\your_location\cacert.pem

works for php5.3+

upvote
  flag
Yes! Be careful to edit both apache and php version php.ini files. For WAMP users, this answer was the only to solve my problem: //allinonescript.com/questions/28858351/… – MavBzh

Not the answer you're looking for? Browse other questions tagged or ask your own question.