Easy Paypal Question for Someone Who Knows What They're Doing

While I'm supremely confident this is cake and ice cream for someone who's been down this road before, I'm like a pig on roller skates right about now so I'm hoping someone can help me.

This much I know: I want to use Paypal's IPN and a custom field as part of the "handshake" that occurs between my database and Paypal's notification of a valid transaction.

I'm using a hosted button that looks like this:

<div align="center"><form target="paypal" action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="K9AU4PN9N6JMS">
<input type="hidden" name="custom" value="<?php echo $novie_id; ?>">
<input type="image" src="images/no_ads.png" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
<input type="hidden" name="notify_url" value=”http://www.brucegust.com/paypal_listener.php">

Notice the "custom" field which I'm including based on the IPN simulator including a custom field and the "notify_url" field which I'm including based on the counsel I received from a helpful Paypal support agent.

I'll run my code through the simulator and I'll get a successful response, but there's no change to my database. By that I mean, I need to update the "paid" field with today's date. Here's the code that I'm using to make that happen:

include ("carter.inc");
$cxn = mysqli_connect($host,$user,$password,$database)
or die ("couldn't connect to server");

  // Read the notification from PayPal and create the acknowledgement response
  $req = 'cmd=_notify-validate';               // add 'cmd' to beginning of the acknowledgement you send back to PayPal

  foreach ($_POST as $key => $value) {         // Loop through the notification NV pairs
    $value = urlencode(stripslashes($value));  // Encode the values
    $req .= "&$key=$value";                    // Add the NV pairs to the acknowledgement

$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'];
$payer_id= $_POST['custom'];

//Set up the acknowledgement request headers
  $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";

  //Open a socket for the acknowledgement request
  $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);

  // Post request back to PayPal for validation
  fputs ($fp, $header . $req);

  while (!feof($fp)) {                     // While not EOF
    $res = fgets ($fp, 1024);              // Get the acknowledgement response
    if (strcmp ($res, "VERIFIED") == 0) {  // Response is VERIFIED

      // Send an email announcing the IPN message is VERIFIED
      $mail_From = "IPN@example.com";
      $mail_To = "bruce@brucegust.com";
      $mail_Subject = "VERIFIED IPN";
      $mail_Body = $req;
      mail($mail_To, $mail_Subject, $mail_Body, $mail_From);

	  //I'm going to update my database here
	  $bruce="update links set paid = '$today' where id='$payer_id'";
	  $bruce_query=mysqli_query($cxn, $bruce);
	  $nuts=mysqli_errno($cxn).': '.mysqli_error($cxn);
      // Notification protocol is complete, OK to process notification contents

      // Possible processing steps for a payment might include the following:

      // Check that 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) { // Response is INVALID

      // Notification protocol is NOT complete, begin error handling

      // Send an email announcing the IPN message is INVALID
      $mail_From = "IPN@example.com";
      $mail_To = "bruce@brucegust.com";
      $mail_Subject = "INVALID IPN";
      $mail_Body = $req;
      mail($mail_To, $mail_Subject, $mail_Body, $mail_From);
   fclose ($fp);  //close file pointer

Open in new window

Based on the fact that my database is not being updated, despite what appears to be a successfully completed transaction, I'm lost as to what I'm missing. So, here are my two questions:

Am I passing my customer's id correctly by using the hidden "custom" field within my button?
Is that information being included in my IPN? Is there a way I can "echo" the script so I can see what's going on under the hood?

Thanks in advance for the help!
brucegustPHP DeveloperAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Marco GasiFreelancerCommented:
First, I would try to pass a hardcoded id to see if the script updates the database:

$bruce="update links set paid = '$today' where id='1'";

Second, you can send an email to you to see how the query is formed:

$bruce="update links set paid = '$today' where id='$payer_id'";
mail('your_email_address', 'test query', $bruce);

Hope this helps.
brucegustPHP DeveloperAuthor Commented:
MarqusG, I ran the test code like you suggested and it worked and I got the email with the syntax to confirm it.

So, we're good to go there. The thing that's gnawing at me is the whole "custom" field. Am I passing that correctly in my button code? Does Paypal see that hidden "custom" field and send it back to me? That's the disconnect that's got me concerned.

What do you think?
Ray PaseurCommented:
I would try this... Do the same email thing, but do it at line 13, like this:

mail('your_email_address', 'test request', $req);

Then you can look in the email and see if "custom" is coming through.

But it looks like you're already getting the $req mailed to you, right?  In an async script like the PayPal IPN, a die() statement with a message is not useful -- it has no way to get the message to you, so you have to use a log file or email or something similar.
Marco GasiFreelancerCommented:
Also, if $payer_id grabs the custom field returned by Paypal, emailing to you $bruce should give you the ability to see if $payewr_id is what it is expected to be. If it is, then we can think you're passing that value correctly and it is correclty processed and returned by Paypal, isn't it?
Cornelia YoderArtistCommented:
Can you check (echo it out before the call to paypal) and see if


has the value you expect you are sending in the custom field?  Perhaps that value isn't set and thus you are getting nothing back from PayPal.

Also you could check your PayPal account directly and see if that custom value is correct there.

Otherwise, your method looks fine to me.

By the way, an email works, but I prefer to use a special database table I call PayPalDebug and update that with all the values I get back (at least when I am testing), so I can see them and store them easily.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.