Configure Wordpress to receive Paypal IPN notifications - php

I'm using Wordpress in my Website. I have attached a few plugins for processing purchase content on my website. I use the Easy Digital Downloads (https://wordpress.org/plugins/easy-digital-downloads) plugin for managing sales of digital content and Paypal IPN for WordPress (https://wordpress.org/plugins/paypal-ipn/) to get transaction details from my Paypal account.
I have to create an account on sandbox.paypal.com to test whether all functions are running properly or not. For the management of the plugin Easy Digital Downloads, current account and recorded properly. However I did not get a report on the Paypal IPN for WordPress plugin. I have entered the URL in the plugin into my Paypal account as an address when the transaction report. However I did not get a report from paypal altogether.
So I think to create their own web pages from scratch without a wordpress plugin and run all functions on top of the PHP script. So, am I better keep using Wordpress or rebuild the website from scratch by writing my own script.
If you have a reference about the use of the wordpress plugin, please share it in the comments. Thanks for your help.

First you will need to create a custom WordPress page and configure Paypal IPN script to post and get data. on such page you can also add features to store the data on a database, send it by mail, add cron jobs or whatever other IPN scripts ...
Also, you need to visit paypal website and set the ipn link, then post there the data from your website and configure it to post back to the url of the wordpress site with the page to receive paypal ipn post data...
here is a page example:
<?php
class PayPal_IPN{
function infotuts_ipn($im_debut_ipn) {
define('SSL_P_URL', 'https://www.paypal.com/cgi-bin/webscr');
define('SSL_SAND_URL', 'https://www.sandbox.paypal.com/cgi-bin/webscr');
$hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']);
if (!preg_match('/paypal\.com$/', $hostname)) {
$ipn_status = 'Validation post isn\'t from PayPal';
if ($im_debut_ipn == true) {
// mail test
}
return false;
}
// parse the paypal URL
$paypal_url = ($_REQUEST['test_ipn'] == 1) ? SSL_SAND_URL : SSL_P_URL;
$url_parsed = parse_url($paypal_url);
$post_string = '';
foreach ($_REQUEST as $field => $value) {
$post_string .= $field . '=' . urlencode(stripslashes($value)) . '&';
}
$post_string.="cmd=_notify-validate"; // append ipn command
// get the correct paypal url to post request to
$paypal_mode_status = $im_debut_ipn; //get_option('im_sabdbox_mode');
if ($paypal_mode_status == true)
$fp = fsockopen('ssl://www.sandbox.paypal.com', "443", $err_num, $err_str, 60);
else
$fp = fsockopen('ssl://www.paypal.com', "443", $err_num, $err_str, 60);
$ipn_response = '';
if (!$fp) {
// could not open the connection. If loggin is on, the error message
// will be in the log.
$ipn_status = "fsockopen error no. $err_num: $err_str";
if ($im_debut_ipn == true) {
echo 'fsockopen fail';
}
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)) {
$ipn_response .= fgets($fp, 1024);
}
fclose($fp); // close connection
}
// Invalid IPN transaction. Check the $ipn_status and log for details.
if (!preg_match("/VERIFIED/s", $ipn_response)) {
$ipn_status = 'IPN Validation Failed';
if ($im_debut_ipn == true) {
echo 'Validation fail';
print_r($_REQUEST);
}
return false;
} else {
$ipn_status = "IPN VERIFIED";
if ($im_debut_ipn == true) {
echo 'SUCCESS';
}
return true;
}
}
function ipn_response($request){
mail("sanjeev00733#gmail.com","My subject",print_r($request,true));
$im_debut_ipn=true;
if ($this->infotuts_ipn($im_debut_ipn)) {
// if paypal sends a response code back let's handle it
if ($im_debut_ipn == true) {
$sub = 'PayPal IPN Debug Email Main';
$msg = print_r($request, true);
$aname = 'infotuts';
//mail send
}
// process the membership since paypal gave us a valid +
$this->insert_data($request);
}
}
function issetCheck($post,$key){
if(isset($post[$key])){
$return=$post[$key];
}
else{
$return='';
}
return $return;
}
function insert_data($request){
require_once('dbconnect.php');
$post=$request;
$item_name=$this->issetCheck($post,'item_name');
$amount=$this->issetCheck($post,'mc_gross');
$currency=$this->issetCheck($post,'mc_currency');
$payer_email=$this->issetCheck($post,'payer_email');
$first_name=$this->issetCheck($post,'first_name');
$last_name=$this->issetCheck($post,'last_name');
$country=$this->issetCheck($post,'residence_country');
$txn_id=$this->issetCheck($post,'txn_id');
$txn_type=$this->issetCheck($post,'txn_type');
$payment_status=$this->issetCheck($post,'payment_status');
$payment_type=$this->issetCheck($post,'payment_type');
$payer_id=$this->issetCheck($post,'payer_id');
$create_date=date('Y-m-d H:i:s');
$payment_date=date('Y-m-d H:i:s');
mysqli_query($con,"INSERT INTO infotuts_transection_tbl (item_name,payer_email,first_name,last_name,amount,currency,country,txn_id,txn_type,payer_id,payment_status,payment_type,create_date,payment_date)
VALUES ('$item_name','$payer_email','$first_name','$last_name','$amount','$currency','$country','$txn_id','$txn_type','$payer_id','$payment_status','$payment_type','$create_date','$payment_date')");
mysqli_close($con);
}
}
$obj = New PayPal_IPN();
$obj->ipn_response($_REQUEST);
?>

