?
Solved

PayPal Payment Approval Notification

Posted on 2009-04-29
16
Medium Priority
?
1,586 Views
Last Modified: 2013-12-12
I use PayPal on my site to accept payments. The user chooses the amount on page A and is then taken to page B, where I create the form that takes the user to PayPal with the information to process the payment (see code).

I now need to get confirmation that they payment has gone through in real time.

I have reviewed the PayPal APIs and I have not been able to integrate their code into my site to give me the notification I want. I have an API signature, password and certificate, but I can't figure out a safe way include them.

I also need to know how to poll the PayPal site to confirm the transaction completed successfully.
<form target="paypal"action="https://www.paypal.com/cgi-bin/webscr"   method="post">
   <input type="hidden" name="add" value="1">
   <input type="hidden" name="cmd" value="_cart">
   <input type="hidden" name="business" value="xxxxxx@gmail.com">
   <input type="hidden" name="item_name" value="User Credits">
   <input type="hidden" name="invoice" value="".$SESSION['username'].date("Ymd")."">
   <input type="hidden" name="amount" value="".$_POST['credit']."">
   <input type="hidden" name="return" value="http://www.xxxxxx.com/paypal_accepted.php">
<input type="hidden" name="cancel_return" value="http://www.xxxxxx.com/paypal_cancelled.php">
   <input type="hidden" name="no_shipping" value="1">
   <input type="hidden" name="no_note" value="1">
   <input type="hidden" name="currency_code" value="USD">
   <input type="hidden" name="tax" value="0">
   <input type="hidden" name="bn" value="IC_Sample">
<p>You are purchasing ".$_POST['credit']." credits from us for $".number_format($_POST['credit'], 2)." US$</p>
<p> Click the "Buy Now" Button to Complete This Transaction</p><br />
   <div class='message'><img src='images/site_logo.gif' alt='' /><input type="image" src="https://www.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="Make payments with PayPal -       it's fast, free and secure!">
   <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif width="1" height="1"></div>
</form>

Open in new window

0
Comment
Question by:birwin
  • 8
  • 5
  • 3
16 Comments
 
LVL 36

Expert Comment

by:Loganathan Natarajan
ID: 24267132
0
 
LVL 6

Author Comment

by:birwin
ID: 24267213
thanks Logudotcom.
The PHP code from the PayPal site shows below. Does this go in the http://www.xxxxxx.com/paypal_accepted.php? How is that code initiated?
Do I need to send the password / username / certificate with the original post? If yes, how do I do that?
// 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);
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
if (!$fp) {
// HTTP ERROR
} else {
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
}
else if (strcmp ($res, "INVALID") == 0) {
// log for manual investigation
}
}
fclose ($fp);
}
?>
0
 
LVL 36

Expert Comment

by:Loganathan Natarajan
ID: 24267220
After you post the values to the paypal , it will process and made transaction... you need to mention about the response page while you post...

on the response page, you need to retrieve the details (using IPN services)...

just print the response...
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 6

Author Comment

by:birwin
ID: 24267616
I tried this using the paypal sandbox. I put the code above in the paypal_approved.php, which is the return link from paypal.
I got this error:
Warning: fsockopen() [function.fsockopen]: unable to connect to ssl://www.paypal.com:443 (Unable to find the socket transport "ssl" - did you forget to enable it when you configured PHP?) in /home/nuggets/public_html/paypal_accepted.php on line 15
Line 15 is:
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);
any idea why?
 
0
 
LVL 18

Expert Comment

by:Sudaraka Wijesinghe
ID: 24267824
I think it's https://www.paypal.com not ssl://www.paypal.com
0
 
LVL 36

Expert Comment

by:Loganathan Natarajan
ID: 24267868
yes, it is https://palpal.com
0
 
LVL 6

Author Comment

by:birwin
ID: 24273511
I changed it to https and got this error:
Warning: fsockopen() [function.fsockopen]: unable to connect to https://www.paypal.com:443 (Unable to find the socket transport "https" - did you forget to enable it when you configured PHP?) in /home/xxxxxx/public_html/paypal_accepted.php on line 49
0
 
LVL 6

Author Comment

by:birwin
ID: 24273582
Note: The page on my site is not ssl. Does it need to be?
0
 
LVL 18

Expert Comment

by:Sudaraka Wijesinghe
ID: 24276390
try it with out any protocol specification on the host name:
$fp = fsockopen ('www.paypal.com', 443, $errno, $errstr, 30);
I think fsocketopen only accept the host name.

I always use curl as listed below (if it helps)

