Reconocimientos de IPN de PayPal que fallan con rutinas SSL: SSL3_READ_BYTES: error de handshake de alerta de sslv3

Sin cambios en nuestro lado y quizás relacionado con POODLE / SSL3, nuestra API de PayPal llama a PPIPNMessage :: validate ahora está fallando.

SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure 

El pago y la recepción de IPN está bien (y nunca hemos admitido SSL3 entrante), solo falla al reconocer el IPN (curiosamente, PayPal no vuelve a intentarlo, aunque hayamos fallado)

Ejecutar Curl desde la misma línea de comando del servidor tiene éxito

 $ curl -iv https://ipnpb.paypal.com/cgi-bin/webscr * About to connect() to ipnpb.paypal.com port 443 (#0) * Trying 173.0.88.8... connected * successfully set certificate verify locations: * CAfile: none CApath: /etc/ssl/certs * SSLv3, TLS handshake, Client hello (1): * SSLv3, TLS handshake, Server hello (2): * SSLv3, TLS handshake, CERT (11): * SSLv3, TLS handshake, Server finished (14): * SSLv3, TLS handshake, Client key exchange (16): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSL connection using AES256-SHA * Server certificate: * subject: 1.3.6.1.4.1.311.60.2.1.3=US; 1.3.6.1.4.1.311.60.2.1.2=Delaware; businessCategory=Private Organization; serialNumber=3014267; C=US; postalCode=95131-2021; ST=California; L=San Jose; street=2211 N 1st St; O=PayPal, Inc.; OU=PayPal Production; CN=ipnpb.paypa * start date: 2013-06-28 00:00:00 GMT * expire date: 2015-08-02 23:59:59 GMT * subjectAltName: ipnpb.paypal.com matched * issuer: C=US; O=VeriSign, Inc.; OU=VeriSign Trust Network; OU=Terms of use at https://www.verisign.com/rpa (c)06; CN=VeriSign Class 3 Extended Validation SSL CA * SSL certificate verify ok. > GET /cgi-bin/webscr HTTP/1.1 > User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3 > Host: ipnpb.paypal.com > Accept: */* 

Noté que ssllabs.com muestra 1 de cada 4 IPs que todavía soportan SSL3 en este punto final.

Este es el mismo problema que el Error 0x1408F10B: “SSL3_GET_RECORD: número de versión incorrecta” con el SDK de PayPal

La versión de la API de PayPal estamos utilizando los códigos duros CURLOPT_SSLVERSION a 3.

Nuestra solución es insertar esto antes de cualquier llamada de PayPal.

 PPHttpConfig::$DEFAULT_CURL_OPTS[CURLOPT_SSLVERSION] = 4; 

Tuve el mismo problema … Simplemente cambie la siguiente línea en ipnlistener.php

de:

 curl_setopt($ch, CURLOPT_SSLVERSION, 3); 

a:

 curl_setopt($ch, CURLOPT_SSLVERSION, 4); 

