Comprehensive Guide to Resolving cURL Error 60: SSL Certificate Problem - Unable to Get Local Issuer Certificate

Nov 10, 2025 · Programming · 20 views · 7.8

Keywords: cURL Error 60 | SSL Certificate Verification | PHP Configuration | CA Certificate | Stripe API

Abstract: This technical paper provides an in-depth analysis of cURL error 60 in PHP environments, offering complete solutions from downloading CA certificate bundles to configuring php.ini. With detailed step-by-step instructions and code examples, developers can effectively resolve SSL certificate verification issues and ensure proper communication with APIs like Stripe.

Problem Background and Error Analysis

When using cURL for HTTPS requests in PHP development environments, developers often encounter the "cURL error 60: SSL certificate problem: unable to get local issuer certificate" error. This indicates that cURL cannot validate the SSL certificate's legitimacy due to missing necessary Certificate Authority (CA) root certificates.

Root Cause Analysis

SSL/TLS certificate validation relies on the integrity of the certificate chain. When a client (like cURL) connects to an HTTPS-enabled server, it needs to verify whether the server certificate is issued by a trusted CA. Missing corresponding root or intermediate certificates in the local system leads to validation failure.

Complete Solution

Step 1: Download CA Certificate Bundle

First, download the latest CA certificate bundle from the official source:

// Download cacert.pem file from curl official website
// Download URL: https://curl.se/ca/cacert.pem

Step 2: File Storage Location

Save the downloaded cacert.pem file to an appropriate directory:

// Recommended path for XAMPP users
C:\xampp\php\extras\ssl\cacert.pem

// Recommended path for WAMP users
C:\wamp64\bin\php\php[version]\extras\ssl\cacert.pem

Step 3: Configure php.ini File

Add or modify the following configuration items in the php.ini file:

[curl]
curl.cainfo = "C:\xampp\php\extras\ssl\cacert.pem"

[openssl]
openssl.cafile = "C:\xampp\php\extras\ssl\cacert.pem"

Step 4: Server Restart

After completing the configuration, you must restart the web server (like Apache) and PHP-FPM (if used):

// Restart Apache service on Windows
net stop apache2.4
net start apache2.4

Common Issue Troubleshooting

Multiple php.ini Files Issue

Some environments may have multiple php.ini files; ensure all relevant files are correctly configured:

// Check the path of currently used php.ini file
php --ini

// Common php.ini file locations:
// - php.ini used by web server
// - php.ini used by CLI

Path Verification

Ensure the configured path points to the correct cacert.pem file:

// Verify file existence
if (file_exists("C:\xampp\php\extras\ssl\cacert.pem")) {
    echo "CA certificate file exists";
} else {
    echo "File path error or file does not exist";
}

Code-Level Solution

In addition to system-level configuration, you can also specify the CA certificate path directly in code:

// Use cURL options to specify CA certificate
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.stripe.com/v1/charges");
curl_setopt($ch, CURLOPT_CAINFO, "C:\xampp\php\extras\ssl\cacert.pem");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
$response = curl_exec($ch);

Stripe API Integration Example

Here's the Stripe payment code with proper SSL verification configured:

public function chargeStripe()
{
    // Initialize Stripe client
    $stripe = new \Stripe\StripeClient(env('STRIPE_SECRET_KEY'));
    
    try {
        // Create payment request
        $charge = $stripe->charges->create([
            'amount' => 2900,
            'currency' => 'eur',
            'source' => $_POST['stripeToken'],
            'description' => 'Order payment'
        ]);
        
        return redirect()->route('step1');
    } catch (\Stripe\Exception\ApiErrorException $e) {
        // Error handling
        return back()->withErrors([$e->getMessage()]);
    }
}

Security Considerations

Although you can bypass SSL verification by setting CURLOPT_SSL_VERIFYPEER to false, this poses serious security risks:

// Not recommended - vulnerable to man-in-the-middle attacks
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

Maintenance Recommendations

The CA certificate bundle needs regular updates to ensure it contains the latest root certificates:

Conclusion

By correctly configuring the CA certificate path, you can completely resolve cURL error 60 issues. The system-level configuration approach is recommended, as it benefits all PHP applications using cURL. Regular maintenance of the CA certificate bundle is crucial for long-term stable operation.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.