$http=curl_init("https://www.paypal.com/cgi-bin/webscr");
curl_setopt($http, CURLOPT_POST,1);
curl_setopt($http, CURLOPT_POSTFIELDS, $strPOSTData."&cmd=_notify-validate");
curl_setopt($http, CURLOPT_RETURNTRANSFER,1);
$strVerification=curl_exec($http);
curl_close($http);

Open in new window

0
 
LVL 6

Author Comment

by:birwin
ID: 24284926
Thank you for the suggestions.
This is getting very frustrating. I removed the ssl and https from the url and the error stopped, but I get no reponse from the program.
Using the paypal sandbox, I made a payment and returned to my site. The code about is on the landing page. I get no reponse from the code.
if I add a printout of the values
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
echo"key is $key and value is $value<br />";
$req .= "&$key=$value";
}
Nothing prints.
$res has no value.
Any idea what I am doing wrong?
0
 
LVL 18

Expert Comment

by:Sudaraka Wijesinghe
ID: 24284973
Hi birwin,

Please make sure of the following:

1. IPN is enabled on your PayPal account.
2. You setup the correct callback Url (full Url, not just relative path) on the PayPal account or you are sending it with each request to PayPal from your shopping cart or what ever: <input type="hidden" name="notify_url" value="http://domain/paypal.ipn.php" />
3. Make sure paypal.com is accessible from your web server (not the browser).

Also, from what you said above, it seems you are looking for IPN data on the page that you return to from pay pal payment process (from your browser, maybe I'm wrong?) IPN is NOT sent to the Url you specify on RETURN parameter, unless of cause you configured like that, but still it won't be in the same session.
Create a page to handle the IPN post back from PayPal and write it to a text file or DB for debugging.

If possible please attache your IPN handling page also.

Hope this helps.
0
 
LVL 6

Author Comment

by:birwin
ID: 24286702
Thank you sudaraka:
I think I made this more complicated than it had to be. I was trying to use the full API when I really just need the IPN. I set up my client's account with the IPN settings, although I am using my personal developer's sandbox to test the results. Am I right to assume that the sandbox would be sending the correct IPN data? If not, how do I ask it to do so?
Below is the code I am now using, which is somewhat different than I show above. I found on the PayPal forum, the Curl code which does not create the errors. There were a number of postings that said that the fp version wouldn't work on Apache.
The code now doesn't show an error, but I get a "NO DATA" error message.
Yes, I do have the code on the customer's approved page. As I understand your comment, I should have a separate page that PayPal can post to that is different from the customer's approved page. Isn't the page indicated as the return page in the code the one that PayPal uses to return the customer to the site? If not, how do I indicate the page that PayPal should use to send me the data?
When I applied for the IPN, was given a token. I don't see any place that the token is used. Is it used in the verification process?
I appreciate your help with this.

Checkout Code:
 
<?
 
$successurl="http://www.xxxxxxxxxxxx.com/paypal_accepted.php";
$cancelurl="http://www.xxxxxxxxxx.com/paypal_cancelled.php";
 
//<form target="paypal"action="https://www.paypal.com/cgi-bin/webscr"   method="post">    
 
 
<form target="paypal"action="https://sandbox.paypal.com/cgi-bin/webscr"   method="post">
 
  <form target="paypal"action="https://sandbox.paypal.com/cgi-bin/webscr"   method="post">
   <input type="hidden" name="add" value="1">
   <input type="hidden" name="cmd" value="_cart">
   <input type="hidden" name="business" value="xxxxxx_1241074915_biz@xxxxxxxxxxxxx.com">";    
 
   echo"
   <input type="hidden" name="item_name" value="Credits">
   <input type="hidden" name="invoice" value="".$SESSION['username'].date("YmdHms")."">
   <input type="hidden" name="amount" value="".$_POST['credit']."">
   <input type="hidden" name="return" value="$successurl">
<input type="hidden" name="cancel_return" value="$cancelurl">
   <input type="hidden" name="no_shipping" value="1">
   <input type="hidden" name="no_note" value="1">
   <input type="hidden" name="currency_code" value="USD">
   <input type="hidden" name="tax" value="0">
   <input type="hidden" name="bn" value="IC_Sample">
<p>You are purchasing ".$_POST['credit']." credits from xxxxxxxx for $".number_format($_POST['credit'], 2)." US$</p>
<p> Click the "Buy Now" Button to Complete This Transaction</p><br />
   <div class='message'><img src='images/site_logo.gif' alt='' /><input type="image" src="https://www.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="Make payments with PayPal -       it's fast, free and secure!">
   <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif width="1" height="1"></div>
</form>
?>
 
 
The recieving page code has a bunch of code to dump the return data into a database, but the basic code to verify is:
 
<?
 
// read the post from PayPal system and add 'cmd'
if($_SERVER['REQUEST_METHOD']!="POST") die("No data");
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
 
// post back to PayPal system to validate
$url=(!isset($_POST['test_ipn'])) ? 'https://www.paypal.com/cgi-bin/webscr' : 'https://www.sandbox.paypal.com/cgi-bin/webscr';
 
    $curl_result=$curl_err='';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req)));
    curl_setopt($ch, CURLOPT_HEADER , 0);   
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
 
    $curl_result = @curl_exec($ch);
    $curl_err = curl_error($ch);
    curl_close($ch);
 