ipnlistener.php

 use_ssl) { $uri = 'https://'.$this->getPaypalHost().'/cgi-bin/webscr'; $this->post_uri = $uri; } else { $uri = 'http://'.$this->getPaypalHost().'/cgi-bin/webscr'; $this->post_uri = $uri; } $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__)."/cert/api_cert_chain.crt"); curl_setopt($ch, CURLOPT_URL, $uri); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded_data); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $this->follow_location); curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_SSLVERSION, 4); if ($this->force_ssl_v3) { curl_setopt($ch, CURLOPT_SSLVERSION, 4); //Modified from 3 to 4 } $this->response = curl_exec($ch); $this->response_status = strval(curl_getinfo($ch, CURLINFO_HTTP_CODE)); if ($this->response === false || $this->response_status == '0') { $errno = curl_errno($ch); $errstr = curl_error($ch); throw new Exception("cURL error: [$errno] $errstr"); } } /** * Post Back Using fsockopen() * * Sends the post back to PayPal using the fsockopen() function. Called by * the processIpn() method if the use_curl property is false. Throws an * exception if the post fails. Populates the response, response_status, * and post_uri properties on success. * * @param string The post data as a URL encoded string */ protected function fsockPost($encoded_data) { if ($this->use_ssl) { $uri = 'ssl://'.$this->getPaypalHost(); $port = '443'; $this->post_uri = $uri.'/cgi-bin/webscr'; } else { $uri = $this->getPaypalHost(); // no "http://" in call to fsockopen() $port = '80'; $this->post_uri = 'http://'.$uri.'/cgi-bin/webscr'; } $fp = fsockopen($uri, $port, $errno, $errstr, $this->timeout); if (!$fp) { // fsockopen error throw new Exception("fsockopen error: [$errno] $errstr"); } $header = "POST /cgi-bin/webscr HTTP/1.1\r\n"; $header .= "Host: ".$this->getPaypalHost()."\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: ".strlen($encoded_data)."\r\n"; $header .= "Connection: Close\r\n\r\n"; fputs($fp, $header.$encoded_data."\r\n\r\n"); while(!feof($fp)) { if (empty($this->response)) { // extract HTTP status from first line $this->response .= $status = fgets($fp, 1024); $this->response_status = trim(substr($status, 9, 4)); } else { $this->response .= fgets($fp, 1024); } } fclose($fp); } private function getPaypalHost() { if ($this->use_sandbox) return self::SANDBOX_HOST; else return self::PAYPAL_HOST; } /** * Get POST URI * * Returns the URI that was used to send the post back to PayPal. This can * be useful for troubleshooting connection problems. The default URI * would be "ssl://www.sandbox.paypal.com:443/cgi-bin/webscr" * * @return string */ public function getPostUri() { return $this->post_uri; } /** * Get Response * * Returns the entire response from PayPal as a string including all the * HTTP headers. * * @return string */ public function getResponse() { return $this->response; } /** * Get Response Status * * Returns the HTTP response status code from PayPal. This should be "200" * if the post back was successful. * * @return string */ public function getResponseStatus() { return $this->response_status; } /** * Get Text Report * * Returns a report of the IPN transaction in plain text format. This is * useful in emails to order processors and system administrators. Override * this method in your own class to customize the report. * * @return string */ public function getTextReport() { $r = ''; // date and POST url for ($i=0; $i<80; $i++) { $r .= '-'; } $r .= "\n[".date('m/d/Y g:i A').'] - '.$this->getPostUri(); if ($this->use_curl) $r .= " (curl)\n"; else $r .= " (fsockopen)\n"; // HTTP Response for ($i=0; $i<80; $i++) { $r .= '-'; } $r .= "\n{$this->getResponse()}\n"; // POST vars for ($i=0; $i<80; $i++) { $r .= '-'; } $r .= "\n"; foreach ($this->post_data as $key => $value) { $r .= str_pad($key, 25)."$value\n"; } $r .= "\n\n"; return $r; } /** * Process IPN * * Handles the IPN post back to PayPal and parsing the response. Call this * method from your IPN listener script. Returns true if the response came * back as "VERIFIED", false if the response came back "INVALID", and * throws an exception if there is an error. * * @param array * * @return boolean */ public function processIpn($post_data=null) { $encoded_data = 'cmd=_notify-validate'; if ($post_data === null) { // use raw POST data if (!empty($_POST)) { $this->post_data = $_POST; $encoded_data .= '&'.file_get_contents('php://input'); } else { throw new Exception("No POST data found."); } } else { // use provided data array $this->post_data = $post_data; foreach ($this->post_data as $key => $value) { $encoded_data .= "&$key=".urlencode($value); } } if ($this->use_curl) $this->curlPost($encoded_data); else $this->fsockPost($encoded_data); if (strpos($this->response_status, '200') === false) { throw new Exception("Invalid response status: ".$this->response_status); } if (strpos($this->response, "VERIFIED") !== false) { return true; } elseif (strpos($this->response, "INVALID") !== false) { return false; } else { throw new Exception("Unexpected response from PayPal."); } } /** * Require Post Method * * Throws an exception and sets a HTTP 405 response header if the request * method was not POST. */ public function requirePostMethod() { // require POST requests if ($_SERVER['REQUEST_METHOD'] && $_SERVER['REQUEST_METHOD'] != 'POST') { header('Allow: POST', true, 405); throw new Exception("Invalid HTTP request method."); } } } ?> 

PayPal inhabilitó SSLv3 en respuesta a la vulnerabilidad de “POODLE”. Lea sobre esto aquí: Respuesta de PayPal

Si está usando ipnlistener.php, fuerce TLS 1.2 como el protocolo SSL:

 curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); 

(Actualizado: se requiere TLS V1.2 para 2017)

Nota: PayPal está actualizando los protocolos utilizados para proteger todas las conexiones externas realizadas en sus sistemas. Transport Layer Security versión 1.2 (TLS 1.2) y el Protocolo de transferencia de hipertexto versión 1.1 (HTTP / 1.1) serán obligatorios para la comunicación con PayPal en 2018. Consulte su Hoja de ruta de seguridad.

SSLv3 ya no está disponible para http://www.paypal.com:

 # sslscan www.paypal.com|grep Accepted Accepted TLSv1 256 bits AES256-SHA Accepted TLSv1 128 bits AES128-SHA Accepted TLSv1 168 bits DES-CBC3-SHA Accepted TLSv1 128 bits RC4-SHA Accepted TLSv1 128 bits RC4-MD5 

Debe cambiar su CURLOPT_SSLVERSION a TLSv1 :

 curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); 

(Este “CURL_SSLVERSION_TLSv1” -constant no está disponible para versiones anteriores de PHP, entonces otra forma es eliminar simplemente la aplicación CURLOPT_SSLVERSION).

En mi caso, ninguna de estas cosas mencionadas en las otras respuestas funcionó, pero pude descifrar la solución y está en la misma línea, pero me tomó un tiempo averiguar qué archivo utilizaba el sdk que estaba usando como config. no había ningún archivo de escucha ipn y que “PPHttpConfig” me daría un error fatal

así que descubrí que este es el archivo de escucha que están usando ahora:

PayPal-PHP-SDK / paypal / rest-api-sdk-php / lib / PayPal / Core / PayPalHttpConfig.php

Encontré dentro

CURLOPT_SSLVERSION => 1

Lo cambié a:

CURLOPT_SSLVERSION => 4

y eso lo solucionó para mí.

Secundo que. Perdí horas tratando de descubrirlo. En mi escucha de IPN tuve que eliminar ‘force ssl v3’. A partir de ese momento, mi IPN comienza a funcionar nuevamente.

Solo haz un curl -v https://paypal.com

Muestra: conexión SSL usando TLS_RSA_WITH_AES_256_CBC_SHA

Tengo el mismo error mientras verifico IPN con PayPal. Aquí están las soluciones de problema

Trabajé con PHP 5.3 y PHP 5.3 ya no es compatible con SSL versión 3. Tengo la actualización con la versión de PHP con 5.4 y agregué la siguiente línea de código. Es trabajo para mi

 curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $req); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); #curl_setopt($ch, CURLOPT_SSLVERSION, 4); curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'TLSv1'); 

Use esta configuración en su clase de paypal en la función de llamada PPHttpPost ()

 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSLVERSION, 6); //6 is for TLSV1.2