After a user makes a payment they are returned to this page:
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-synch';
$tx_token = $_GET['tx'];
$auth_token = "REMOVEDFROMQUESTION";
$req .= "&tx=$tx_token&at=$auth_token";
// 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";
// url for paypal sandbox
$fp = fsockopen ('www.sandbox.paypal.com', 80, $errno, $errstr, 30);
// url for payal
// $fp = fsockopen ('www.paypal.com', 80, $errno, $errstr, 30);
// If possible, securely post back to paypal using HTTPS
// Your PHP server will need to be SSL enabled
// $fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);
if (!$fp) {
// HTTP ERROR
echo "http error";
} else {
fputs ($fp, $header . $req);
// read the body data
$res = '';
$headerdone = false;
while (!feof($fp)) {
$line = fgets ($fp, 1024);
if (strcmp($line, "\r\n") == 0) {
// read the header
$headerdone = true;
}
else if ($headerdone) {
// header has been read. now read the contents
$res .= $line;
}
}
// parse the data
$lines = explode("\n", $res);
$keyarray = array();
if (strcmp ($lines[0], "SUCCESS") == 0) {
for ($i=1; $i<count($lines);$i++){
list($key,$val) = explode("=", $lines[$i]);
$keyarray[urldecode($key)] = urldecode($val);
}
// 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
$firstname = $keyarray['first_name'];
$lastname = $keyarray['last_name'];
$itemname = $keyarray['item_name'];
$amount = $keyarray['payment_gross'];
echo ("<p><h3>Thank you for your purchase!</h3></p>");
echo ("<b>Payment Details</b><br>\n");
echo ("<li>Name: $firstname $lastname</li>\n");
echo ("<li>Item: $itemname</li>\n");
echo ("<li>Amount: $amount</li>\n");
echo ("");
}
else if (strcmp ($lines[0], "FAIL") == 0) {
// log for manual investigation
echo "fail";
} else {
echo "fail2";
}
}
fclose ($fp);
Paypal is succesfully returning the user to the page with correct GET variables:
?status=success&tx=203229VT863344T&st=Pending&amt=76.00&cc=GBP&cm=19&item_number=
But when the script is run it returns "error2". When I try to output the response I get nothing.
Thanks for the help.
You should post back to:
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
And not:
$fp = fsockopen ('www.sandbox.paypal.com', 80, $errno, $errstr, 30);
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>";
}
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.
PayPal documentation is make my head spinning!
I has copied sample from somewhere to setup auto return upon payment completion, I created a page called success.php to grab returned params, somehow I was not success to display those returned params, can anyone expert in Paypal please help to check what's wrong with below code?
success.php
<?php
$req = 'cmd=_notify-synch';
$tx_token = $_GET['tx'];
$auth_token = "ZgTzjTg49XZGeD54WsS";
$req .= "&tx=".$tx_token."&at=".$auth_token;
foreach($_POST as $key => $value){
$value = urlencode(stripslashes($value));
$req .= '&'.$key.'='.$value;
}
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Host: http://www.sandbox.paypal.com\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: ".strlen($req)."\r\n\r\n";
// url for paypal sandbox
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
if(!$fp){
// HTTP ERROR
}else{
fputs($fp, $header . $req);
// read the body data
$res = '';
$headerdone = false;
while(!feof($fp)){
$line = fgets ($fp, 1024);
if(strcmp($line, '\r\n') == 0){
// read the header
$headerdone = true;
}else if($headerdone){
// header has been read. now read the contents
$res .= $line;
}
}
// parse the data
$lines = explode('\n', $res);
$keyarray = array();
if(strcmp($lines[0], 'SUCCESS') == 0){
for($i=1; $i<count($lines);$i++){
list($key,$val) = explode('=', $lines[$i]);
$keyarray[urldecode($key)] = urldecode($val);
}
// 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
$firstname = $keyarray['first_name'];
$lastname = $keyarray['last_name'];
$itemname = $keyarray['item_name'];
$amount = $keyarray['payment_gross'];
echo '<p><h3>Thank you for your purchase!</h3></p>';
echo '<b>Payment Details</b><br>';
echo '<ul>';
echo '<li>Name: '.$firstname.' '.$lastname.'</li>';
echo '<li>Item: '.$itemname.'</li>';
echo '<li>Amount: '.$amount.'</li>';
echo '</ul>';
}else if(strcmp($lines[0], 'FAIL') == 0){
// log for manual investigation
}
}
fclose($fp);
?>
Your transaction has been completed, and a receipt for your purchase has been emailed to you.<br>
This is auto returned URL:
http://sitename.com/success.php?tx=88L2235578117773M&st=Completed&amt=318.00&cc=USD&cm=2013-23&item_number=&sig=HzS1ku7OeDrZJVZcXta6X9jrf71vct7Spstv0%2bW7lxj%2bqRtQXBDO9pqs%2bhmzaoSGs6EDjpEFCnPwOGYzlZ1FMbyw%2fIpF6%2bVMFCNDBYuLdFTYkWaiwG70IpyEMGFFNh1aJUsn3W%2fQK6ad6HOC7%2fzccQPUebhMSqp4WBw%2bRw%2f4tw4%3d
I find that using the Sandbox is not very good for final testing, so once you have established that you code is working, it is best to go live and then test with $1 transactions.
Also, you won't get all of your customer's order details returned, so it is better to simply retrieve the order number and populate your receipt from a database record that was created prior to sending details to Paypal.
The data to retrieve for your invoice number will be found as Request("item_number")
I am using codeigniter library called paypal_class. Everything is fine, but at validate ipn function i get this error. Use of undefined constant host - assumed 'host' which must be the reason that mail is not being sent to the user. Nothing is returned.
I am new to paypal. So i hope for a detailed solution. Thank you. Please ask whatever other information you may require.
Error is at this line:
$fp = fsockopen($url_parsed[host], "80", $err_num, $err_str, 30);
where
$url_parsed = parse_url($this->paypal_url);
here is the ipn function:
function validate_ipn() {
// parse the paypal URL
$url_parsed = parse_url($this->paypal_url);
// generate the post string from the _POST vars aswell as load the
// _POST vars into an arry so we can play with them from the calling
// script.
$post_string = '';
foreach ($_POST as $field => $value) {
$this->ipn_data["$field"] = $value;
$post_string .= $field . '=' . urlencode(stripslashes($value)) . '&';
}
$post_string.="cmd=_notify-validate"; // append ipn command
// open the connection to paypal
$fp = fsockopen($url_parsed['host'], "80", $err_num, $err_str, 30);
if (!$fp) {
// could not open the connection. If loggin is on, the error message
// will be in the log.
$this->last_error = "fsockopen error no. $errnum: $errstr";
$this->log_ipn_results(false);
return false;
} else {
// Post the data back to paypal
fputs($fp, "POST $url_parsed[path] HTTP/1.1\r\n");
fputs($fp, "Host: $url_parsed[host]\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: " . strlen($post_string) . "\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $post_string . "\r\n\r\n");
// loop through the response from the server and append to variable
while (!feof($fp)) {
$this->ipn_response .= fgets($fp, 1024);
}
fclose($fp); // close connection
}
if (preg_match("/VERIFIED/i", $this->ipn_response)) {
// Valid IPN transaction.
$this->log_ipn_results(true);
return true;
} else {
// Invalid IPN transaction. Check the log for details.
$this->last_error = 'IPN Validation Failed.';
$this->log_ipn_results(false);
return false;
}
}
you need to change this:
$fp = fsockopen($url_parsed[host], "80", $err_num, $err_str, 30);
to
$fp = fsockopen($url_parsed['host'], "80", $err_num, $err_str, 30);
then debug the returned value here do:
$url_parsed = parse_url($this->paypal_url);
var_dump($url_parsed);
How do I debug the ipn.php file when using the paypal sandbox ipn simulator tool?
The code looks like this:
// 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);
if (!$fp) {
// HTTP ERROR
} else {
fputs($fp, $header.$req);
while (!feof($fp)) {
$res = fgets($fp, 1024);
if (strcmp($res, "VERIFIED") == 0) {
$DBH = new PDO("mysql:host=localhost;dbname=db", "user", "pass");
$DBH - > setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$STH = $DBH - > prepare("update table2 set status = :status where tracking_id = :tracking_id");
$status = 1;
parse_str($req, $data);
$STH - > bindParam(':status', $status, PDO::PARAM_INT, 1);
$STH - > bindParam(':tracking_id', 'id_goes_here', PDO::PARAM_STR, 50);
$STH - > execute();
$DBH = null;
} else if (strcmp($res, "INVALID") == 0) {
// do something else
}
}
fclose($fp);
}
I normally use netbeans debug facility to debug, but how do I debug using the sandbox simulator? When I click send ipn from the sandbox ipn simulator, I get a message in the sandbox saying IPN successfully sent., but when I then go into my database to check the status, it's still 0.
Maybe problem is in parameter binding
$STH - > bindParam(':tracking_id', 'id_goes_here', PDO::PARAM_STR, 50);
if table 'table2' do not contain row with tracking_id = 'id_goes_here' update action will fail.
Try this
<?php
$testMode = false;
$url = 'https://www.paypal.com/cgi-bin/webscr';
if ($testMode === true)
$url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
$ipnResponse = ''; // holds the IPN response from paypal
$ipnData = array(); // array will contain the POST values for IPN
$urlParsed = parse_url($url);
$req = 'cmd=_notify-validate'; // Add 'cmd' to req (ipn command)
// Read the post from PayPal system and add them to req
foreach ($_POST as $key => $value) {
$ipnData["$key"] = $value;
$value = urlencode(stripslashes($value));
$req .= "&" . $key . "=" . $value;
}
// Open the connection to paypal
$fp = fsockopen($urlParsed['host'], "80", $errno, $errstr, 30);
// If could open the connection and check response
if ($fp) {
fputs($fp, "POST " . $urlParsed['path'] . " HTTP/1.1\r\n");
fputs($fp, "Host: " . $urlParsed['host'] . "\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: " . strlen($req) . "\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $req . "\r\n\r\n");
// Loop through the response from the server and append to variable
while (!feof($fp)) {
$ipnResponse .= fgets($fp, 1024);
}
fclose($fp);
// Valid IPN transaction.
if (preg_match('/^VERIFIED/', $ipnResponse)) {
// Some action on IPN validation - update payment status etc
die("OK. IPN Validation: Success");
}
// Invalid IPN transaction
else {
// Some action on IPN validation - update payment status etc
die("ERROR. IPN Validation: Failed");
}
}
// Else no connection, so maybe wrong url or other reasons, you can do another call later
else {
die("ERROR. IPN Connection: fsockopen error");
}
?>
In general when I want to debug a script that doesn't provide direct output in the browser, I call a simple logging function throughout the script to output variable values or help determine where errors are occurring.
When I have no idea where the script is dying, I write a line to a log file after each significant line of code. After running the script and then checking the log file I can see exactly which line caused the script to die, a very simplified example is below. Of course after everything is running smoothly all of the logging should be removed.
public function logToFile($msg){
$file = 'log.txt';
$current = file_get_contents($file);
$current .= $msg . "\n";
file_put_contents($file, $current);
}
public function doOtherStuff(){
foreach ($_POST as $key => $value) {
$ipnData["$key"] = $value;
$value = urlencode(stripslashes($value));
$req .= "&" . $key . "=" . $value;
}
logToFile("1");
$fp = fsockopen($urlParsed['host'], "80", $errno, $errstr, 30);
logToFile("2");
if ($fp) {
logToFile("3");
fputs($fp, "POST " . $urlParsed['path'] . " HTTP/1.1\r\n");
logToFile("4");
fputs($fp, "Host: " . $urlParsed['host'] . "\r\n");
logToFile("5");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
logToFile("6");
fputs($fp, "Content-length: " . strlen($req) . "\r\n");
logToFile("7");
fputs($fp, "Connection: close\r\n\r\n");
logToFile("8");
fputs($fp, $req . "\r\n\r\n");
logToFile("9");
while (!feof($fp)) {
logToFile("10");
$ipnResponse .= fgets($fp, 1024);
}
logToFile("11");
fclose($fp);
}
}