attemptRequest($httpMethod, $url, $headers, $httpBody); } catch (\Mollie\Api\Exceptions\CurlConnectTimeoutException $e) { // Nothing } } throw new \Mollie\Api\Exceptions\CurlConnectTimeoutException("Unable to connect to Mollie. Maximum number of retries (" . self::MAX_RETRIES . ") reached."); } /** * @param string $httpMethod * @param string $url * @param array $headers * @param string $httpBody * @return \stdClass|void|null * @throws \Mollie\Api\Exceptions\ApiException */ protected function attemptRequest($httpMethod, $url, $headers, $httpBody) { $curl = \curl_init($url); $headers["Content-Type"] = "application/json"; \curl_setopt($curl, \CURLOPT_RETURNTRANSFER, \true); \curl_setopt($curl, \CURLOPT_HTTPHEADER, $this->parseHeaders($headers)); \curl_setopt($curl, \CURLOPT_CONNECTTIMEOUT, self::DEFAULT_CONNECT_TIMEOUT); \curl_setopt($curl, \CURLOPT_TIMEOUT, self::DEFAULT_TIMEOUT); \curl_setopt($curl, \CURLOPT_SSL_VERIFYPEER, \true); \curl_setopt($curl, \CURLOPT_CAINFO, \_PhpScoper506056c89102\Composer\CaBundle\CaBundle::getBundledCaBundlePath()); switch ($httpMethod) { case \Mollie\Api\MollieApiClient::HTTP_POST: \curl_setopt($curl, \CURLOPT_POST, \true); \curl_setopt($curl, \CURLOPT_POSTFIELDS, $httpBody); break; case \Mollie\Api\MollieApiClient::HTTP_GET: break; case \Mollie\Api\MollieApiClient::HTTP_PATCH: \curl_setopt($curl, \CURLOPT_CUSTOMREQUEST, 'PATCH'); \curl_setopt($curl, \CURLOPT_POSTFIELDS, $httpBody); break; case \Mollie\Api\MollieApiClient::HTTP_DELETE: \curl_setopt($curl, \CURLOPT_CUSTOMREQUEST, 'DELETE'); \curl_setopt($curl, \CURLOPT_POSTFIELDS, $httpBody); break; default: throw new \InvalidArgumentException("Invalid http method: " . $httpMethod); } $startTime = \microtime(\true); $response = \curl_exec($curl); $endTime = \microtime(\true); if ($response === \false) { $executionTime = $endTime - $startTime; $curlErrorNumber = \curl_errno($curl); $curlErrorMessage = "Curl error: " . \curl_error($curl); if ($this->isConnectTimeoutError($curlErrorNumber, $executionTime)) { throw new \Mollie\Api\Exceptions\CurlConnectTimeoutException("Unable to connect to Mollie. " . $curlErrorMessage); } throw new \Mollie\Api\Exceptions\ApiException($curlErrorMessage); } $statusCode = \curl_getinfo($curl, \CURLINFO_RESPONSE_CODE); \curl_close($curl); return $this->parseResponseBody($response, $statusCode, $httpBody); } /** * The version number for the underlying http client, if available. * @example Guzzle/6.3 * * @return string|null */ public function versionString() { return 'Curl/*'; } /** * Whether this http adapter provides a debugging mode. If debugging mode is enabled, the * request will be included in the ApiException. * * @return false */ public function supportsDebugging() { return \false; } /** * @param int $curlErrorNumber * @param string|float $executionTime * @return bool */ protected function isConnectTimeoutError($curlErrorNumber, $executionTime) { $connectErrors = [\CURLE_COULDNT_RESOLVE_HOST => \true, \CURLE_COULDNT_CONNECT => \true, \CURLE_SSL_CONNECT_ERROR => \true, \CURLE_GOT_NOTHING => \true]; if (isset($connectErrors[$curlErrorNumber])) { return \true; } if ($curlErrorNumber === \CURLE_OPERATION_TIMEOUTED) { if ($executionTime > self::DEFAULT_TIMEOUT) { return \false; } return \true; } return \false; } /** * @param string $response * @param int $statusCode * @param string $httpBody * @return \stdClass|null * @throws \Mollie\Api\Exceptions\ApiException */ protected function parseResponseBody($response, $statusCode, $httpBody) { if (empty($response)) { if ($statusCode === self::HTTP_NO_CONTENT) { return null; } throw new \Mollie\Api\Exceptions\ApiException("No response body found."); } $body = @\json_decode($response); // GUARDS if (\json_last_error() !== \JSON_ERROR_NONE) { throw new \Mollie\Api\Exceptions\ApiException("Unable to decode Mollie response: '{$response}'."); } if (isset($body->error)) { throw new \Mollie\Api\Exceptions\ApiException($body->error->message); } if ($statusCode >= 400) { $message = "Error executing API call ({$body->status}: {$body->title}): {$body->detail}"; $field = null; if (!empty($body->field)) { $field = $body->field; } if (isset($body->_links, $body->_links->documentation)) { $message .= ". Documentation: {$body->_links->documentation->href}"; } if ($httpBody) { $message .= ". Request body: {$httpBody}"; } throw new \Mollie\Api\Exceptions\ApiException($message, $statusCode, $field); } return $body; } protected function parseHeaders($headers) { $result = []; foreach ($headers as $key => $value) { $result[] = $key . ': ' . $value; } return $result; } }