Related

Paypal sandBox transaction value store database?

I am Currently using Paypal in my site.Now checking in Paypal Sandbox account. I have Created test account in Sandbox.its my code using PHP with MySQL. After Sandbox Transaction i have store IPN data in to My local Database? Previously its working code Now not Working...
<?php
class paypal_class {
var $last_error; // holds the last error encountered
var $ipn_log; // bool: log IPN results to text file?
var $ipn_log_file; // filename of the IPN log
var $ipn_response; // holds the IPN response from paypal
var $ipn_data = array(); // array contains the POST values for IPN
var $fields = array(); // array holds the fields to submit to paypal
function paypal_class() {
// initialization constructor. Called when class is created.
$this->paypal_url = 'https://www.paypal.com/cgi-bin/webscr';
//$this->paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
$this->last_error = '';
$this->ipn_log_file = '.ipn_results.log';
$this->ipn_log = true;
$this->ipn_response = '';
$this->add_field('rm','2'); // Return method = POST
$this->add_field('cmd','_xclick');
}
function add_field($field, $value) {
$this->fields["$field"] = $value;
}
function submit_paypal_post() {
echo "<html>\n";
echo "<head><title>Processing Payment...</title></head>\n";
echo "<body onLoad=\"document.forms['paypal_form'].submit();\">\n";
echo "<center><h2>Please wait, your order is being processed and you";
echo " will be redirected to the paypal website.</h2></center>\n";
echo "<form method=\"post\" name=\"paypal_form\" ";
echo "action=\"".$this->paypal_url."\">\n";
foreach ($this->fields as $name => $value) {
echo "<input type=\"hidden\" name=\"$name\" value=\"$value\"/>\n";
}
echo "<center><br/><br/>If you are not automatically redirected to ";
echo "paypal within 5 seconds...<br/><br/>\n";
echo "<input type=\"submit\" value=\"Click Here\"></center>\n";
echo "</form>\n";
echo "</body></html>\n";
}
function validate_ipn() {
// parse the paypal URL
$url_parsed=parse_url($this->paypal_url);
$post_string="cmd=_notify-validate";
foreach ($_POST as $field=>$value) {
$this->ipn_data["$field"] = $value;
// $post_string .= $field.'='.urlencode(stripslashes($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 (eregi("VERIFIED",$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;
}
}
function log_ipn_results($success) {
if (!$this->ipn_log) return; // is logging turned off?
// Timestamp
$text = '['.date('m/d/Y g:i A').'] - ';
// Success or failure being logged?
if ($success) $text .= "SUCCESS!\n";
else $text .= 'FAIL: '.$this->last_error."\n";
// Log the POST variables
$text .= "IPN POST Vars from Paypal:\n";
foreach ($this->ipn_data as $key=>$value) {
$text .= "$key=$value, ";
}
// Log the response from the paypal server
$text .= "\nIPN Response from Paypal Server:\n ".$this->ipn_response;
// Write to log
$fp=fopen($this->ipn_log_file,'a');
fwrite($fp, $text . "\n\n");
fclose($fp); // close file
}
function dump_fields() {
echo "<h3>paypal_class->dump_fields() Output:</h3>";
echo "<table width=\"95%\" border=\"1\" cellpadding=\"2\" cellspacing=\"0\">
<tr>
<td bgcolor=\"black\"><b><font color=\"white\">Field Name</font></b></td>
<td bgcolor=\"black\"><b><font color=\"white\">Value</font></b></td>
</tr>";
ksort($this->fields);
foreach ($this->fields as $key => $value) {
echo "<tr><td>$key</td><td>".urldecode($value)." </td></tr>";
}
echo "</table><br>";
}
}
Paypal.php:
<?php
require_once($_SERVER['DOCUMENT_ROOT'].'/Abaceu/lms/conf.php');
require_once('LMS_functions.php');
require_once('paypal.class.php'); // include the class file
//$email = "behavior.solutions.training#gmail.com";
$email = "pixel.thennarasu#gmail.com"; //for testing in sandbox paypal
$p = new paypal_class; // initiate an instance of the class
$p->paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; // testing paypal url
//$p->paypal_url = 'https://www.paypal.com/cgi-bin/webscr'; // paypal url
// setup a variable for this script (ie: 'http://www.micahcarrick.com/paypal.php')
$this_script = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
// if there is not action variable, set the default action of 'process'
if (empty($_GET['action']))
{
$_GET['action'] = 'process';
}
$cid=$_POST['courseid'];
switch ($_GET['action'])
{
case 'process': // Process and order...
$p->add_field('business', $email);
$p->add_field('return', $this_script.'?action=success');
$p->add_field('cancel_return', $this_script.'?action=cancel');
$p->add_field('notify_url', $this_script.'?action=ipn');
$p->add_field('item_number',$cid); //June04,2010 courseid,coursename were added to insert second course
$p->add_field('item_name',$_POST['coursename']);
$p->add_field('amount', '50.00');
$p->submit_paypal_post(); // submit the fields to paypal
//$p->dump_fields(); // for debugging, output a table of all the fields
break;
case 'success': // Order was successful...
/
include("thank_you.php");
break;
case 'cancel': // Order was canceled...
// The order was canceled before being completed.
echo "<html><head><title>Canceled</title></head><body><h3>The order was canceled.</h3>";
echo "</body></html>";
break;
case 'ipn': // Paypal is calling page for IPN validation...
if ($p->validate_ipn())
{
// For this example, we'll just email ourselves ALL the data.
$subject = 'Instant Payment Notification - Recieved Payment';
$to = $email; // your email
$body = "An instant payment notification was successfully recieved\n";
$body .= "from ".$p->ipn_data['payer_email']." on ".date('m/d/Y');
$body .= " at ".date('g:i A')."\n\nDetails:\n";
foreach ($p->ipn_data as $key => $value) { $body .= "\n$key: $value"; }
mail($to, $subject, $body);
//code to instant message after payment written on July 22,2010 as per client request
$subject1 = 'Instant message for Course Account information';
$toaddress = $p->ipn_data['payer_email']; // your email
$body1 = "Thank you very much for your course purchase from ABACEU.COM! You will get the login information shortly. Sometimes It can take several hours depending on the processing speed of the Paypal server \n\n";
$body1 .= "THIS IS AN AUTOMATED MESSAGE FROM ABACEU.COM\n\n";
$body1 .= "\n".date('m/d/Y');
$headers1 = "From: abaceu#abaceu.com" . "\r\n"."CC: behavior.solutions.training#gmail.com";
mail($toaddress, $subject1, $body1, $headers1);
// update_LMS( $p->ipn_data ,$dir_usercourselist);
update_LMS( $p->ipn_data ,$dir_usercourselist, $cid); //June04,2010 : For inserting new course
}
break;
}
?>
Any mistake my code. Please Let me know? Information not stored in database

