Jump to content

Recommended Posts

Hi,

 

I'll try explain this the best I can.

 

I have a PayPal IPN script that works, inserts the the data into my database etc. But i'm having trouble with a custom variable. I can seem to pass it through to paypal.

 

I have my input field

<input type="text" name="on0" value="">

. This is where the will insert his/her username. And when the press the button

<form action="https://www.paypal.com/cgi-bin/webscr" method="POST">
		 <center><input type="text" name="on0" value="">
		 <br />
 <?php
 $on0 = $_POST['on0'];
 ?>
			 <input type="hidden" name="cmd" value="_xclick">
			 <input type="hidden" name="business" value="donate@dawncraftmc.com">
			 <input type="hidden" name="item_name" value="VIP">
			 <input type="hidden" name="item_number" value="1">
			 <input type="hidden" name="amount" value="0.01">
			 <input type="hidden" name="no_shipping" value="1">
			 <input type="hidden" name="no_note" value="1">
			 <input type="hidden" name="currency_code" value="GBP">
			 <input type="hidden" name="lc" value="GB">
			 <input type="hidden" name="bn" value="PP-BuyNowBF">
			 <input type="hidden" name="return" value="http://www.dawncraftmc.com/index.html">
			 <input type="hidden" name="cancel_return" value="http://www.dawncraftmc.com/index.html">
			 <input type="hidden" name="rm" value="2">
			 <input type="hidden" name="notify_url" value="http://vip.dawncraftmc.com/ipn.php" />
 <input type="hidden" name="on0" value="">
			 <input type="hidden" name="os0" value="<?php echo $on0; ?>">
			 <input type="image" src="https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
 <img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1"></center>
		 </form>

, it takes them to the PayPal page, they pay, and the variables passed through to the IPN goes into the database.

 

Could someone help me please? Tell me if i'm doing something wrong?

 

Here is both my ipn.php and ipnlistener.php:

 

<?php
include 'connect_to_mysql.php';
// tell PHP to log errors to ipn_errors.log in this directory
ini_set('log_errors', true);
ini_set('error_log', dirname(__FILE__).'/ipn_errors.log');
// intantiate the IPN listener
include('ipnlistener.php');
$listener = new IpnListener();
// tell the IPN listener to use the PayPal test sandbox
$listener->use_sandbox = false;
// try to proces
try {
$listener->requirePostMethod();
$verified = $listener->processIpn();
} catch (Exception $e) {
error_log($e->getMessage());
exit(0);
}
// manually investigate variables from paypal
 $body = "IPN failed variable check: \n\n";
 $body .= $listener->getTextReport();
 mail('donate@dawncraftmc.com', 'IPN Variables', $body);
