I don't know why am I getting INVALID result, while everything works fine with IPN simulator.
IPNSampleCode.php
<?php
// STEP 1: Read POST data
// reading posted data from directly from $_POST causes serialization
// issues with array data in POST
// reading raw POST data from input stream instead.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// STEP 2: Post IPN data back to paypal to validate
$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr'); // change to [...]sandbox.paypal[...] when using sandbox to test
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path
// of the certificate as shown below.
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
// STEP 3: Inspect IPN validation result and act accordingly
echo $res;
if (strcmp ($res, "VERIFIED") == 0) {
// check whether 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
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
if ($_POST['mc_gross'] != NULL)
$payment_amount = $_POST['mc_gross'];
else
$payment_amount = $_POST['mc_gross1'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
$custom = $_POST['custom'];
// Insert your actions here
if($payment_status == "Completed" && $receiver_email == "naujas#mt2014.com"){
$db = new mysqli('localhost', 'myDetails', 'myDetails', 'myDetails');
if($db->connect_errno > 0){
die('Unable to connect to database [' . $db->connect_error . ']');
}
//
$time = strtotime(date("Y-m-d"));
$final = date("Y-m-d", strtotime("+12 month", $time));
$db->query("UPDATE users SET active_till='2012-05-05' WHERE email='naujas#mt2014.com';");
$db->close();
}
} else if (strcmp ($res, "INVALID") == 0) {
// log for manual investigation
echo "err";
}
?>
My botton:
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="QKH6ANQ9ZGXUU">
<table>
<tr><td><input type="hidden" name="on0" value="Period:">Period:</td></tr><tr><td><select name="os0">
<option value="1 month">1 month €50.00 EUR</option>
<option value="3 months">3 months €130.00 EUR</option>
<option value="6 months">6 months €200.00 EUR</option>
<option value="1 year">1 year €350.00 EUR</option>
</select> </td></tr>
</table>
<input type="hidden" name="currency_code" value="EUR">
<input type="image" src="https://www.sandbox.paypal.com/en_US/i/btn/btn_paynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.sandbox.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
When I has been creating my button, I added IPN code url into a finish field.
Maybe I don't have to use button, what then should I use? Thanks for help.
looks good, but try this when looking for a verified:
...
if (strcmp (trim($res), "VERIFIED") == 0) {
...
the payload may contain carriage return and line feed characters when using HTTP 1.1
Related
I am trying to make an online shopping with my custom shopping cart.
Here's the code in HTML:
<form name="paypalSubmit" action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="POST">
<input type="hidden" name="cmd" value="_cart">
<input type="hidden" name="upload" value="1">
<input type="hidden" name="business" value="value">
<input type="hidden" name="currency_code" value="EUR">
<input type="hidden" name="cancel_return" value="link">
<input type="hidden" name="return" value="link">
<input type="hidden" name="item_name_1" value='Stiklines is ledo'>
<input type="hidden" name="amount_1" value=0.56>
<input type="hidden" name="quantity1" value=3>
<input type="hidden" name="item_name_2" value='RGB lempute su pultu'>
<input type="hidden" name="amount_2" value=0.68>
<input type="hidden" name="quantity2" value=1>
<input type="image" src="http://www.paypal.com/en_US/i/btn/x-click-but01.gif" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
</form>
Everything works fine. After the payment is complete, ipn hits my ipn_listener which then updates database. Although it won't return item_name nor quantity. Thus it returns payment_status, mc_gross, mc_currency, txn_id, payer_email, payment_date.
Anyone can help me figure out what am I missing? Thank You very much.
EDIT:
ipn_listener.php
<?php
require_once("dbcontroller.php");
$db_handle = new DBController();
// STEP 1: Read POST data
// reading posted data from directly from $_POST causes serialization
// issues with array data in POST
// reading raw POST data from input stream instead.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// STEP 2: Post IPN data back to paypal to validate
$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path
// of the certificate as shown below.
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
// STEP 3: Inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// check whether 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
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_quantity = $_POST['quantity'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$payer_email = $_POST['payer_email'];
$payment_date = $_POST['payment_date'];
// <---- HERE you can do your INSERT to the database
$db_handle->insert("INSERT INTO buy_history(payment_method, item_name, item_quantity, payment_status, payment_amount, payment_currency, txn_id, payer_email, payment_date) VALUES ('paypal', '" . $item_name . "', " . $item_quantity . ", '" . $payment_status . "', '" . $payment_amount . "', '" . $payment_currency . "', '" . $txn_id . "', '" . $payer_email . "', '" . $payment_date . "')");
} else if (strcmp ($res, "INVALID") == 0) {
}
?>
Since you have multiple items in your cart, you receive multiple items in the IPN.
So you have to do like so:
$item_name1 = $_POST['item_name1'];
$item_quantity1 = $_POST['quantity1'];
// and so on
I am trying to code a simple PayPal purchase page with options on my site. However, I am having trouble testing it. For some odd reason, when I use "http://paypal.com/cgi-bin/webscr" as the form URL, it seems to work, however I can't test the IPN without someone purchasing it. If I leave it as "http://sandbox.paypal.com/cgi-bin/webscr", it will pop up with this on the PayPal Sandbox site,
PayPal cannot process this transaction because of a problem with the seller's website. Please contact the seller directly to resolve this problem.
Below is my Form:
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="YDPZBQ2LRBCSE">
<table>
<tr><td><input type="hidden" name="on0" value="Packages">Packages</td></tr><tr><td><select name="os0">
<option value="Bronze">Bronze $10.00 USD</option>
<option value="Silver">Silver $25.00 USD</option>
<option value="Gold">Gold $50.00 USD</option>
</select> </td></tr>
<tr><td><input type="hidden" name="on1" value="Wubbo Username">Wubbo Username</td></tr><tr><td><input type="text" name="os1" maxlength="200"></td></tr>
</table>
<input type="hidden" name="currency_code" value="USD">
<input type="image" src="http://wubbo.me/paypal/buynow.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">
</form>
And here is my IPN Code:
<?php
mysql_connect("localhost", "root", "PASSWORD") or die(mysql_error());
mysql_select_db("DATABASE") or die(mysql_error());
// STEP 1: read POST data
// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
// Instead, read raw POST data from the input stream.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// Step 2: POST IPN data back to PayPal to validate
$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp-like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set
// the directory path of the certificate as shown below:
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
// inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// The IPN is verified, process it:
// check whether 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 the notification
// assign posted variables to local variables
$package = $_POST['os0'];
$username = $_POST['os1'];
if ($package == 'Bronze') {
mysql_query("UPDATE `users` SET `vip_points` = (`vip_points` + 10) WHERE username = '" . $username . "'");
} else if ($package == 'Silver') {
mysql_query("UPDATE `users` SET `vip_points` = (`vip_points` + 30) WHERE username = '" . $username . "'");
} else if ($package == 'Gold') {
mysql_query("UPDATE `users` SET `vip_points` = (`vip_points` + 100) WHERE username = '" . $username . "'");
}
}
} else if (strcmp ($res, "INVALID") == 0) {
// IPN invalid, log for manual investigation
echo "The response from IPN was: <b>" .$res ."</b>";
}
?>
Any assistance would be greatly appreciated!
When you're using a hosted button you can't just change it from paypal.com to sandbox.paypal.com. You would have to create a separate hosted button from within your sandbox seller account.
Then you would use a sandbox buyer account to make purchases through that button, and if IPN is setup in the seller account it will trigger accordingly.
For some reason im having more trouble with this then I should... I have a IPN listner for Paypal and the IPN Simulator says successful each time and with different methods, but I can not get it to then manipulate the database based on a successful response.
Any ideas anyone?
<?php
//INCLUDE CONNECTION STRING
include('connect.php');
// STEP 1: read POST data
// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
// Instead, read raw POST data from the input stream.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// STEP 2: POST IPN data back to PayPal to validate
$ch = curl_init('https://www.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
if( !($res = curl_exec($ch)) ) {
error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
// STEP 3: Inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// 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($payment_status=="Completed"){
$selectuser = mssql_query("select statsmemberid from statsmembers where email='$payer_email'");
if(mssql_num_rows($selectuser) != 0){
$row = mssql_fetch_row($selectuser);
$statsmemberid = $row[0];
$getCredits = mssql_query("select creditsbought from statsmuplayers where statsmemberid='$statsmemberid'");
$row = mssql_fetch_row($getCredits);
$totalCredits = $row[0]+11;
$updatemu = mssql_query("update statsmuplayers set creditsbought='$totalCredits' where statsmemberid='$statsmemberid'");
echo "Credits Applyed";
}else{
echo "Invalid Email";
}
}
} else if (strcmp ($res, "INVALID") == 0) {
// IPN invalid, log for manual investigation
echo "The response from IPN was: <b>" .$res ."</b>";
}
?>
I'd suggest you encapsulate all of this code into a few objects. That will really help you figure out where things are going wrong.
You want an object that handles the IPN communication with paypal (you don't need to write that from scratch here's the first PHP implementation I found in a google search https://github.com/dodev34/paypal-ipn-response-client)
Then you want a base object that handles your database connections. And finally you want a statsmembers object that extends your database connection object and enforces your business logic. You might just lift some PHP ORM code like what you see here http://www.phpactiverecord.org/projects/main/wiki/Quick_Start
That would allow you to test the update functionality separately from the actual paypal IPN communication. The good news is at that point you don't have to rely on writing to system files for debugging like someone suggested in a comment above.
I don't see the specific error in your code just from a glance sorry, are you sure your passing the payer_email through paypal correctly?
So on my website, people are able to order upgrades by clicking "Pay Now" for the upgrade they want and by entering their username in the box. Up until now, I would then go in to PayPal, see the payment, and look at the Minecraft Username field, and upgrade it by hand. Now I want to start using IPN so that I can automate all of the work that i've been doing.
Here is the HTML code for a upgrade option:
<div class=donationBox>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="W2RH7VA3YS3Y4">
<table>
<tr>
<td width=75%><h2>Custom Maps - $5.00</h2></td>
<td><input type="hidden" name="on0" value="Minecraft Username">Minecraft Username<input type="text" name="os0" maxlength="200"></td>
</tr>
<tr>
<td>The ability to upload any map you want to play on! Maybe a survival island map? You bet! Or the Hunger Games!</td>
<td><input type="submit" class="btn btn-primary" value="Buy Now" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!"></td>
</tr>
</table>
</form>
</div>
And here is the PHP code to simply send me an Email with the info I need to try to get it working:
<?php
// STEP 1: Read POST data
// reading posted data from directly from $_POST causes serialization
// issues with array data in POST
// reading raw POST data from input stream instead.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// STEP 2: Post IPN data back to paypal to validate
$ch = curl_init('https://www.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path
// of the certificate as shown below.
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
// STEP 3: Inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// check whether 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
// 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'];
$custom = $_POST['on0'];
$message = "An order has been IPNified! " . $item_name . " " . $item_number . " " . $payment_amount . " " . $txn_id . " " . $custom;
mail('myemail#gmail.com', 'PayPal IPN', $message);
} else if (strcmp ($res, "INVALID") == 0) {
mail('myemail#gmail.com', 'PayPal IPN', 'Errors');
}
?>
The problem that I'm having is here:
$custom = $_POST['on0'];
I tried it as the above and:
$custom = $_POST['custom'];
The first one because that's the name of the Minecraft Username field, and the second I tried because I read that's what it should be, but either way it just didn't return anything. Any help would be great! Thanks!
Dump the results of $_POST and see which key fits the values you're looking for. Use either var_dump or print_r
// Displays more detail such as value types
var_dump($_POST);
// Only displays key => value relationships of an array
print_r($_POST);
EDIT
I just realized it's not possible to see the output of this using ipn. In this case you can always serialize the entire $_POST array and send it in an email.
$post_data_string = serialize($_POST);
mail('myemail#gmail.com', 'PayPal IPN', $post_data_string);
First, you're using a hosted button. As such, any custom options you set must be done within the button creation wizard or edit area of your PayPal account.
The actual parameter name for sending custom data is indeed "custom" so that's what you'll need to use in IPN to get values back for that particular parameter.
What was mentioned before (changing the field name on your form to custom) would work except that you're using a hosted button, so again, that will need to be adjusted in the button manager in your PayPal account.
UPDATE: I've even tried having the whole PHP script just be a single line that emails me when the script is viewed, and it still doesn't email me.
I've tried everything, or so I feel like. I have the script set up (very basic just so I can learn how to use it) to insert a row based upon the IPN response (completed, invalid, etc.)
However, it does not appear to be doing anything.
I've tried using the sandbox's built in IPN tester, and it does not do anything. I've tried using a Sandbox-based donator button with "notify_url" as a hidden input type, and it does not do anything.
The only time a row is actually inserted, is when I visit the file directly over my browser (the IPN file, of course). In that case, it inserts a row saying it was an invalid payment.
What in the dickens am I doing wrong or is PayPal's sandbox temporarily screwed up?
<?php
require("../functions.php");
sql();
// read the post from PayPal system and add 'cmd'
$req = 'cmd=' . urlencode('_notify-validate');
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.sandbox.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Host: www.paypal.com'));
$res = curl_exec($ch);
curl_close($ch);
// 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 (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
if($payment_status == "Completed") {
mysql_query("INSERT INTO donators (username)
VALUES ('completed')");
} else {
mysql_query("INSERT INTO donators (username)
VALUES ('wrong payment status')");
}
}
else if (strcmp ($res, "INVALID") == 0) {
mysql_query("INSERT INTO donators (username)
VALUES ('invalid')");
}
?>
Donator form:
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="QJUZ2AGANUWYS">
<input name="notify_url" value="http://mysite.com/libs/paypal/ipn.php" type="hidden">
<input type="image" src="https://www.sandbox.paypal.com/en_US/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.sandbox.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
Probably the invalid payment could be coming from the fact you were using a credit card or a credit card simulation by a sandbox account.
Throw away the condition if (strcmp ($res, "VERIFIED") == 0) { and you'll be ok.
i do not know the sandbox's built in IPN tester, sorry, probably someone here will help you on that point.
as this page says:
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_nvp_r_GetExpressCheckoutDetails
"NOTIFYURL is deprecated since version 63.0. Use
PAYMENTREQUEST_0_NOTIFYURL instead. "
Link to post here
Also, as a Code Injection point, do not put your IPN address in your HTML code. Anyone can view it, and as such know the location of the file. For safety purposes, put it inside your background PHP script, inside you're Paypal functions file, inside the function call ConfirmPayment.
Have you tried trimming $res?
strcmp(trim($res), "VERIFIED")
instead of
strcmp($res, "VERIFIED")
That's what finally got it working for me...