PayPal IPN Listener works inside sandbox but not outside

I am running this PayPal IPN listener written by tutsplus, it's modified a bit to suit my needs. Everything worked fine until I have moved from sandbox to live mode. I have went over the code, and don't quite understand if I need to switch anything or it is checking for sandbox/live itself.
<?php
class PayPal_IPN{
function infotuts_ipn($im_debut_ipn) {
define('SSL_P_URL', 'https://www.paypal.com/cgi-bin/webscr');
define('SSL_SAND_URL', 'https://www.sandbox.paypal.com/cgi-bin/webscr');
$hostname = gethostbyaddr($_SERVER['REMOTE_ADDR']);
if (!preg_match('/paypal\.com$/', $hostname)) {
$ipn_status = 'Validation post isn\'t from PayPal';
if ($im_debut_ipn == true) {
// mail test
}
return false;
}
// parse the paypal URL
$paypal_url = ($_REQUEST['test_ipn'] == 1) ? SSL_SAND_URL : SSL_P_URL;
$url_parsed = parse_url($paypal_url);
$post_string = '';
foreach ($_REQUEST as $field => $value) {
$post_string .= $field . '=' . urlencode(stripslashes($value)) . '&';
}
$post_string.="cmd=_notify-validate"; // append ipn command
// get the correct paypal url to post request to
$paypal_mode_status = $im_debut_ipn; //get_option('im_sabdbox_mode');
if ($paypal_mode_status == true)
$fp = fsockopen('ssl://www.sandbox.paypal.com', "443", $err_num, $err_str, 60);
else
$fp = fsockopen('ssl://www.paypal.com', "443", $err_num, $err_str, 60);
$ipn_response = '';
if (!$fp) {
// could not open the connection. If loggin is on, the error message
// will be in the log.
$ipn_status = "fsockopen error no. $err_num: $err_str";
if ($im_debut_ipn == true) {
echo 'fsockopen fail';
}
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)) {
$ipn_response .= fgets($fp, 1024);
}
fclose($fp); // close connection
}
// Invalid IPN transaction. Check the $ipn_status and log for details.
if (!preg_match("/VERIFIED/s", $ipn_response)) {
$ipn_status = 'IPN Validation Failed';
if ($im_debut_ipn == true) {
echo 'Validation fail';
print_r($_REQUEST);
}
return false;
} else {
$ipn_status = "IPN VERIFIED";
if ($im_debut_ipn == true) {
echo 'SUCCESS';
}
return true;
}
}
function ipn_response($request){
mail("mssoad#gmail.com","My subject",print_r($request,true));
$im_debut_ipn=true;
if ($this->infotuts_ipn($im_debut_ipn)) {
// if paypal sends a response code back let's handle it
if ($im_debut_ipn == true) {
$sub = 'PayPal IPN Debug Email Main';
$msg = print_r($request, true);
$aname = 'infotuts';
//mail send
}
// process the membership since paypal gave us a valid +
$this->insert_data($request);
}
}
function issetCheck($post,$key){
if(isset($post[$key])){
$return=$post[$key];
}
else{
$return='';
}
return $return;
}
function insert_data($request){
require_once('dbconnect.php');
$post=$request;
$item_name=$this->issetCheck($post,'item_name');
$amount=$this->issetCheck($post,'mc_gross');
$currency=$this->issetCheck($post,'mc_currency');
$payer_email=$this->issetCheck($post,'payer_email');
$first_name=$this->issetCheck($post,'first_name');
$last_name=$this->issetCheck($post,'last_name');
$country=$this->issetCheck($post,'residence_country');
$txn_id=$this->issetCheck($post,'txn_id');
$txn_type=$this->issetCheck($post,'txn_type');
$payment_status=$this->issetCheck($post,'payment_status');
$payment_type=$this->issetCheck($post,'payment_type');
$payer_id=$this->issetCheck($post,'payer_id');
$date=$this->issetCheck($post,'custom');
$create_date=date('Y-m-d H:i:s');
$payment_date=date('Y-m-d H:i:s');
$firstLast = $first_name . $last_name;
$explode = explode('|', $item_name);
foreach($explode as $slot) {
if(strlen($slot) > 0) {
$query = "INSERT INTO bookings (date, start, name, email, phone, order_id) VALUES ('$date', '$slot', '$firstLast', '$payer_email', '$phone', '$orderid')";
$result = mysqli_query($con, $query) or die(mysqli_error($link));
} // Close if
} // Close foreach
mysqli_query($con,"INSERT INTO trans_tbl (item_name,ride_day,payer_email,first_name,last_name,amount,currency,country,txn_id,txn_type,payer_id,payment_status,payment_type,create_date,payment_date)
VALUES ('$item_name','$date','$payer_email','$first_name','$last_name','$amount','$currency','$country','$txn_id','$txn_type','$payer_id','$payment_status','$payment_type','$create_date','$payment_date')");
mysqli_close($con);
}
}
$obj = New PayPal_IPN();
$obj->ipn_response($_REQUEST);
?>
On the IPN History of the paypal website it is stuck at sent - resending.
I have setup IPN settings and notify URL in profile settings, and have a business account. My email is verified on the account as well.
Another thing to note, I have been doing simple $0.01 to test this outside sandbox mode, and the return page is working fine just not the ipn listener.
Any help is much appreciated, thanks.
$paypal_mode_status = $im_debut_ipn; //get_option('im_sabdbox_mode');
if ($paypal_mode_status == true)
$fp = fsockopen('ssl://www.sandbox.paypal.com', "443", $err_num, $err_str, 60);
else
$fp = fsockopen('ssl://www.paypal.com', "443", $err_num, $err_str, 60);
Could be incorrect, you should test to confirm, but I think it's because your $im_debut_ipn variable, when set to TRUE, is not only "debugging" but for some reason is also being used to determine the paypal url. It then sets the url to be paypals sandbox url (see above).
i.e, When
$im_debut_ipn = true
then,
$fp = fsockopen('ssl://www.sandbox.paypal.com', "443", $err_num, $err_str, 60);
is also true.
Note that I think $im_debut_ipn is actually a typo and should be ..debug.., meaning a debug mode that lets error messages be shown.