if ($verified) {
$errmsg = ''; // stores errors from fraud checks

// 1. Make sure the payment status is "Completed"
if ($_POST['payment_status'] != 'Completed') {
 // simply ignore any IPN that is not completed
 exit(0);
}
// 2. Make sure seller email matches your primary account email.
if ($_POST['receiver_email'] != 'donate@dawncraftmc.com') {
 $errmsg .= "'receiver_email' does not match: ";
 $errmsg .= $_POST['receiver_email']."\n";
}

// 3. Make sure the amount(s) paid match
if ($_POST['mc_gross'] != '0.01') {
 $errmsg .= "'mc_gross' does not match: ";
 $errmsg .= $_POST['mc_gross']."\n";
}

// 4. Make sure the currency code matches
if ($_POST['mc_currency'] != 'GBP') {
 $errmsg .= "'mc_currency' does not match: ";
 $errmsg .= $_POST['mc_currency']."\n";
}
$txn_id = mysql_real_escape_string($_POST['txn_id']);
$sql = "SELECT COUNT(*) FROM log WHERE txn_id = '$txn_id'";
$r = mysql_query($sql);

if (!$r) {
 error_log(mysql_error());
 exit(0);
}

$exists = mysql_result($r, 0);
mysql_free_result($r);

if ($exists) {
 $errmsg .= "'txn_id' has already been processed: ".$_POST['txn_id']."\n";
}

if (!empty($errmsg)) {

 // manually investigate errors from the fraud checking
 $body = "IPN failed fraud checks: \n$errmsg\n\n";
 $body .= $listener->getTextReport();
 mail('donate@dawncraftmc.com', 'IPN Fraud Warning', $body);

} else {

 // add this order to a table of completed orders
 $payer_email = mysql_real_escape_string($_POST['payer_email']);
 $mc_gross = mysql_real_escape_string($_POST['mc_gross']);
 $option_selection1 = ($_POST['option_selection1_1'])?$_POST['option_selection1_1']:$_POST['option_selection1'];
 $option_selection2 = ($_POST['option_selection2_1'])?$_POST['option_selection2_1']:$_POST['option_selection2'];

 $sql = "INSERT INTO log VALUES
		 ('', '$txn_id', '$payer_email', '$mc_gross', '$option_selection1', '$option_selection2')";

 if (!mysql_query($sql)) {
	 error_log(mysql_error());
	 exit(0);
 }

 // send user an email with a link to their digital download
 $to = filter_var($_POST['payer_email'], FILTER_SANITIZE_EMAIL);
 $subject = "Your digital download is ready";
 mail($to, "Thank you for your order", "VIP");

 $to = filter_var($_POST['receiver_email'], FILTER_SANITIZE_EMAIL);
 $subject = "Donation Received";
 mail($to, "Donation Received", "Donation received from", $_POST['payer_email']);
}

} else {
// manually investigate the invalid IPN
mail('donate@dawncraftmc.com', 'Invalid IPN', $listener->getTextReport());
}
?>

 

<?php
/**
* PayPal IPN Listener
*
* A class to listen for and handle Instant Payment Notifications (IPN) from
* the PayPal server.
*/
class IpnListener {

   /**
* If true, the recommended cURL PHP library is used to send the post back
* to PayPal. If flase then fsockopen() is used. Default true.
*
* @var boolean
*/
   public $use_curl = true;

   /**
* If true, explicitly sets cURL to use SSL version 3. Use this if cURL
* is compiled with GnuTLS SSL.
*
* @var boolean
*/
   public $force_ssl_v3 = true;

   /**
* If true, cURL will use the CURLOPT_FOLLOWLOCATION to follow any
* "Location: ..." headers in the response.
*
* @var boolean
*/
   public $follow_location = false;

   /**
* If true, an SSL secure connection (port 443) is used for the post back
* as recommended by PayPal. If false, a standard HTTP (port 80) connection
* is used. Default true.
*
* @var boolean
*/
   public $use_ssl = true;

   /**
* If true, the paypal sandbox URI www.sandbox.paypal.com is used for the
* post back. If false, the live URI www.paypal.com is used. Default false.
*
* @var boolean
*/
   public $use_sandbox = false;

   /**
* The amount of time, in seconds, to wait for the PayPal server to respond
* before timing out. Default 30 seconds.
*
* @var int
*/
   public $timeout = 30;

   private $post_data = array();
   private $post_uri = '';
   private $response_status = '';
   private $response = '';
   const PAYPAL_HOST = 'www.paypal.com';
   const SANDBOX_HOST = 'www.sandbox.paypal.com';

