I am using the following code for paypal ipn:
<?php
mysql_connect("localhost", "user", "password") or die(mysql_error());
mysql_select_db("PayPal") or die(mysql_error());
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
// post back to PayPal system to validate
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);
if (!$fp) {
// HTTP ERROR
} else {
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0) {
// PAYMENT VALIDATED & VERIFIED!
}
else if (strcmp ($res, "INVALID") == 0) {
// PAYMENT INVALID & INVESTIGATE MANUALY!
}
}
fclose ($fp);
}
?>
After testing in every which way, I am getting everything to work except when:
if (strcmp ($res, "VERIFIED") == 0)
does not work
if (strcmp ($res, "VERIFIED") == 1)
WORKS
Obviously its not getting verified as I'm sending IPN from sandbox.
What could be missing?
Since you both say that strcmp($res, "VERIFIED") == 1 is true, $res is 1 character "bigger" than the string VERIFIED. My guess is that $res has a \n character at the end or something else that needs to be stripped. Try doing something like str_replace('\n', '', $res) before calling the lines with strcmp. Just thinking out loud though. If this is not working, let me know.
Fyi, PayPal has sample code online to verify an IPN in PHP using cURL.
Link: http://www.x.com/developers/paypal/documentation-tools/paypal-code-samples#instantpaymentnotification
Related
I'm having some issues with my notify_url in PayPal. The handshake is fine, but the code to update my DB doesn't work. So to debug, I'm using the return.php url to output some data and try to debug and echo where the problem is.
Here is what I did so far to debug (on return.php)
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value)
{
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
echo "<br>test REQ: ".$req."<br><br>";;
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
if (!$fp)
{
echo "FP NOT WORKIGN";
}
else
{
echo "FP WORKIGN<br><br>";
fputs ($fp, $header . $req);
while (!feof($fp))
{
echo "whie: YES<br>";
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0)
{
echo "verified<br>";
if($status == "Completed")
{
echo "<br>####### completed<br>";
}
}
}
}
My result is I get the echo of REQ, I get the echo of FP Working, I get echo "WHILE YES" 5 times, but I don't the echo of "VERIFIED". SO it seems the script doesn't get pass the if (strcmp ($res, "VERIFIED") == 0)
I'm stuck now, how can I fix this issue? Not sure what's wrong
This is the echo of my $req (if it helps to debug)
test: cmd=_notify-validate&mc_gross=1.00&protection_eligibility=Ineligible&payer_id=3EW5DFETD3E4L&tax=0.00&payment_date=15%3A35%3A43+Nov+14%2C+2016+PST&payment_status=Completed&charset=windows-1252&first_name=test&mc_fee=0.33¬ify_version=3.8&custom=1000%40%40Katia%40%40213+st-louis%40%40lemoyne%40%40quebec%40%40j4r+2l3%40%40Canada%40%401%40%40CAD%40%400%40%401.00&payer_status=verified&business=louisefrigon1-facilitator%40gmail.com&quantity=1&payer_email=louisefrigon1-buyer%40gmail.com&verify_sign=AFcWxV21C7fd0v3bYYYRCpSSRl31AchhgWj8TBE3e7K7SSx6jHwconuT&txn_id=6E11719159210262F&payment_type=instant&last_name=buyer&receiver_email=louisefrigon1-facilitator%40gmail.com&payment_fee=&receiver_id=LMCZ83V6LRE4S&txn_type=web_accept&item_name=Superfood+Powder&mc_currency=CAD&item_number=&residence_country=CA&test_ipn=1&handling_amount=0.00&transaction_subject=&payment_gross=&shipping=0.00&merchant_return_link=click+here&auth=A1CZ8ecFDP.O-dZHCSU6ouq8Gxn8qrDXHyoUX9qI-CEmFlvuS1Rq8FlqPmP8dCqlTffcxTJX84-huLEvRi5C.fA
The result of fgets() includes the newline, but "VERIFIED" doesn't have a newline. You need to strip it off before comparing.
$res = trim(fgets($fp, 1024));
There's also no point in using strcmp() if you just want to test if two strings are equal, just use ==.
if ($res == "VERIFIED") {
...
}
But instead of trying to do the HTTP protocol yourself, use curl.
$req = 'cmd=_notify-validate&' . http_build_query($_POST);
$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
$res = curl_exec($ch);
if ($res == "VERIFIED") {
echo "verified<br>";
if($status == "Completed")
{
echo "<br>####### completed<br>";
}
} else {
echo "$res<br>";
}
I have the same issue like PayPal Instant Payment Notification Warning. I have two sites. I have the ipn url set in paypal account to site1. But I'm sending notify_url in paypal form for current site. My verification code on both sites:
public function paymentCheck()
{
$request = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$request .= "&$key=$value";
}
$header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($request) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);
if (!$fp)
return false;
else {
fputs ($fp, $header . $request);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp ($res, "INVALID") == 0) {
return false;
}
}
fclose ($fp);
}
return true;
}
My sites handle ipn. All working fine. But some of paypal messages is failing and they turned it off. Do you have any ideas, what can cause warnings?
It means that for some reason PayPal is getting something other than a 200 OK response back from your script. If it looks like your script is working it could mean that all of the tasks are completing, but then an issue at the very end causes a failure that you don't even see other than the fact that PayPal isn't getting a good response back.
You need to check your web server logs for the times when your IPN script was hit and look at the results. You'll probably find a bunch of them that show 500 or something other than 200. You should also be able to see the error details there, too, and get it resolved.
So I'm trying to send a custom variable with a Paypal adaptive payment and when Paypal does its IPN with the file that I specified in the selling preferences on my Paypal account, the custom variable is empty. My Curl code works fine and the response envelope returns successful. I echoed the post fields before sending them and this is what I got (sensitive data censored):
actionType=PAY&clientDetails.applicationId=[app
ID]&clientDetails.ipAddress=[my ip]
¤cyCode=USD&feesPayer=EACHRECEIVER&memo=[my
memo]&custom=1Ad2Ad8Ad9&receiverList.receiver(0).amount=1&receiverList.receiver(0).email=[email1]&receiverList.receiver(0).primary=true&receiverList.receiver(1).amount=0.2&receiverList.receiver(1).email=[email2]&receiverList.receiver(1).primary=false&receiverList.receiver(2).amount=0.19&receiverList.receiver(2).email=[email3]&receiverList.receiver(2).primary=false&receiverList.receiver(3).amount=0.16&receiverList.receiver(3).email=[email4]&receiverList.receiver(3).primary=false&requestEnvelope.errorLanguage=en_US&returnUrl=[return
url]&cancelUrl=[cancel url]
The custom variable is in tact and exactly as I want it. On the other hand I noticed that the currencyCode field was changed to "¤cyCode" somehow. I have no clue why but when I changed it to an array and used print_r, it said currencyCode.
Anyway the problem that I'm having comes up when Paypal does its instant notification to my Confirm.php and runs the following code:
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
// post back to PayPal system to validate
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);
if (!$fp) {
// HTTP ERROR
} else {
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0) {
$strEmail = $_POST[ "payer_email" ];
if( isset( $_POST[ "custom" ] ) == true )
{
$strQuery = "UPDATE TTest SET TestField = 'posted: " . $_POST[ "custom" ] . "' WHERE id = 1";
}
// Execute
mysql_query( $strQuery );
}
else if (strcmp ($res, "INVALID") == 0) {
}
}
fclose ($fp);
}
The $_POST[ "custom" ] variable appears to be empty because it only sets TestField to "posted: " every time.
Can someone please tell me whats wrong with this code.
I am trying for payment integration with Paypal with html form. I have specified the notify_url, payment goes all right but i am not able to enter in this block if (strcmp($res, "VERIFIED") == 0){}
// Response from Paypl
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$value = preg_replace('/(.*[^%^0^D])(%0A)(.*)/i', '${1}%0D%0A${3}', $value); // IPN fix
$req .= "&$key=$value";
}
// assign posted variables to local variables
$data['item_name'] = $_POST['item_name'];
// post back to PayPal system to validate
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
if (!$fp) {
// HTTP ERROR
echo 'HTTP ERROR';
} else {
file_put_contents('test1.txt', 'test');
fputs($fp, $header . $req);
while (!feof($fp)) {
$res = fgets($fp, 1024);
if (strcmp($res, "VERIFIED") == 0) {
echo 'SUCCESS';
} else if (strcmp($res, "INVALID") == 0) {
echo 'INVALID';
}
}
fclose($fp);
}
Use CuRl method to POST data back instead of fsock here is link:https://developer.paypal.com/webapps/developer/docs/classic/ipn/ht_ipn/ or My suggestion is Use AngellaEye library which is more effective and useful for Paypal integration here is link:http://www.angelleye.com/how-to-integrate-paypal-with-php-class-library/
Download it from this link and go throgh it.
I just realized that my paypal ipn handler in php doesn't work anymore (and I change nothing), I use the sample php script provided by paypal.
I tried to isolate the problem by making several test, and at this time I can say that the problem is not the "VERIFIED" or the "INVALID" thing but comes from these lines:
[...]
fputs ($fp, $header . $req);
while (!feof($fp))
{
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0)
{
// check the payment_status is Completed
[...]
Anyone know if paypal change something or why it doesn't work?
thanks'
ps: if I put my code before all the paypal tests (before the line "if (!$fp)") it just works fine
This is my code, I comment where the "database process" works and where it doesn't.
<?php
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value)
{
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
// post back to PayPal system to validate
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
// assign posted variables to local variables
$payment_status = $_POST['payment_status'];
// DATABASE PROCESS WORKS (BEFORE THE PAYPAL TESTS)
if (!$fp)
{
// HTTP ERROR
}
else
{
// DATABASE PROCESS WORKS
fputs ($fp, $header . $req);
while (!feof($fp))
{
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0)
{
// check the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process payment
// DATABASE PROCESS NOT WORKING
}
else if (strcmp ($res, "INVALID") == 0)
{
// log for manual investigation
// DATABASE PROCESS NOT WORKING
}
}
fclose ($fp);
}
?>
try using the updated script on x.xom
https://www.x.com/instant-payment-notification-4
it uses CURL instead of fsock
This error occurred when server not configured properly for socket or openSSL module not configured.
OR
You can try with below code sample of using file_get_contents instead of $fp code
<?php
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
// for live mode
$url="https://www.paypal.com/cgi-bin/webscr";
// for developement mode
$url="https://www.sandbox.paypal.com/cgi-bin/webscr";
// instead of use of fopen you can use
$res=file_get_contents($url"?".$req);
// compare response
if (strcmp (trim($res), "VERIFIED") == 0) {
// check the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process payment
}
else if (strcmp (trim($res), "INVALID") == 0) {
// log for manual investigation
}
?>
if file_get_contents not working then you can use CURL for getting response...
Let me know if have any question?
Thanks