How do I use Paypal to sell something and have something in SQL change after the payment is confirmed?

I have a website I am making in PHP and I need to sell an online product. When someone buys this product I need a way to have my website notified and change some information in an SQL table. I have googled this for the past five hours and I read things about paypal IPN and paypal sandbox. I am still very confused about what paypal IPN is and how to use it. As for paypal sandbox, several tutorials for what I am asking say to use paypal sandbox. I have tried, but every time I try to login to my account it says the password is wrong, and when I try to make another it redirects me to paypal.com.
My main question is: How do I make buying something on paypal change information in an SQL table on my website?
Update:
I have been trying to use this tutorial: http://www.evoluted.net/thinktank/web-development/paypal-php-integration
I have this php code here (modified from the tutorial):
<?php // Database variables
$host = "localhost"; //database location
$user = "user"; //database username
$pass = "pass"; //database password
$db_name = "db"; //database name
// PayPal settings
$paypal_email = 'my sandbox business email is here';
$return_url = 'http://painlessnotes.com/';
$cancel_url = 'http://painlessnotes.com/';
$notify_url = 'http://painlessnotes.com/Paypal/payments.php';
$item_name = 'Test Item';
$item_amount = 10.00;
// Include Functions
include("functions.php");
//Database Connection
$link = mysql_connect($host, $user, $pass);
mysql_select_db($db_name);
// Check if paypal request or response
if (!isset($_POST["txn_id"]) && !isset($_POST["txn_type"])){
echo "<script type='text/javascript'>alert('send start');</script>";
$querystring = "";
// Firstly Append paypal account to querystring
$querystring .= "?business=".urlencode($paypal_email)."&";
// Append amount& currency (£) to quersytring so it cannot be edited in html
//The item name and amount can be brought in dynamically by querying the $_POST['item_number'] variable.
$querystring .= "item_name=".urlencode($item_name)."&";
$querystring .= "amount=".urlencode($item_amount)."&";
//loop for posted values and append to querystring
foreach($_POST as $key => $value){
$value = urlencode(stripslashes($value));
$querystring .= "$key=$value&";
}
// Append paypal return addresses
$querystring .= "return=".urlencode(stripslashes($return_url))."&";
$querystring .= "cancel_return=".urlencode(stripslashes($cancel_url))."&";
$querystring .= "notify_url=".urlencode($notify_url);
// Append querystring with custom field
//$querystring .= "&custom=".USERID;
echo "<script type='text/javascript'>alert('{$querystring}');</script>";
// Redirect to paypal IPN
header('location:https://www.sandbox.paypal.com/cgi-bin/webscr'.$querystring);
exit();
}else{
// Response from Paypal
mail("my email", "response", "TEST", "From: my email is here");//I am using this to check if it works
// 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'];
$data['item_number'] = $_POST['item_number'];
$data['payment_status'] = $_POST['payment_status'];
$data['payment_amount'] = $_POST['mc_gross'];
$data['payment_currency'] = $_POST['mc_currency'];
$data['txn_id'] = $_POST['txn_id'];
$data['receiver_email'] = $_POST['receiver_email'];
$data['payer_email'] = $_POST['payer_email'];
$data['custom'] = $_POST['custom'];
// 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 {
mail('my email', '0', '0');//used to check if it works
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0) {
// Validate payment (Check unique txnid & correct price)
$valid_txnid = check_txnid($data['txn_id']);
$valid_price = check_price($data['payment_amount'], $data['item_number']);
// PAYMENT VALIDATED & VERIFIED!
if($valid_txnid && $valid_price){
$orderid = updatePayments($data);
if($orderid){
// Payment has been made & successfully inserted into the Database
}else{
// Error inserting into DB
// E-mail admin or alert user
}
}else{
// Payment made but data has been changed
// E-mail admin or alert user
}
}else if (strcmp ($res, "INVALID") == 0) {
// PAYMENT INVALID & INVESTIGATE MANUALY!
// E-mail admin or alert user
}
}
fclose ($fp);
}
}
?>
The receiving part of this code works when I use IPN simulator in developer.paypal.com for paypal sandbox. The functions.php and the html code giving in the tutorial is the same as what is in the tutorial. When I test this I get the javascript alert boxes coming up and it all looks correct to me, but for some reason I am not getting a response after sending the paypal sandbox request.
What am I doing wrong and how do I fix it? I have create a buyer with a normal paypal account in the sandbox and a business account.
After doing more research and searching I found a paypal page called Paypal Integration Wizard.
This will generate the code needed for what I have asked. It gives a step by step process and is easy to follow. After reading the code I now understand more on how it works.

