Skip to content

Commit

Permalink
Update bundled cacert.pem file. Follows Mozilla's recommendations on …
Browse files Browse the repository at this point in the history
…invalid certificates. Always use certificate bundle, ignore old installed bundles. Enable HTTP Keep-Alive to enhance performance of multiple API calls
  • Loading branch information
Willem Stuursma committed Apr 22, 2015
1 parent 9657b89 commit 771a69b
Show file tree
Hide file tree
Showing 2 changed files with 892 additions and 555 deletions.
95 changes: 63 additions & 32 deletions src/Mollie/API/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class Mollie_API_Client
/**
* Version of our client.
*/
const CLIENT_VERSION = "1.1.6";
const CLIENT_VERSION = "1.1.7";

/**
* Endpoint of the remote API.
Expand Down Expand Up @@ -93,6 +93,15 @@ class Mollie_API_Client
*/
protected $version_strings = array();

/**
* This property will contain a cURL handle, which we will keep around to enable the re-use of of the TCP
* connection. This saves re-negotiating the TLS handshake and setting up the new TCP connections when performing
* multiple API calls.
*
* @var resource
*/
protected $ch;

public function __construct ()
{
$this->payments = new Mollie_API_Resource_Payments($this);
Expand Down Expand Up @@ -171,13 +180,27 @@ public function performHttpCall ($http_method, $api_method, $http_body = NULL)
throw new Mollie_API_Exception("You have not set an API key. Please use setApiKey() to set the API key.");
}

$url = $this->api_endpoint . "/" . self::API_VERSION . "/" . $api_method;
if (empty($this->ch))
{
/*
* Initialize a cURL handle.
*/
$this->ch = curl_init();
}
else
{
/*
* Re-use the same cURL handle.
*/
curl_reset($this->ch);
}

$ch = curl_init($url);
$url = $this->api_endpoint . "/" . self::API_VERSION . "/" . $api_method;

curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_ENCODING, "");
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($this->ch, CURLOPT_URL, $url);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($this->ch, CURLOPT_ENCODING, "");
curl_setopt($this->ch, CURLOPT_TIMEOUT, 10);

$user_agent = join(' ', $this->version_strings);

Expand All @@ -188,33 +211,30 @@ public function performHttpCall ($http_method, $api_method, $http_body = NULL)
"X-Mollie-Client-Info: " . php_uname(),
);

curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $http_method);
curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, $http_method);

if ($http_body !== NULL)
{
$request_headers[] = "Content-Type: application/json";
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $http_body);
curl_setopt($this->ch, CURLOPT_POST, 1);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $http_body);
}

curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $request_headers);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, TRUE);

$body = curl_exec($ch);
/*
* On some servers, the list of installed certificates is outdated or not present at all (the ca-bundle.crt
* is not installed). So we tell cURL which certificates we trust.
*/
curl_setopt($this->ch, CURLOPT_CAINFO, realpath(dirname(__FILE__) . "/cacert.pem"));

if (curl_errno($ch) == CURLE_SSL_CACERT || curl_errno($ch) == CURLE_SSL_PEER_CERTIFICATE || curl_errno($ch) == 77 /* CURLE_SSL_CACERT_BADFILE (constant not defined in PHP though) */)
{
/*
* On some servers, the list of installed certificates is outdated or not present at all (the ca-bundle.crt
* is not installed). So we tell cURL which certificates we trust. Then we retry the requests.
*/
$request_headers[] = "X-Mollie-Debug: used shipped root certificates";
curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
curl_setopt($ch, CURLOPT_CAINFO, realpath(dirname(__FILE__) . "/cacert.pem"));
$body = curl_exec($ch);
$body = curl_exec($this->ch);

if (strpos(curl_error($ch), "error setting certificate verify locations") !== FALSE)
if (curl_errno($this->ch) == CURLE_SSL_CACERT || curl_errno($this->ch) == CURLE_SSL_PEER_CERTIFICATE || curl_errno($this->ch) == 77 /* CURLE_SSL_CACERT_BADFILE (constant not defined in PHP though) */)
{
if (strpos(curl_error($this->ch), "error setting certificate verify locations") !== FALSE)
{
/*
* Error setting CA-file. Could be missing, or there is a bug in OpenSSL with too long paths.
Expand All @@ -224,28 +244,39 @@ public function performHttpCall ($http_method, $api_method, $http_body = NULL)
*/
array_shift($request_headers);
$request_headers[] = "X-Mollie-Debug: unable to use shipped root certificaties, no peer validation.";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$body = curl_exec($ch);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$body = curl_exec($this->ch);
}
}

if (strpos(curl_error($ch), "certificate subject name 'mollie.nl' does not match target host") !== FALSE)
if (strpos(curl_error($this->ch), "certificate subject name 'mollie.nl' does not match target host") !== FALSE)
{
/*
* On some servers, the wildcard SSL certificate is not processed correctly. This happens with OpenSSL 0.9.7
* from 2003.
*/
$request_headers[] = "X-Mollie-Debug: old OpenSSL found";
curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$body = curl_exec($ch);
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $request_headers);
curl_setopt($this->ch, CURLOPT_SSL_VERIFYHOST, 0);
$body = curl_exec($this->ch);
}

if (curl_errno($ch))
if (curl_errno($this->ch))
{
throw new Mollie_API_Exception("Unable to communicate with Mollie (".curl_errno($ch)."): " . curl_error($ch) . ".");
throw new Mollie_API_Exception("Unable to communicate with Mollie (".curl_errno($this->ch)."): " . curl_error($this->ch) . ".");
}

return $body;
}

/**
* Destroy cURL handle if is still exist.
*/
public function __destruct ()
{
if (is_resource($this->ch))
{
curl_close($this->ch);
}
}
}
Loading

0 comments on commit 771a69b

Please sign in to comment.