   /**
* Post Back Using cURL
*
* Sends the post back to PayPal using the cURL library. Called by
* the processIpn() method if the use_curl property is true. Throws an
* exception if the post fails. Populates the response, response_status,
* and post_uri properties on success.
*
* @param string The post data as a URL encoded string
*/
   protected function curlPost($encoded_data) {
    if ($this->use_ssl) {
	    $uri = 'https://'.$this->getPaypalHost().'/cgi-bin/webscr';
	    $this->post_uri = $uri;
    } else {
	    $uri = 'http://'.$this->getPaypalHost().'/cgi-bin/webscr';
	    $this->post_uri = $uri;
    }

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $uri);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $encoded_data);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $this->follow_location);
    curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, true);

    if ($this->force_ssl_v3) {
	    curl_setopt($ch, CURLOPT_SSLVERSION, 3);
    }

    $this->response = curl_exec($ch);
    $this->response_status = strval(curl_getinfo($ch, CURLINFO_HTTP_CODE));

    if ($this->response === false || $this->response_status == '0') {
	    $errno = curl_errno($ch);
	    $errstr = curl_error($ch);
	    throw new Exception("cURL error: [$errno] $errstr");
    }
   }

   /**
* Post Back Using fsockopen()
*
* Sends the post back to PayPal using the fsockopen() function. Called by
* the processIpn() method if the use_curl property is false. Throws an
* exception if the post fails. Populates the response, response_status,
* and post_uri properties on success.
*
* @param string The post data as a URL encoded string
*/
   protected function fsockPost($encoded_data) {

    if ($this->use_ssl) {
	    $uri = 'ssl://'.$this->getPaypalHost();
	    $port = '443';
	    $this->post_uri = $uri.'/cgi-bin/webscr';
    } else {
	    $uri = $this->getPaypalHost(); // no "http://" in call to fsockopen()
	    $port = '80';
	    $this->post_uri = 'http://'.$uri.'/cgi-bin/webscr';
    }
    $fp = fsockopen($uri, $port, $errno, $errstr, $this->timeout);

    if (!$fp) {
	    // fsockopen error
	    throw new Exception("fsockopen error: [$errno] $errstr");
    }
    $header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
    $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $header .= "Content-Length: ".strlen($encoded_data)."\r\n";
    $header .= "Connection: Close\r\n\r\n";

    fputs($fp, $header.$encoded_data."\r\n\r\n");

    while(!feof($fp)) {
	    if (empty($this->response)) {
		    // extract HTTP status from first line
		    $this->response .= $status = fgets($fp, 1024);
		    $this->response_status = trim(substr($status, 9, 4));
	    } else {
		    $this->response .= fgets($fp, 1024);
	    }
    }

    fclose($fp);
   }

   private function getPaypalHost() {
    if ($this->use_sandbox) return IpnListener::SANDBOX_HOST;
    else return IpnListener::PAYPAL_HOST;
   }

   /**
* Get POST URI
*
* Returns the URI that was used to send the post back to PayPal. This can
* be useful for troubleshooting connection problems. The default URI
* would be "ssl://www.sandbox.paypal.com:443/cgi-bin/webscr"
*
* @return string
*/
   public function getPostUri() {
    return $this->post_uri;
   }

   /**
* Get Response
*
* Returns the entire response from PayPal as a string including all the
* HTTP headers.
*
* @return string
*/
   public function getResponse() {
    return $this->response;
   }

   /**
* Get Response Status
*
* Returns the HTTP response status code from PayPal. This should be "200"
* if the post back was successful.
*
* @return string
*/
   public function getResponseStatus() {
    return $this->response_status;
   }

   /**
* Get Text Report
*
* Returns a report of the IPN transaction in plain text format. This is
* useful in emails to order processors and system administrators. Override
* this method in your own class to customize the report.
*
* @return string
*/
   public function getTextReport() {

    $r = '';

    // date and POST url
    for ($i=0; $i<80; $i++) { $r .= '-'; }
    $r .= "\n[".date('m/d/Y g:i A').'] - '.$this->getPostUri();
    if ($this->use_curl) $r .= " (curl)\n";
    else $r .= " (fsockopen)\n";

    // HTTP Response
    for ($i=0; $i<80; $i++) { $r .= '-'; }
    $r .= "\n{$this->getResponse()}\n";

    // POST vars
    for ($i=0; $i<80; $i++) { $r .= '-'; }
    $r .= "\n";

    foreach ($this->post_data as $key => $value) {
	    $r .= str_pad($key, 25)."$value\n";
    }
    $r .= "\n\n";

    return $r;
   }

   /**
* Process IPN
*
* Handles the IPN post back to PayPal and parsing the response. Call this
* method from your IPN listener script. Returns true if the response came
* back as "VERIFIED", false if the response came back "INVALID", and
* throws an exception if there is an error.
*
* @param array
*
* @return boolean
*/
   public function processIpn($post_data=null) {
    $encoded_data = 'cmd=_notify-validate';

    if ($post_data === null) {
	    // use raw POST data
	    if (!empty($_POST)) {
		    $this->post_data = $_POST;
		    $encoded_data .= '&'.file_get_contents('php://input');
	    } else {
		    throw new Exception("No POST data found.");
	    }
    } else {
	    // use provided data array
	    $this->post_data = $post_data;

	    foreach ($this->post_data as $key => $value) {
		    $encoded_data .= "&$key=".urlencode($value);
	    }
    }
    if ($this->use_curl) $this->curlPost($encoded_data);
    else $this->fsockPost($encoded_data);

    if (strpos($this->response_status, '200') === false) {
	    throw new Exception("Invalid response status: ".$this->response_status);
    }

    if (strpos($this->response, "VERIFIED") !== false) {
	    return true;
    } elseif (strpos($this->response, "INVALID") !== false) {
	    return false;
    } else {
	    throw new Exception("Unexpected response from PayPal.");
    }
   }

   /**
* Require Post Method
*
* Throws an exception and sets a HTTP 405 response header if the request
* method was not POST.
*/
   public function requirePostMethod() {
    // require POST requests
    if ($_SERVER['REQUEST_METHOD'] && $_SERVER['REQUEST_METHOD'] != 'POST') {
	    header('Allow: POST', true, 405);
	    throw new Exception("Invalid HTTP request method.");
    }
   }
}
?>

 

I'm testing this on the real PayPal, not the sandbox.

Link to comment
https://forums.phpfreaks.com/topic/269628-paypal-ipn-custom-variable/
Share on other sites

Premiso, I got help from someone else on another forum. He told me to use 'on0' and 'os0', and that it should work after I put in

<?php
$on0 = $_POST['on0'];
?>
and:
<input type="hidden" name="on0" value="">
<input type="hidden" name="os0" value="<?php echo $on0; ?>">

which it never.

 

I don't want spoon feeding, but would you be able to tell me in some description how I'd go about setting the variable and passing it through to the IPN?

Well the question is, do you want it to be on or do you want it to just be "custom". The onX stuff is nice if you need multiple items you want to show up on the invoice. However, if you want it to be more or less hidden the custom field is the way to go.

 

Let me know which you want and I can fix you up. And also, next time post relevant code for your OP, posting ALL your code is just messy and sort of annoying :)

I just need it so the user can enter their username in the input field. I'm guessing it'll be custom, since you said the onX stuff is for multiple items?

 

The onX is for multiple items, but it will also display on the "order page" for that user. Custom will not display on the order page it is essentially hidden.

 

For custom just do:

 

<input type="hidden" name="custom" value="<?php echo $on0; ?>">

 

Simple as that, for the onX:

 

<input type="hidden" name="on1_1" value="Username" />
<input type="hidden" name="os1_1" value="<?php echo $on0;?>" />

 

For custom, you should be able to access it on the IPN page as $_POST['custom'] if the os1, should be $_POST['os1']

 

Sorry about posting all of the code, people usually tend to get quite... nasty when you don't :P

 

It really depends on the problem, since your paypal script does work, that stuff is not necessary, the problem in this case lies with the form data :) It can also detract from your original problem as people like to go off on tangents.

Edited by premiso

Thank you. I'm getting the custom field through now, it's sending as 'option_name1'.

 

I'm inserting the payment info into my database, I'm needing the custom field too. Since it's sending as 'option_name1', will I need to insert it as 'on0', or 'custom'?

 

Here's how I'm inserting it right now.

// add this order to a table of completed orders
    $payer_email = mysql_real_escape_string($_POST['payer_email']);
    $mc_gross = mysql_real_escape_string($_POST['mc_gross']);
    $on0 = mysql_real_escape_string($_POST['custom']);

    $sql = "INSERT INTO log VALUES
		    ('', '$txn_id', '$payer_email', '$mc_gross', '$on0')";

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.