PHP Paypal IPN: transaction not confirmed

I'm creating an IPN for a custom digital ecommerce but i have a problem:
everything works file,i create a "pending payment" in my database with an ID that i call PID (payment id),the user go to the paypal page and when the payment is completed paypal contact me on the IPN listener that checks if the payment is completed and enable all the media that the user bought.
I successfully created an IPN using the micah carrick php class
( http://www.micahcarrick.com/php-paypal-ipn-integration-class.html ) and everything is working exept i ALWAYS get a pendign payment status and i can't get a confirmed one.
I'm currently testing it in the paypal sandbox,i created 2 buyers and one seller and i have enabled the "payment review" for everybody.
I tryed also different approach but i always get the same result.
Code:
file_put_contents('ipn.log',"\n>IPN\n",FILE_APPEND);
//Check the Payment ID,i pass it to the IPN by GET
if(!isset($_GET['pid'])|| !is_numeric($_GET['pid'])){
file_put_contents('ipn.log',"\n!!!IPN:INVALID PID(".$_GET['pid'].")!!!\n",FILE_APPEND);
exit('PID INVALIDO!');
}
//Logging errors
ini_set('log_errors', true);
ini_set('error_log', dirname(__FILE__).'/ipn_errors.log');
// instantiate the IpnListener class
require('ipnlistener.php');
$listener = new IpnListener();
//Use the sandbox instead of going "live"
$listener->use_sandbox = true;
//validate the request
try {
$listener->requirePostMethod();
$verified = $listener->processIpn();
}
catch (Exception $e) {
error_log($e->getMessage());
exit(0);
}
//Just for debug
file_put_contents('ipn.log',"\n###IPN:verifying...###\n",FILE_APPEND);
if($verified){//the payment is verified
file_put_contents('ipn.log',"\n###IPN:transaction verified(confirmed=".$_POST['payment_status'].")###\n".$listener->getTextReport(),FILE_APPEND);
/*
Once you have a verified IPN you need to do a few more checks on the POST
fields--typically against data you stored in your database during when the
end user made a purchase (such as in the "success" page on a web payments
standard button). The fields PayPal recommends checking are:
1. Check the $_POST['payment_status'] is "Completed"
2. Check that $_POST['txn_id'] has not been previously processed
3. Check that $_POST['receiver_email'] is your Primary PayPal email
4. Check that $_POST['payment_amount'] and $_POST['payment_currency']
are correct
Since implementations on this varies, I will leave these checks out of this
example and just send an email using the getTextReport() method to get all
of the details about the IPN.
*/
if($_POST['payment_status']=="Completed"){
//--check if the price is right and enable the user media--
confirm_payment($_GET['pid'],$_POST['payment_amount']);
file_put_contents('ipn.log',"\n###IPN:Transaction completed###\n".$listener->getTextReport(),FILE_APPEND);
}
}
else {
/*
An Invalid IPN *may* be caused by a fraudulent transaction attempt. It's
a good idea to have a developer or sys admin manually investigate any
invalid IPN.
*/
file_put_contents('ipn.log',"\n###IPN:ERROR###\n".$listener->getTextReport(),FILE_APPEND);
}
The debug log i created is always like this
> IPN <--it states that the ipn was correctly called
##IPN:verifying...### <--the IPN is verifying the transaction
##IPN:transaction verified(confirmed=Pending)<--the transaction is verified but it's NOT confirmed because it's pending,i can't enable the download!
Disable Payment Review. Payment Review will always place them in a Pending state.
That's actually the whole point of it; to be able to use negative testing and payment review in order to test 'negative' scenario's to verify your error handling.
I am not familiar with the class you are using, but this is what i have been using for PP IPN in all my work and it works like a charm, maybe one day i'll make my own Object Oriented way but for now this seems to be doing the trick and i hope it helps you.
(Just to get you on the right track, i am using the same file for incoming and outcoming messages to/from PP)
$sandbox="sandbox.";
$paypal_email="seller_XXXXX_biz#twbooster.com";
$item_id = "1XN12PJ";
$cost = "22.30";
$item_name = 'My Item';
$return_url = "http://www.example.com/return";
$cancel_url = "http://www.example.com/cancel";
$notify_url = "http://www.example.com/notify";
function check_txnid($tnxid){
global $link;
$sql = mysql_query("SELECT * FROM `payments_pending` WHERE `txnid` = '$tnxid'", $link);
return mysql_num_rows($sql)==0;
}
function check_price($price, $id){
$sql = mysql_query("SELECT `cost` FROM `orders` WHERE `id` = '$id'");
if (mysql_numrows($sql) != 0) {
$row = mysql_fetch_array($sql);
$num = (float) $row['cost'];
if($num - $price == 0){
return true;
}
}
return false;
}
if (!isset($_POST["txn_id"]) && !isset($_POST["txn_type"])){ // Request TO Paypal
// Firstly Append paypal account to querystring
$querystring .= "?business=".urlencode($paypal_email)."&";
// Append amount& currency (£) to quersytring so it cannot be edited in html
$querystring .= "lc=CA&";
$querystring .= "currency_code=CAD&";
$querystring .= "item_number=".$item_id."&";
//The item name and amount can be brought in dynamically by querying the $_POST['item_number'] variable.
$querystring .= "item_name=".urlencode($item_name)."&";
$querystring .= "amount=".$cost."&";
//loop for posted values and append to querystring
foreach($_POST as $key => $value){
$value = urlencode(stripslashes($value));
$querystring .= "$key=$value&";
}
// Append paypal configs
$querystring .= "return=".urlencode(stripslashes($return_url))."&";
$querystring .= "cancel_return=".urlencode(stripslashes($cancel_url))."&";
$querystring .= "notify_url=".urlencode($notify_url);
// Append querystring with custom field
//$querystring .= "&custom=".USERID;
// Redirect to paypal IPN
header('location:https://www.'.$sandbox.'paypal.com/cgi-bin/webscr'.$querystring);
exit();
}else{ // Response FROM Paypal
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$req .= "&$key=$value";
}
// assign posted variables to local variables
$data = array();
$data['item_name'] = $_POST['item_name'];
$data['item_number'] = $_POST['item_number'];
$data['payment_status'] = $_POST['payment_status'];
$data['payment_amount'] = $_POST['mc_gross'];
$data['payment_currency'] = $_POST['mc_currency'];
$data['txn_id'] = $_POST['txn_id'];
$data['receiver_email'] = $_POST['receiver_email'];
$data['payer_email'] = $_POST['payer_email'];
$data['custom'] = $_POST['custom'];
// 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 : Do something to notify you
}
else {
fputs($fp, $header.$req);
$res = "";
while (!feof($fp)){
$res .= fgets($fp, 1024);
}
if(strpos($res, "VERIFIED")!==false){
// Validate payment (Check unique txnid & correct price)
$valid_txnid = check_txnid($data['txn_id']);
// $valid_price = check_price($data['payment_amount'], $data['item_number']);
$valid_price = check_price($data['payment_amount'], $_POST['item_number']);
// PAYMENT VALIDATED & VERIFIED!
if($valid_txnid && $valid_price){
$orderid = updatePayments($data);
if($orderid){
// Payment has been made & successfully inserted into the Database
}else{
// Error inserting into DB
}
}
else{
// Payment made but data has been changed : Do something to notify you
}
}
else{
if(strpos($res, "VERIFIED")!==false){
// PAYMENT INVALID & INVESTIGATE MANUALY! : Do something to notify you
}
}
fclose($fp);
}
}

