I've just finish implementing a Payment Gateway Server that supports Paypal. The gateway also has an adaptive IPN server for Paypal and Skrill notifications. During implementation and tests, I used the documentation provided by Paypal's IPN manual. During tests, everything went "All Okay". I test it with the example given by the documentation, "All Okay":
mc_gross=19.95&protection_eligibility=Eligible&address_status=confirmed&payer_id=LPLWNMTBWMFAY&tax=0.00&address_street=1+Main+St&payment_date=20%3A12%3A59+Jan+13%2C+2009+PST&payment_status=Completed&charset=windows-1252&address_zip=95131&first_name=Test&mc_fee=0.88&address_country_code=US&address_name=Test+User¬ify_version=2.6&custom=&payer_status=verified&address_country=United+States&address_city=San+Jose&quantity=1&verify_sign=AtkOfCXbDm2hu0ZELryHFjY-Vb7PAUvS6nMXgysbElEn9v-1XcmSoGtf&payer_email=gpmac_1231902590_per%40paypal.com&txn_id=61E67681CH3238416&payment_type=instant&last_name=User&address_state=CA&receiver_email=gpmac_1231902686_biz%40paypal.com&payment_fee=0.88&receiver_id=S8XGHLYDW9T3S&txn_type=express_checkout&item_name=&mc_currency=USD&item_number=&residence_country=US&test_ipn=1&handling_amount=0.00&transaction_subject=&payment_gross=19.95&shipping=0.00
The problem started when we deployed the gateway to our production server, and went testing with the simulation form provided by Paypal's IPN Simulator. Well, when I clicked the Send IPN button, the message didn't reached my server, and after a few seconds (more like minutes), an HTTP error status response appeared:
Yes 502 Bad Gateway! What the heck is that?!? The message did not even got to server. A few remarks, we are not using the standard 80/443 ports, and we only support "POST" messages. Again the IPN message is not getting into our server, we test it with other testing tools, and the message arrives successfully.
Please help!
>> We are using Express Checkout by the way!
You should avoid putting the host in your headers.
Change this:
$header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
$header .= "Host: www.paypal.com\r\n"; *****DELETE THIS LINE*****
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
For this:
$header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
Related
I am trying to reproduce some HTTP requests I launched with the Postman Chrome extension on a PowerShell script.
The goal of my request is to recieve a ticket by logging in to a CAS server.
I wrote the following PowerShell (I used [variable] notation for anonymisation purposes) :
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true} ;
$postParams = #{username='[username]';password='[password]'}
Invoke-WebRequest -Uri https://[host]:[port]/cas/v1/tickets/ -Method POST -
Body $postParams'
But the Tomcat server answers with a HTTP 404 error whereas the same request on Postman provides me with the ticket and works perfectly.
404 indicates that something is wrong with the URL you are sending the request. You could use fiddler to trace the request and check the URL
A perl script that has been running ok for two years just began returning "500 SSL Handshake Failure" errors upon postback of IPN message. My host service supports SHA 256, TLS 1.2 and HTTP/1.1. I'm using my host service's shared cert.
The code (from PayPal's sample script):
# read post from PayPal system and add 'cmd'
read (STDIN, $query, $ENV{'CONTENT_LENGTH'});
$query .= '&cmd=_notify-validate';
# post back to PayPal system to validate
$ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 1 });
$req = HTTP::Request->new('POST', 'https://www.sandbox.paypal.com/cgi-bin/webscr');
$req->content_type('application/x-www-form-urlencoded');
$req->header(Host => 'www.sandbox.paypal.com');
$req->content($query);
$res = $ua->request($req);
if ($res->is_error) {
# HTTP error
$retmsg = "HTTP Error:<br />";
$retmsg .= $res->status_line();
}
...
How do I best troubleshoot this?
According to SSLLabs the site is TLS 1.2 only, that it it does not accept TLS 1.0 or TLS 1.1. And according to your comment you are using OpenSSL version 1.0.0e (1000005f). But this version does not support TLS 1.2 yet because such support was only added with version 1.0.1.
This means that your system is too old to support TLS 1.2. You need to upgrade at least the OpenSSL version but preferable the whole system. Note that it does not help to just install a new version of OpenSSL. Instead you would need to recompile all the modules in Perl which make use of the library, i.e. especially Net::SSLeay in this case.
I have the following perl script to send pipelined http request over a sinlge tcp connection. The first request goes through and i am able to get the response. The second reqeust also gets sent, but no response is received for this request. I am able to see both requests being received on the server in the trace.
use IO::Socket::INET;
$| = 1;
$socket = new IO::Socket::INET (
PeerHost => '10.102.218.56',
PeerPort => '80',
Proto => 'tcp',);
die "cannot connect to the server $!\n" unless $socket;
print "connected to the server\n";
# data to send to a server
my $req = "GET /test/file5.html HTTP/1.1\r\nHost:10.102.218.50\r\nAccept: */*\r\n\r\n\r\n";
my $size = $socket->send($req);
print "1. sent data of length $size\n";
$socket->recv($response, 1024);
print "received response: $response\n";
my $req = "GET /test/file5.html HTTP/1.1\r\nHost:10.102.218.50\r\nAccept: */*\r\n\r\n\r\n";
my $size = $socket->send($req);
print "1. sent data of length $size\n";
$socket->recv($response, 1024);
print "received response: $response\n";
sleep 1;
$socket->close();
On the Apache access_log i see only one instance of the HTTP request being received :
10.102.218.50 - - [02/Sep/2014:23:04:50 +0530] "GET /test/file5.html HTTP/1.1" 200 6 "-" "-"
I am guessing that I am missing some characters that indicate the end of an HTTP request of the server. But i am not able to find what they are.
What am i doing wrong here?
Edit: Could the Apache server be closing the connection after the first HTTP request is answered. Is there a setting for this?
Edit2: KeepAlive was set to Off on my apache server. Setting it to ON fixes the issue.
Found the problem. The KeepAlive was set to off on my Apache server. Setting the KeepAlive to On fixed the problem.
I have a problem with push notification in my app. I just started to work with push notifications so I dont know what's the reason of my problem, and i cant find the solution in google.
So, I used this tutorial http://www.raywenderlich.com/3443/apple-push-notification-services-tutorial-part-12 as the example of programming of push notifications. When I run "php simplepush.php" on my terminal everything is fine and I get the notification on my device. But when I load that script on the server and trying to run it from there there is no actions performed. only 30 sec of waiting and message "Failed to connect: 110 Connection timed out"
Here os the code of my script
<?php
Put your device token here (without spaces):
$deviceToken = '***************';
// Put your private key's passphrase here:
$passphrase = '**************';
// Put your alert message here:
$message = 'My first push notification!';
////////////////////////////////////////////////////////////////////////////////
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);
echo 'Connected to APNS' . PHP_EOL;
// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);
// Encode the payload as JSON
$payload = json_encode($body);
// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));
if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;
// Close the connection to the server
fclose($fp);
Yes, as NewObjective clarified, 2195 & 2196 ports have to be open. To open these ports you might ask Bluehost technical support team (ticket/chat), but you have to have dedicated IP address before that.
But there is another issue. If you try to send push notification message right after dedicated IP address is set and both ports are open you might receive the same "Connection timed out" error. You can test that problem by logging in to your server via SSH and running "telnet gateway.sandbox.push.apple.com 2195" command. If you receive "Connection timed out" error - you can try to contact Bluehost support team, but they can't solve this problem.
If you try to telnet any other server with 2195 opened port you will also receive that error. I had about 10 chats with Bluehost support team, opened 10 or so tickets, but they really couldn't help me. But two weeks later everything began to work. I think it was because turning dedicated IP on takes some time, but I'm not sure. Anyway, it very interesting that Bluehost support team always answers that the problem is on the Apple side, even if you tell them that any other server with 2195 opened port isn't available too)
I have meet a big problem when I was doing developing about Apple Push Notification Service.
I wrote a PHP script(apns.php) which will use a PEM(ck.pem) file as security certificate and build a SSL connection to APNS when I post a HTTP request to it, but it always failed when it tried to connect the service port ( ssl://gateway.sandbox.push.apple.com:2195). The PHP script is deployed on a Linux Hosting of GoDaddy (it should support SSL).
I have already registered to be a member of iOS developer program,and I have registered the apple push notification service for my application. And I have generated a certificate file and a key file (cert.p12 and key.p12) from Keychain Access and translate them into PEM files(cert.pem and key.pem) and join them into one(ck.pem) and put it in the same directory of PHP script .
I want to know if there is something wrong I did ! Would you refer to the attachment of the files that you may need?
Thanks very much!
The HTTP request is something like below.
http://www.insidertracker.net/apns/apns.php?message=&badge=2&sound=received5.caf
The response message of my request is below:
Warning: stream_socket_client() [function.stream-socket-client]:
unable to connect to ssl://gateway.sandbox.push.apple.com:2195
(Connection refused) in /home/content/40/6967940/html/apns/apns.php on
line 25 Failed to connect 111 Connection refused
The PHP script:
<?php
$deviceToken = '0535dda1 6fd04e87 ed0a8194 d418a6c1 99eec462 8a871891 d062018d c6af4f99';
$pass = 'Php1234'; // Passphrase for the private key (ck.pem file)
// Get the parameters from http get or from command line
$message = $_GET['message'] or $message = $argv[1] or $message = 'You have an important message from InsiderTracker';
$badge = (int)$_GET['badge'] or $badge = (int)$argv[2];
$sound = $_GET['sound'] or $sound = $argv[3];
// Construct the notification payload
$body = array();
$body['aps'] = array('alert' => $message);
if ($badge)
$body['aps']['badge'] = $badge;
if ($sound)
$body['aps']['sound'] = $sound;
/* End of Configurable Items */
$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
// assume the private key passphase was removed.
stream_context_set_option($ctx, 'ssl', 'passphrase', $pass);
// connect to apns
$fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
// $fp = fsockopen('ssl://gateway.sandbox.push.apple.com:2195', 2195, $err, $errstr, 30);
if (!$fp) {
print "Failed to connect $err $errstr\n";
return;
}
else {
print "Connection OK\n<br/>";
}
// send message
$payload = json_encode($body);
$msg = chr(0) . pack("n",32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack ("n",strlen($payload)) . $payload;
print "Sending message :" . $payload . "\n";
fwrite($fp, $msg);
fclose($fp);
?>
It's my understanding that GoDaddy prohibits outgoing connections on exotic ports (anything other than 80 a perhaps a few others). You're probably out of luck trying to roll your own push service hosted on GoDaddy. I have had luck doing what you're attempting with bluehost.
For general advice on developing a push service in PHP, these two articles were invaluable: One Two
I also got this error. Following things you have to remember:
Path of ios push cert file should be correct. Check on online portals using device token and push cert.
Your server is enabled for 2195 port. Check on terminal by using telnet command.
Check ssl supported by your php version if using ssl://gateway.sandbox.push.apple.com and tls if using tls://gateway.sandbox.push.apple.com
The data you are sending in the push or token etc should be equal or less than the specified bytes mentioned in the apple doc. link is mentioned below.
You can also use api get reference for sending push Development server: api.development.push.apple.com:443 Production server: api.push.apple.com:443
https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW1