问题
First, Thanks for your attention. Comes to prob.
I'm using this IPN Listener code:
// IPN LISTENER
// intercetta le variabili IPN inviate da PayPal
$req = 'cmd=_notify-validate';
// legge l'intero contenuto dell'array POST
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
// intestazione, prepara le variabili PayPal per la validazione
$header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Host: www.sandbox.paypal.com\r\n"; // www.paypal.com for a live site
$header .= "Content-Length: " . strlen($req) . "\r\n";
$header .= "Connection: close\r\n\r\n";
// apre una connessione al socket PayPal
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
// converte le variabili inviate da IPN in variabili locali
$txn_id = filter_var($_POST['txn_id'], FILTER_SANITIZE_STRING);
$payment_status = filter_var($_POST['payment_status'], FILTER_SANITIZE_STRING);
$receiver_email = filter_var($_POST['receiver_email'], FILTER_SANITIZE_EMAIL);
$payer_email = filter_var($_POST['payer_email'], FILTER_SANITIZE_EMAIL);
$first_name = filter_var($_POST['first_name'], FILTER_SANITIZE_STRING);
$last_name = filter_var($_POST['last_name'], FILTER_SANITIZE_STRING);
$address_street = filter_var($_POST['address_street'], FILTER_SANITIZE_STRING);
$address_city = filter_var($_POST['address_city'], FILTER_SANITIZE_STRING);
$address_state = filter_var($_POST['address_state'], FILTER_SANITIZE_STRING);
$address_zip = filter_var($_POST['address_zip'], FILTER_SANITIZE_STRING);
// verifica l'apertura della connessione al socket
if (!$fp) {
// se la connessione non avviene l'esecuzione dello script viene bloccata
print("connessione PayPal non avvenuta, si prega di riprovare piu' tardi");
// in alternativa è per esempio possibile inviare un'email al venditore
} else {
// elaborazione delle informazioni
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
// azioni in caso di risposta positiva da parte di PayPal
if (stripos($res, "VERIFIED") !== false) {
$myvariables = 1;
$anothermyvariables = "INSERT INTO MyDB ( paid, name, email, date)
VALUES ('". $txn_id ."','" . $first_name ." ". $last_name . "','" . $payer_email ."','". the_date('Y-m-d','','',FALSE) . "');";
$wpdb->query($anothermyvariables);
}
}
// azione in caso di risposta negativa da parte di PayPal else
if (stripos($res, "INVALID") !== false) {
$anothervariablesofmine = 2;
$paypalerr = "Pagamento non riuscito!"; // Payment not success!
}
}
// chiusura della sorgente di dati
fclose($fp);
It did work previously, but not now... I've tested the variables that PayPal return to my website with var_dump and payment_status=Completed. They seem ok.
I've tested if connection is established and also it works:
if (!$fp) {
ecc..
} else {
print("Connection Established");
etc....
The problem comes with variables stripos($res, "VERIFIED") stripos($res, "INVALID").
var_dump returns both as bool (false).
Looking on Sandbox profile History (of buyer and seller), all transactions results are completed. But the thing that makes me crazy is that one week later works perfectly... I've searched about maybe some change in IPN listener port, host or variables by PayPal but seems none has changed. Right?
I wrote the IPN Listener directly in the page of buying form, this mean IPN Listener is called also without $_POST variables. Only possible reply for me is a spam protection from IPN Listener in PayPal side that blocked me, it's possible? 'Cause the Listener is called also without cmd=_notify-validate, but simply it just don't work (but made a blank call that perhaps isn't very appreciated by PayPal).
EDIT:
Sorry guys, re-debugged (God bless var_dump).
Putted var_dump in while loop so:
....
while (!feof($fp)) {
$res = fgets ($fp, 1024);
var_dump(stripos($res, "VERIFIED"));
print("<br> VERIFIED". stripos($res, "VERIFIED") ."<br>");
var_dump(stripos($res, "INVALID"));
print("<br> INVALID". stripos($res, "INVALID") ."<br>");
...
and find one VERIFIED int(0) instead of bool (false)
I have just changed
if (stripos($res, "VERIFIED") !== false) {
to
if (stripos($res, "VERIFIED") == 0) {
I think same in INVALID case.
But I'm still not sure if this is right.
That was the problem? Or may I have to change something else? May I have to use both if conditions (if == 0 and if !== false)?
PayPal Just changed VERIFIED return value?
回答1:
What worked for me was to remove the connection close header, and add a trim to the response back from PP. Here are the headers:
$header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Host: www.paypal.com\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
Here is the fsockopen:
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);
and here is the trim on the response back from PP:
if (!$fp) {
// HTTP ERROR
error_mail("Could not open socket");
//
} else {
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = trim(fgets ($fp, 1024));
}
//
// check the payment_status is Completed
// check that receiver_email is your Primary PayPal email
//
if ((strcmp ($res, "VERIFIED") == 0) && ($payment_status == "Completed") && ($receiver_email == $valid_receiver_email)) {
That worked for me.
回答2:
I had a similar problem, fixed as follows :
From time to time, when my listener posts back the cmd=_notify-validate to check a new IPN, you'll get something other than "VERIFIED" or "INVALID" back.
Sometimes I get this :
'8'.chr(13).chr(10).'VERIFIED'.chr(13).chr(10).'0'.chr(13).chr(10).chr(13).chr(10)
Sometimes I get this :
'00000008'.chr(13).chr(10).'VERIFIED'.chr(13).chr(10).'00000000'.chr(13).chr(10).chr(13).chr(10))
I think if you check for those two strings in addition to "VERIFIED" or "INVALID" you'll be fine. If not, show me what you ARE getting back from paypal that is failng your stripos($res, "VERIFIED") and stripos($res, "INVALID") tests.
Also worth noting I sometimes get an error from an intermediate cache or my ISP, or paypal just times out.. so your code needs to be able to recover from that by doing cmd=_notify-validate for that IPN later.
Lastly... I struggled with IPN systems for many years. It's always a bit unreliable, the documentation is seriously wrong in a couple of places, and IPNs lag behind transactions, often by 15 minutes or more.
I have found it is far better is to use the TransactionSearch and GetTransactionDetails methods of the API.
Documentation here :
https://developer.paypal.com/docs/classic/api/merchant/GetTransactionDetails_API_Operation_NVP/
https://developer.paypal.com/docs/classic/api/merchant/TransactionSearch_API_Operation_NVP/
These are reliable and have much less lag. I have a cron job that runs every 15 minutes to check for new transactions using those methods. I also run the new transaction check every time I receive an IPN. Let me know if you want further guidance on implementing.
来源:https://stackoverflow.com/questions/17158335/paypal-ipn-listener-wont-work-anymore