Paypal sandbox IPN and mysql

I'm using Paypal Sandbox to test IPN, which is successful but it isn't updating my MYSQL database. How can i change the code below so that when Paypal sends IPN to my website it updates the mysql database? The below code is paypalipn.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.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!
$email = $_POST['payer_email'];
$email = mysql_escape_string($email);
$voted = mysql_query("INSERT INTO user VALUES ('','','','','','','','','','','','','','',''")or die(mysql_error());
mysql_query("UPDATE users SET `suscribed`=1 WHERE `email`='$email'")or die(mysql_error());
}
else if (strcmp ($res, "INVALID") == 0) {
// PAYMENT INVALID & INVESTIGATE MANUALY!
}
}
fclose ($fp);
}
Firstly always enable error reporting with error_reporting(E_ALL) when developing, plus log the IPN's to a text file (in a safe place obviously) to reference and see if the actual IPN's are being received & getting through your router ect
At first glance I see that your trying to insert a blank record in user table, also have not added a close bracket ) for the statement.
Then your updating a different table users with maybe a typo: suscribed, dont use the deprecated mysql_escape_string function... mysql_real_escape_string should be used instead, or better yet use prepared statements.
EDIT:
A Simple example you can work from, this includes PDO and logging for the IPN. Hope it helps.
<?php
/**Simple Paypal validation class**/
class paypal_class {
var $last_error;
var $ipn_log;
var $ipn_log_file;
var $ipn_response;
var $ipn_data = array();
function paypal_class() {
$this->paypal_url = 'https://www.paypal.com/cgi-bin/webscr';
$this->last_error = '';
$this->ipn_response = '';
$this->ipn_log_file = 'ipn_results.log';
$this->ipn_log = true;
}
function validate_ipn(){
$url_parsed=parse_url($this->paypal_url);
$post_string = '';
foreach($_POST as $field=>$value){
$this->ipn_data["$field"] = $value;
$post_string .= $field.'='.urlencode(stripslashes($value)).'&';
}
$post_string.="cmd=_notify-validate";
$fp = fsockopen($url_parsed[host],"80",$err_num,$err_str,30);
if(!$fp){
$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");
while(!feof($fp)){
$this->ipn_response .= fgets($fp, 1024);
}
fclose($fp);
}
if(eregi("VERIFIED",$this->ipn_response)){
$this->ipn_log(true);
return true;
}else{
$this->last_error = 'IPN Validation Failed.';
$this->ipn_log(false);
return false;
}
}
function ipn_log($success){
if (!$this->ipn_log) return;
$text = '['.date('m/d/Y g:i A').'] - ';
if ($success) $text .= "SUCCESS!\n";
else $text .= 'FAIL: '.$this->last_error."\n";
$text .= "IPN POST Vars from Paypal:\n";
foreach ($this->ipn_data as $key=>$value) {
$text .= "$key=$value, ";
}
$text .= "\nIPN Response from Paypal Server:\n ".$this->ipn_response;
$fp=fopen($this->ipn_log_file,'a');
fwrite($fp, $text . "\n\n");
fclose($fp);
}
}
class database{
/**PDO Connect**/
public function connect($host,$db,$user,$pass){
$this->dbh = new PDO('mysql:host='.$host.';dbname='.$db, $user, $pass);
}
/**Pre Query for prepared statement**/
public function update_valid($email){
$this->value = $email;
$this->prepare();
}
/**Delete pending user, when user clicks cancel # paypal**/
public function delete_pending($email){
$this->result = $this->dbh->prepare('DELETE FROM users where email=":value" and subscribed=0');
$this->result->bindParam(':value', $email);
$this->execute();
}
/**Prepare query for insert**/
private function prepare(){
/* Execute a prepared statement by binding PHP variables */
$this->result = $this->dbh->prepare('UPDATE users SET subscribed=1 WHERE email=":value"');
$this->result->bindParam(':value', $this->value);
$this->execute();
}
/**Execute prepared statement**/
private function execute(){
$this->result->execute();
}
/**Close db**/
public function close(){
$this->result = null;
}
}
?>
<?php
//Handle payment (Set You IPN url too http://yoursite.com?payment=ipn & Cancel url to http://yoursite.com?payment=cancel)
if(isset($_GET['payment'])){
switch ($_GET['payment']) {
case 'cancel':
//Order Cancelled
$db=new database();
$db->connect('localhost','table','root','password');
$db->delete_pending($_SESSION['email']); //hold email in session after submitting form
$db->close();
header('Location: index.php');
die();
break;
case 'ipn':
$pp = new paypal_class;
if ($pp->validate_ipn()){
//Success
$db=new database();
$db->connect('localhost','table','root','password');
$db->update_valid($ipn['payer_email']);
$db->close();
}
die();
break;
}
}
?>

Categories