Curl / php Empty response from PayPal IPN url - php

In the past couple of days, our PayPal IPN has stopped working and receiving a empty response from PayPal. Nothing has changed on the server or in our code.
Attempting to cUrl to the PayPal IPN url simply returns an empty response.
$url = "https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
$data = curl_exec($ch);
curl_close($ch);
print $data;
The above should return "INVALID" and works as expected on my localhost and from other servers.
Changing the url to any other domain other then PayPal also works without issues.
So it seems it only received the empty response from paypal.com
I wonder if any one has run into the issue or could give pointers where to look in the hope to- resolve it?
Kind Regards
Musaffar

It looks like Paypal made some security changes at the weekend. Some oscommerce users have been getting similar symptoms since Sunday with the curl error turning out to be:
SSL certificate problem: unable to get local issuer certificate
In their cases it was due to the local certificate copy only having the Paypal certificate and not the root or intermediate certificates, with the solution to update it.
The working certificate can be found in:
OSCOM Phoenix github

I would perhaps start checking if curl gave you any errors. PHP gives you in this case curl_errno($ch) and curl_error($ch) which will return a message or respectively the error code to it.
In case there is nothing suspicious to it. I would perhaps try to validate if you're able to run the above from your CLI on the server. (requires SSH access to it)
curl -H "User-Agent: ..." "https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate"
I hope this gives you a good starting point. Please let me know if this helps or if you need more ideas.
Edit#2: After comments where added from the author:
cUrl does indeed return an error : error 35 and the error message is as follows:
error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version
In this case I would guess that your system is outdated and does not support the SSL ciphers from paypal. You could try to force a specific TLS version. As of today paypal webservers support only TLS1.2 or TLS1.3. This is how you can force it:
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
or
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_3);
Additionaly #Preston PHX mentioned in a comment a good refernces for this issue coming from paypal:
https://github.com/paypal/TLS-update#php
https://developer.paypal.com/docs/api/info-security-guidelines/

Related

Php Curl doesn't work on just one website

i've an error very very strange.
I need to access this website: http://sub.example.com/ with cURL. From localhost i've no problem as well as if i use cURL from command line or browser to access the website.
I'm using this code on my Siteground server:
<?php
$url="http://sub.example.com/";
$agent= 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)';
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $agent);
curl_setopt($ch, CURLOPT_URL,$url);
$result=curl_exec($ch);
var_dump($result);
?>
and i get $result = false.
If i use Try / Catch i get: Curl failed with error #6: Could not resolve host
I've also tried to substitute $url with another website's url and it always works (http and https, domain and subdomain, on my server and external)!
I spent already a day trying to solve this, please help me!
Thank you in advance, Luca
according to googledns, sub.example.com does not exist.
$ nslookup sub.example.com 8.8.8.8
*** google-public-dns-a.google.com can't find sub.example.com: Non-existent domain
Server: google-public-dns-a.google.com
Address: 8.8.8.8
the fact that it works for you on localhost means you have a weird DNS, or perhaps an entry for it in your hosts file , while your Siteground server does not.
anyway, Curl failed with error #6: Could not resolve host means the server's dns could not find sub.example.com, but luckily, if you know what ip you want to connect to, you can bypass the DNS entirely, by instead writing:
curl_setopt($ch, CURLOPT_URL,'http://93.184.216.34/');
curl_setopt($ch,CURLOPT_HTTPHEADER,array('Host: sub.example.com'));
(there is also a more correct-ish curlopt to tell curl which ip goes with wich domain, but the the name escapes me at the moment, and iirc, php has not added official support for it, so you'd have to use the magic value for it, rather than the defined name, but manually setting the Host: header is pretty easy anyway)

PHP cURL - issues with accessing HTTPS site

I have been using cURL code to access Beanstream for awhile now, and all of a sudden it stopped working as of yesterday. I have determined that this has to do with accessing the HTTPS URL for Beanstream processing, as if I test that same code and just go to the HTTP URL, it works (of course it returns an insecure connection code).
Prior to the below code I was setting VERIFYPEER / VERIFYHOST to FALSE, which was working up until yesterday.
$url = 'https://www.google.com';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, "/xxxx/public_html/_cert/GeoTrustGlobalCA_google.crt");
$getResponse = (curl_exec($ch));
curl_close($ch);
print_r($getResponse);
I have setup the above test code to try and access Google via HTTPS. I had read that a proper connection requires the VERIFYPEER / CAINFO options to be set, which I have done and grabbed the Google .crt and placed it on the web server as well.
I still get a 503 Service Unavailable error back though.
The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.
Additionally, a 503 Service Unavailable error was encountered while
trying to use an ErrorDocument to handle the request.

cURL Error (35): error:14077458:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 unrecognized name

I have been using the following code block to collect data from a HTTPS website using cURL.
$q = 'https://www.example.org/'; // for example
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $q);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
$json = curl_exec($ch);
cURL shows the following error
error:14077458:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 unrecognized name
This might be related to older OpenSSL version, but as the website is in a Shared hosting, server side settings cannot be changed at the moment. All I can do is to change cURL parameters.
I have checked here https://www.ssllabs.com/ssltest/analyze.html to see the available protocols for that server, found SSL3 and SSL2 is not available, but TLS 1.2, TLS 1.1 and TLS 1.0 are available. Searching over Google, I found its best not specifying SSL version which actually auto-negotiate the best level to use. Although, I tried with setting TLS version in CURLOPT_SSLVERSION (as follows), but same error occurs.
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
I have been trying a lot for last few days, but all attempts went in vain.
I have tried to explain all the things I did, but anyone please ask if more info needed. Any help would be greatly appreciated.
Thanks a lot
This might be cURL #1037 Bug http://sourceforge.net/p/curl/bugs/1037/
It seems to happen when you connect with an outdated openssl 0.9.8 cURL against some server with openssl 1.0.x and use SNI.

CURL Request crashes SSL

I've noticed a little problem with CURL in PHP. Whenever I request a https:// connection it returns "false", and every website that I try to reach while I have my PHP page open reports to have an Untrusted certificate.
This is my request method:
private function request($url, $params, $method = "GET") {
if ($method == "GET")
$url = $this->structGET($url, $params);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
if (isset($_SERVER['HTTP_USER_AGENT'])) {
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
} else {
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.X.Y.Z Safari/525.13.');
}
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$header[] = 'Accept-Language: EN';
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
if ($method == "POST") {
curl_setopt($ch, CURLOPT_POST, true);
if ($params)
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
}
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
And this is what Chrome returns when I try visiting Facebook.
The site's security certificate is not trusted!
You attempted to reach
www.facebook.com, but the server presented a certificate issued by an
entity that is not trusted by your computer's operating system. This
may mean that the server has generated its own security credentials,
which Google Chrome cannot rely on for identity information, or an
attacker may be trying to intercept your communications. You cannot
proceed because the website operator has requested heightened security
for this domain.
Don't use techniques that disable certificate verification. While they may "solve" your problem on the surface, they only ignore the problem, rather than fixing it. Never do this in production code.
The most likely cause is that you're on a network where there is a MITM corporate proxy. However legitimate these devices may be, they are effectively MITM devices.
What they do is that they will replace the original certificate with a certificate issued using their own internal CA, so as to be able to monitor the traffic.
If this device was legitimately set up by your network administrator, you should be able to get its CA certificate (in those circumstances, the CA certificate would typically be installed on all end-user machines centrally administered).
It's quite likely that, as a developer, you may have installed your own machine, and might not have the CA certificate installed. Ask your network administrator for that CA certificate, and install it with the certificates used by your browser and by curl within PHP (two different locations). Where the curl default location is may depend on the system you're using, but you can also configure it via CURLOPT_CAINFO.
Presumably, you're developing within a local network, but may possibly deploy that service on a different network when it's done. Make sure that this is configurable.
Yeah that happens when cURL tries to see if the SSL is verified. Facebook usually has a verified signature but may be because of network, it is returning invalid (happens in my case: using fortiguard proxy, facebook blocked!)
So, what you can do is, you can choose to ignore that error totally.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
That should fix it. But, if you want to fix it properly, then you should probably use a proxy or something or get a certificate for the server(if it is yours).
You need to add these two lines for SSL
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);

get_file_content not working for https

I am using php and google's new CSE in my website . The URL for request is like
https://www.googleapis.com/customsearch/v1?key=INSERT-YOUR-KEY&cx=017576662512468239146:omuauf_lfve&q=lectures
The connection is https and file_get_content() is getting failed. How can i get it working?
Since i need to host the site on some external web-hosting servers, I am in need of solution which don't alter php configuration file or work with default options found on most of web-hosting sites.
You can use curl:
## HTTPS url that you are targeting.
$url = "https://www.googleapis.com/customsearch/v1?key=INSERT-YOUR-KEY&cx=017576662512468239146:omuauf_lfve&q=lectures";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_USERAGENT, 'Opera/9.23 (Windows NT 5.1; U; en)');
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
## Below two option will enable the HTTPS option.
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
$result = curl_exec($ch);
echo $result;
If you can't modify the config yourself, talk to the hosting provider. It most probably has to do with the lacking of openssl in the php core or startup.
If you are doing this for someone else and you have no control or contact with the host (the "some external host"), explain the situation and help them find a suitable host with the appropriate features enabled.

Categories