//are we verified? If so, let's process the IPN
if (strpos($curl_result, "VERIFIED")!==false) 
{
$APPROVED_FLAG=1;
}
?>

Open in new window

0
 
LVL 18

Accepted Solution

by:
Sudaraka Wijesinghe earned 2000 total points
ID: 24286838
Hi birwin,

1. You can use paypal sandbox to simulate IPN. It allow you to set each parameter so you can simulate different types of IPN calls.
https://developer.paypal.com/cgi-bin/devscr?cmd=_ipn-link-session

2. You get the "No Data" message because you are trying to process IPN on the customer's approved page. You may have configured the customer approved page as the IPN handler, but PayPal won't send IPN data back to this page with the customer (or in other words, the same session as customer returning to your page).
IPN will be sent in a separate HTTP request, which you will not see. Only way to monitor that is to log the incoming HTTP POST data to a file or DB.

3. In order to specify IPN handling Url with each shopping cart or buy now request, you have to use the notify_ur parameter like below. It has to be in the html from that you post to PayPal.
<input type="hidden" name="notify_url" value="http://domain/pagename" />

4. Is the token you mentioned a 13 character alphanumeric string? If so, that would be your receiver id, which you can use to verify the IPN requests to make sure that they belong to your merchant account.

I have attached a code of a IPN handling page from one of my sites. It just log the transaction in DB and let PayPal know all is done.

Feel free to ask any Qs you have.

//Check parameteres to verify notification
if(
	strtoupper($_REQUEST["txn_type"])!="WEB_ACCEPT" &&
	strtoupper($_REQUEST["txn_type"])!="CART"
) exit;
if($_REQUEST["business"]!=__PAYPAL_ACCOUNT) exit;
if($_REQUEST["test_ipn"]==1) exit; //Ignore sandbox IPNs
 
//Verify Notification
$strPOSTData="";
foreach($_REQUEST as $key=>$val)
{
	if(strtoupper($key)=="PHPSESSID") continue;
	
	if(strlen($strPOSTData)>0) $strPOSTData.="&";
	$strPOSTData.="$key=$val";
}
 
//Save to DB
$objPPL=new PaypalLog();
$objPPL->add($strPOSTData);
unset($objPPL);
 
if(strtoupper($_REQUEST["payment_status"])!="COMPLETED") exit;
 
$http=curl_init(__PAYPAL_IPN_VERIFICATION_URL);
curl_setopt($http, CURLOPT_POST,1);
curl_setopt($http, CURLOPT_POSTFIELDS, $strPOSTData."&cmd=_notify-validate");
curl_setopt($http, CURLOPT_RETURNTRANSFER,1);
$strVerification=curl_exec($http);
curl_close($http);
 
exit;

Open in new window

0
 
LVL 6

Author Closing Comment

by:birwin
ID: 31576292
Thank you so much for your help. I had not understood that the IPN was separate from their API process and I was getting nowhere. Thank you for spotting the issue.
0
 
LVL 6

Author Comment

by:birwin
ID: 24287803
Hi sudaraka:
One question I had was how the response from Curl is handled. I assume that $strVerification holds some indication that the handshake was made. Do I need to test that variable to make sure it is valid?
Thank you again for your help and clarification.
0
 
LVL 18

Expert Comment

by:Sudaraka Wijesinghe
ID: 24288699
Hi birwin,

curl_exec will return the HTTP POST data PayPal return to us for the _notify-validate request we sent. (because CURLOPT_RETURNTRANSFER is set to 1).
I think it would be a query string style name value pair and you can parse that for further verification if you need to.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Build an array called $myWeek which will hold the array elements Today, Yesterday and then builds up the rest of the week by the name of the day going back 1 week.   (CODE) (CODE) Then you just need to pass your date to the function. If i…
Businesses who process credit card payments have to adhere to PCI Compliance standards. Here’s why that’s important.
Viewers will get an overview of the benefits and risks of using Bitcoin to accept payments. What Bitcoin is: Legality: Risks: Benefits: Which businesses are best suited?: Other things you should know: How to get started:
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.
Suggested Courses
Course of the Month16 days, 11 hours left to enroll

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question