From 310e9c0a496ca0806c9797eab6abdd07a2f51ecd Mon Sep 17 00:00:00 2001 From: Estanislau Trepat Date: Fri, 27 Feb 2026 10:54:56 +0100 Subject: [PATCH 1/3] fix: guard curl_close() calls for PHP 8.0+ compatibility Since PHP 8.0, CurlHandle is an object that is automatically closed when it goes out of scope or is garbage collected, making explicit curl_close() calls unnecessary. Starting with PHP 8.5, calling curl_close() triggers a deprecation notice. This commit wraps all curl_close() calls in a PHP_VERSION_ID check so they are only executed on PHP < 8.0, avoiding deprecation warnings on modern PHP versions while maintaining backward compatibility with PHP 7.x. --- src/Client.php | 62 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/src/Client.php b/src/Client.php index 0a84d7b..a4862f9 100644 --- a/src/Client.php +++ b/src/Client.php @@ -41,7 +41,7 @@ class Client /** * Sets a request header for the cURL request. - * + * * @param string $name The name of the header. Must not be empty. * @param string $value The value of the header. Must not be empty. */ @@ -60,7 +60,7 @@ private function setRequestHeader($name, $value) /** * Returns the request headers as an array of strings formatted as "Name: Value". - * + * * @return array An array of request headers formatted as "Name: Value". */ private function getRequestHeaders() @@ -122,7 +122,9 @@ public function startSolicitation($order) $this->setRequestHeader(self::HEADER_SEQURA_MERCHANT_ID, $order['merchant']['id'] ?? ''); $this->verbThePayload('POST', array('order' => $order)); $this->dealWithResponse(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function qualifyForSolicitation($order) @@ -139,11 +141,11 @@ public function qualifyForSolicitation($order) /** * Retrieves the identification form for a given URI and options. - * + * * @param string $uri The URI to retrieve the identification form from. * @param array $options An associative array of options for the form. * @param string $merchant_id The merchant ID to be used in the request. - * + * * @return string The HTML content of the identification form. */ public function getIdentificationForm($uri, $options = array(), $merchant_id = '') @@ -158,7 +160,9 @@ public function getIdentificationForm($uri, $options = array(), $merchant_id = ' $this->sendRequest(); $this->dealWithResponse(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } return $this->curl_result; } @@ -171,7 +175,9 @@ public function sendIdentificationForm($uri, $options = array(), $merchant_id = $this->setRequestHeader(self::HEADER_SEQURA_MERCHANT_ID, $merchant_id); $this->verbThePayload('POST', $options); $this->dealWithResponse(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } return $this->curl_result; } @@ -185,7 +191,9 @@ public function startCards($order) $this->setRequestHeader(self::HEADER_SEQURA_MERCHANT_ID, $order['merchant']['id'] ?? ''); $this->verbThePayload('POST', array('order' => $order)); $this->dealWithResponse(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function getCardsForm($uri, $options = array(), $merchant_id = '') @@ -198,7 +206,9 @@ public function getCardsForm($uri, $options = array(), $merchant_id = '') $this->sendRequest(); $this->dealWithResponse(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function qualifyForstartCards($order) @@ -230,7 +240,9 @@ public function getPaymentMethods($uri, $options = array(), $merchant_id = '') curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'GET'); $this->sendRequest(); $this->dealWithResponse(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function getAvailableDisbursements($merchant_id) @@ -243,7 +255,9 @@ public function getAvailableDisbursements($merchant_id) $this->sendRequest(); $this->dealWithResponse(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function getDisbursementDetails($path) @@ -259,7 +273,9 @@ public function getDisbursementDetails($path) $this->sendRequest(); $this->dealWithResponse(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function getCreditAgreements($amount, $merchant_id, $locale = 'es-ES', $country = 'ES', $currency = 'EUR') @@ -277,7 +293,9 @@ public function getCreditAgreements($amount, $merchant_id, $locale = 'es-ES', $c curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'GET'); $this->sendRequest(); $this->dealWithResponse(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function updateOrder($uri, $order, $verb = 'PUT') @@ -292,7 +310,9 @@ public function updateOrder($uri, $order, $verb = 'PUT') if ($this->status == 409) { $this->cart_has_changed = true; } - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function sendDeliveryReport($delivery_report) @@ -301,7 +321,9 @@ public function sendDeliveryReport($delivery_report) $this->setRequestHeader(self::HEADER_SEQURA_MERCHANT_ID, $delivery_report['merchant']['id'] ?? ''); $this->verbThePayload('POST', array('delivery_report' => $delivery_report)); $this->dealWithResponse(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function orderUpdate($order) @@ -316,7 +338,9 @@ public function orderUpdate($order) if ($this->status == 409) { $this->cart_has_changed = true; } - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function callCron($cron_url) @@ -326,7 +350,9 @@ public function callCron($cron_url) curl_setopt($this->ch, CURLOPT_HTTPGET, 1); curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false); $this->sendRequest(); - curl_close($this->ch); + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } } public function succeeded() @@ -377,7 +403,7 @@ public function dump() /** * Initializes the cURL session with the given URL and sets the necessary options. - * + * * @param string $url The URL to initialize the cURL session with. */ private function initCurl($url) From 42c8dbea11856bb7d4e969304a3bec77f980e133 Mon Sep 17 00:00:00 2001 From: Estanislau Trepat Date: Fri, 27 Feb 2026 13:48:22 +0100 Subject: [PATCH 2/3] test: Add test to guard against PHP8.5+ regressions Adds a test that installs an E_DEPRECATED-to-failure error handler and calls `getAvailableDisbursements()` to guard against regressions on PHP 8.5+ where `curl_close()` should emit a deprecation notice. --- tests/ClientTest.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/ClientTest.php b/tests/ClientTest.php index d8885cf..460d689 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -80,6 +80,29 @@ public function testGetPaymentMethods(): void ); } + public function testNoCurlCloseDeprecationOnPhp85Plus(): void + { + if (PHP_VERSION_ID < 80500) { + $this->markTestSkipped('curl_close() deprecation notices only apply to PHP 8.5+'); + } + + set_error_handler(function (int $errno, string $errstr): bool { + if ($errno === E_DEPRECATED) { + $this->fail("Unexpected E_DEPRECATED notice triggered: $errstr"); + } + return false; + }); + + try { + $client = new Client(self::$username, self::$password, self::$endpoint); + $client->getAvailableDisbursements(self::$merchant); + } finally { + restore_error_handler(); + } + + $this->assertTrue(true); // reached here without any deprecation notice + } + private function createOrder($client): string { $order = json_decode( From 90786e35574f80f4a8a3f6a7ab69828107993dd8 Mon Sep 17 00:00:00 2001 From: Estanislau Trepat Date: Fri, 27 Feb 2026 13:51:03 +0100 Subject: [PATCH 3/3] refactor: extract `curl_close()` guards into a helper Replace repeated `curl_close()` guards with a single private `closeCurlHandle()` method. The helper calls `curl_close()` on PHP < 8.0 and always nulls `$this->ch` so the `CurlHandle` may be released on PHP 8+. --- src/Client.php | 67 +++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/src/Client.php b/src/Client.php index a4862f9..9fbf731 100644 --- a/src/Client.php +++ b/src/Client.php @@ -122,9 +122,7 @@ public function startSolicitation($order) $this->setRequestHeader(self::HEADER_SEQURA_MERCHANT_ID, $order['merchant']['id'] ?? ''); $this->verbThePayload('POST', array('order' => $order)); $this->dealWithResponse(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function qualifyForSolicitation($order) @@ -160,9 +158,7 @@ public function getIdentificationForm($uri, $options = array(), $merchant_id = ' $this->sendRequest(); $this->dealWithResponse(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); return $this->curl_result; } @@ -175,9 +171,7 @@ public function sendIdentificationForm($uri, $options = array(), $merchant_id = $this->setRequestHeader(self::HEADER_SEQURA_MERCHANT_ID, $merchant_id); $this->verbThePayload('POST', $options); $this->dealWithResponse(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); return $this->curl_result; } @@ -191,9 +185,7 @@ public function startCards($order) $this->setRequestHeader(self::HEADER_SEQURA_MERCHANT_ID, $order['merchant']['id'] ?? ''); $this->verbThePayload('POST', array('order' => $order)); $this->dealWithResponse(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function getCardsForm($uri, $options = array(), $merchant_id = '') @@ -206,9 +198,7 @@ public function getCardsForm($uri, $options = array(), $merchant_id = '') $this->sendRequest(); $this->dealWithResponse(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function qualifyForstartCards($order) @@ -240,9 +230,7 @@ public function getPaymentMethods($uri, $options = array(), $merchant_id = '') curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'GET'); $this->sendRequest(); $this->dealWithResponse(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function getAvailableDisbursements($merchant_id) @@ -255,9 +243,7 @@ public function getAvailableDisbursements($merchant_id) $this->sendRequest(); $this->dealWithResponse(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function getDisbursementDetails($path) @@ -273,9 +259,7 @@ public function getDisbursementDetails($path) $this->sendRequest(); $this->dealWithResponse(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function getCreditAgreements($amount, $merchant_id, $locale = 'es-ES', $country = 'ES', $currency = 'EUR') @@ -293,9 +277,7 @@ public function getCreditAgreements($amount, $merchant_id, $locale = 'es-ES', $c curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'GET'); $this->sendRequest(); $this->dealWithResponse(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function updateOrder($uri, $order, $verb = 'PUT') @@ -310,9 +292,7 @@ public function updateOrder($uri, $order, $verb = 'PUT') if ($this->status == 409) { $this->cart_has_changed = true; } - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function sendDeliveryReport($delivery_report) @@ -321,9 +301,7 @@ public function sendDeliveryReport($delivery_report) $this->setRequestHeader(self::HEADER_SEQURA_MERCHANT_ID, $delivery_report['merchant']['id'] ?? ''); $this->verbThePayload('POST', array('delivery_report' => $delivery_report)); $this->dealWithResponse(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function orderUpdate($order) @@ -338,9 +316,7 @@ public function orderUpdate($order) if ($this->status == 409) { $this->cart_has_changed = true; } - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function callCron($cron_url) @@ -350,9 +326,7 @@ public function callCron($cron_url) curl_setopt($this->ch, CURLOPT_HTTPGET, 1); curl_setopt($this->ch, CURLOPT_SSL_VERIFYPEER, false); $this->sendRequest(); - if (PHP_VERSION_ID < 80000) { - curl_close($this->ch); - } + $this->closeCurlHandle(); } public function succeeded() @@ -401,6 +375,21 @@ public function dump() // Private methods below + /** + * Releases the cURL handle after a request. + * On PHP < 8.0 the resource must be explicitly closed; on PHP 8.0+ the + * CurlHandle object is reference-counted, so we simply null the property + * to let it be garbage-collected and avoid the curl_close() deprecation + * introduced in PHP 8.5. + */ + private function closeCurlHandle() + { + if (PHP_VERSION_ID < 80000) { + curl_close($this->ch); + } + $this->ch = null; + } + /** * Initializes the cURL session with the given URL and sets the necessary options. *