PayPal Mysql PHP
Copy link to clipboard
Copied
Hi,
I'm not sure if this is the right area to post this, but I was wondering if anyone could help.
For my coursework I am making an e-commerce website with Paypal integration.
When I complete the PayPal process and I am taken to my success.php file I am given the error:
Notice: Undefined index: tx in /storage/h3/495/770495/public_html/success.php on line 12
Notice: Undefined index: amt in /storage/h3/495/770495/public_html/success.php on line 13
Notice: Undefined index: cc in /storage/h3/495/770495/public_html/success.php on line 14
Notice: Undefined index: st in /storage/h3/495/770495/public_html/success.php on line 15
My success.php file:
<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>PayPal Transaction Success</title></head><body><?phpinclude 'dbConfig.php';//Get payment information from PayPal $txn_id = $_GET['tx'];$payment_gross = $_GET['amt'];$currency_code = $_GET['cc'];$payment_status = $_GET['st'];if(!empty($txn_id)){ //Check if payment data exists with the same TXN ID. $paymentResult = $db->query("SELECT * FROM payments WHERE txn_id = '".$txn_id."'"); if($paymentResult->num_rows > 0){ //payment information $paymentRow = $paymentResult->fetch_assoc(); $payment_id = $paymentRow['payment_id']; //order items details $orderItemResult = $db->query("SELECT p.name, i.quantity, i.gross_amount FROM order_items as i LEFT JOIN products as p ON p.id = i.item_number WHERE payment_id = '".$payment_id."'");?> <h1>Your payment has been successful.</h1> <h2>Payment ID: <?php echo $payment_id; ?></h2> <h2>Payment Gross: <?php echo '$'.$paymentRow['payment_gross'].' '.$paymentRow['currency_code']; ?></h2> <?php if($orderItemResult->num_rows > 0){ ?> <h3>Order Items</h3> <table style="width:50%"> <tr> <th>#</th> <th>Product Name</th> <th>Quantity</th> <th>Gross Amount</th> </tr> <?php $i=0; while($item = $orderItemResult->fetch_assoc()){ $i++; ?> <tr> <td align="center"><?php echo $i; ?></td> <td align="center"><?php echo $item['name']; ?></td> <td align="center"><?php echo $item['quantity']; ?></td> <td align="center"><?php echo '$'.$item['gross_amount'].' '.$paymentRow['currency_code']; ?></td> </tr> <?php } ?> </table> <?php } ?> <?php }else{ ?> <h1>Your payment has been successful.</h1> <h2>TXN ID: <?php echo $txn_id; ?></h2> <h2>Payment Gross: <?php echo '$'.$payment_gross.' '.$currency_code; ?></h2><?php } }else{ ?> <h1>Your payment has failed.</h1><?php } ?><a href="products.php">Back to products</a></body></html>
Could anyone help me fix this issue?
Thanks a million,
Danyaal.
Copy link to clipboard
Copied
How does the script GET tx, amt, cc, st? From the script it looks like they are trying to be sent via a url parameter.
The script is saying we cant find this information so effectively we cant do anything.
Normally one would communicate with Paypal using IPN instant payment notification which is a listener script you house on your server which listens for any completed payment. This script retrieves all the various Paypal variables which you use in a form to send to Paypal when a buyer purchases something from your site.
Once you have all those variables passed back to you from the Paypal server you can do someting with the values like update your database and sent confirmation emails of the purchase to the buyer etc
Does that sound like a workflow that you have used?
Copy link to clipboard
Copied
Hi,
Thanks for your reply.
Yes, that is the workflow I am using.
I have the ipn.php file on my server and have set up IPN on my PayPal account to the file on my server.
Danyaal.
Copy link to clipboard
Copied
So what is in the IPN file because that is where all the processing should take place, the communicating with your the database etc
How are you telling Paypal to go to your success.php page. lt seems like you are skipping a step and Paypal is getting to your success.php page without all the information to do what you are asking in the success.php page
Copy link to clipboard
Copied
My IPN file:
<?php
//Include DB configuration file
include 'dbConfig.php';
/*
* Read POST data
* reading posted data 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";
}
/*
* Post IPN data back to PayPal to validate the IPN data is genuine
* Without this step anyone can fake IPN data
*/
$paypalURL = "https://www.sandbox.paypal.com/cgi-bin/webscr";
$ch = curl_init($paypalURL);
if ($ch == FALSE) {
return FALSE;
}
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_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close', 'User-Agent: company-name'));
$res = curl_exec($ch);
/*
* Inspect IPN validation result and act accordingly
* Split response headers and payload, a better way for strcmp
*/
$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));
if (strcmp($res, "VERIFIED") == 0 || strcasecmp($res, "VERIFIED") == 0) {
//Payment data
$txn_id = $_POST['txn_id'];
$payment_gross = $_POST['mc_gross'];
$currency_code = $_POST['mc_currency'];
$payment_status = $_POST['payment_status'];
$payer_email = $_POST['payer_email'];
//Check if payment data exists with the same TXN ID.
$prevPayment = $db->query("SELECT payment_id FROM payments WHERE txn_id = '".$txn_id."'");
if($prevPayment->num_rows > 0){
exit();
}else{
//Insert tansaction data into the database
$insertPayment = $db->query("INSERT INTO payments(txn_id,payment_gross,currency_code,payment_status,payer_email) VALUES('".$txn_id."','".$payment_gross."','".$currency_code."','".$payment_status."','".$payer_email."')");
if($insertPayment){
//Insert order items into the database
$payment_id = $db->insert_id;
$num_cart_items = $_POST['num_cart_items'];
for($i=1;$i<=$num_cart_items;$i++){
$order_item_number = $_POST['item_number'.$i];
$order_item_quantity = $_POST['quantity'.$i];
$order_item_gross_amount = $_POST['mc_gross_'.$i];
$insertOrderItem = $db->query("INSERT INTO order_items(payment_id,item_number,quantity,gross_amount) VALUES('".$payment_id."','".$order_item_number."','".$order_item_quantity."','".$order_item_gross_amount."')");
}
}
}
}
On my Paypal profile I have set auto return to e.g. mysite.com/success/php
Thanks.
Danyaal
Copy link to clipboard
Copied
As I suspected you are just directing Paypal back to a page after payment has completed BUT it does not have the correct information to do what you need according to the script.
$txn_id = $_GET['tx'];$payment_gross = $_GET['amt'];$currency_code = $_GET['cc'];$payment_status = $_GET['st'];
For instance the above bit of code is looking for some information which is passed in a url parameter like below but I've never seen it done like this before.
success.php?tx=12345&amt=20.00&cc=US&am;st=completed
But you can only get some of that information from the Paypal server which is what the below bit of code does in your IPN script:
foreach ($myPost as $key => $value) {
But as the IPN script and the success.php are not linked in anyway shape or form it seems it cant get it.
This is why all the processing should take place in the IPN file . The below block of code checks to see if the unique transaction exists if it does the script exits (stops running). If it doesnt then the code between the else { } block is executed.This is where you would call information from your database and update the database, you could send emails to the buyer and redirect to a success page.
//Check if payment data exists with the same TXN ID.
$prevPayment = $db->query("SELECT payment_id FROM payments WHERE txn_id = '".$txn_id."'");
if($prevPayment->num_rows > 0){
exit();
}
else {
//Insert tansaction data into the database
$insertPayment = $db->query("INSERT INTO payments(txn_id,payment_gross,currency_code,payment_status,payer_email) VALUES('".$txn_id."','".$payment_gross."','".$currency_code."','".$payment_status."','".$ payer_email."')");
if($insertPayment){
//Insert order items into the database
$payment_id = $db->insert_id;
$num_cart_items = $_POST['num_cart_items'];
for($i=1;$i<=$num_cart_items;$i++){
$order_item_number = $_POST['item_number'.$i];
$order_item_quantity = $_POST['quantity'.$i];
$order_item_gross_amount = $_POST['mc_gross_'.$i];
$insertOrderItem = $db->query("INSERT INTO order_items(payment_id,item_number,quantity,gross_amount) VALUES('".$payment_id."','".$order_item_number."','".$order_item_quantity."','".$order_it em_gross_amount."')");
}
Obvioulsy I assume you have the Paypal notify_url included in the payment form on your website, with a the link similar to below?
<input type='hidden' name='notify_url' value='http://www.xxxxxxxxx.xxxx/ipn/ipn.php'>
I would ask your coursework tutor for some assistance on this as its not something which is easy to set up until you have and then it becomes easy, but initially its a mine field.
Copy link to clipboard
Copied
Hi,
I do have <input type='hidden' name='notify_url' value='http://www.xxxxxxxxx.xxxx/ipn/ipn.php'> in my payment form.
Unfortunately, my teachers have been unable to help me with this so far. I was hoping for someone to help online.
Thanks for the reply though,
Danyaal.
Copy link to clipboard
Copied
I'm not sure how you are even testing this?
Are you using a live link to the Paypal gateway?
What I usually do is avoid the Paypal sandbox testing area because its always not working or corrupt in some way. I specify a low nominal amount like a penny to the items and then use the live environment. This way you can have 100 goes for a britsh pound to get things right.
.
I first check to see if everything is functioning by using the redirect function between the else { } block of code in the IPN script:
else {
header("Location: http://example.com/success.php");
}
If you get redirected to the success.php page you know something is happening. You can then connect to your database and do what you need to do within the IPN scripts else { } block.
Copy link to clipboard
Copied
Hi,
i am testing it in Sandbox.
Once I put in my credentials for PayPal and i am returned to my own website (the success.php) page I get the message in my first post.
Thanks,
Danyaal
Copy link to clipboard
Copied
Hi,
I have added a bracket under the code on my success.php file.
if($paymentResult->num_rows > 0){
//payment information
$paymentRow = $paymentResult->fetch_assoc();
$payment_id = $paymentRow['payment_id'];
}
On my success page I now get this message:
Parse error: syntax error, unexpected 'else' (T_ELSE) in /storage/h3/495/770495/public_html/success.php on line 53
Have I put too many brackets.
Thanks,
Danyaal.
Copy link to clipboard
Copied
danyaalk74530408 wrote
Hi,
I have added a bracket under the code on my success.php file.
if($paymentResult->num_rows > 0){
//payment information
$paymentRow = $paymentResult->fetch_assoc();
$payment_id = $paymentRow['payment_id'];
}
On my success page I now get this message:
Parse error: syntax error, unexpected 'else' (T_ELSE) in /storage/h3/495/770495/public_html/success.php on line 53
Why are you adding a bracket there?
Copy link to clipboard
Copied
the bracket was missing.
Copy link to clipboard
Copied
danyaalk74530408 wrote
the bracket was missing.
Are you following a tutorial?
Copy link to clipboard
Copied
Yes, I am following a code from codex world.
I managed to fix the above error but I am still getting the error:
Notice: Undefined index: tx in /storage/h3/495/770495/public_html/success.php on line 12
Notice: Undefined index: amt in /storage/h3/495/770495/public_html/success.php on line 13
Notice: Undefined index: cc in /storage/h3/495/770495/public_html/success.php on line 14
Notice: Undefined index: st in /storage/h3/495/770495/public_html/success.php on line 15
Copy link to clipboard
Copied
danyaalk74530408 wrote
Yes, I am following a code from codex world.
I managed to fix the above error but I am still getting the error:
Notice: Undefined index: tx in /storage/h3/495/770495/public_html/success.php on line 12
Notice: Undefined index: amt in /storage/h3/495/770495/public_html/success.php on line 13
Notice: Undefined index: cc in /storage/h3/495/770495/public_html/success.php on line 14
Notice: Undefined index: st in /storage/h3/495/770495/public_html/success.php on line 15
Unfortunately you will continue to get that error until the variables have been defined. As an example IF you 'hard code' the values the error should go away BUT its meangless as you need to retreive the dynamic values from somewhere.
$txn_id = 12345;$payment_gross = 20;$currency_code = "US";$payment_status = "completed";
echo $txn_id."<br>";
echo $payment_gross."<br>";
echo $currency_code."<br>";
echo $payment_status."<br>";
Copy link to clipboard
Copied
but I am still getting the error:. . .undefined index
This is not an error. It isn't even a warning. You can change your error message settings to not show such notices. You can ignore it.
Copy link to clipboard
Copied
But then I'll get the message Payment failed.
Copy link to clipboard
Copied
But then I'll get the message Payment failed.
Normally on the public webserver the error messages are set to not display. As I said, ignore them.
Copy link to clipboard
Copied
danyaalk74530408 wrote
But then I'll get the message Payment failed.
Think of it more simply by at first getting rid of a lot of the code.
Because there is no value for the variable $txn_id payment will fail. If you replace $_GET['txn'] with any number like 12345 payment will be successful. If $txn_id has a value you can start checking against information in the database and updating it if certain criteria are met. I fail to see how you are going to do this though because you are not saying where a lot of the variables are coming from, hence the line //Get payment information from PayPal........you dont seem to be doing that.
<?php
//Get payment information from PayPal
$txn_id = $_GET['txn'];
$payment_gross = $_GET['amt'];
$currency_code = $_GET['cc'];
$payment_status = $_GET['st'];
if(!empty($txn_id)) { ?>
// do someting
// do someting
// do someting
// do someting
// do someting
// do someting
// do someting
// do someting
// do someting
<?php echo "<h1>Your payment has been successful</h1>"; ?>
<?php } else { ?>
<h1>Your payment has been failed.</h1>
<?php } ?>
Copy link to clipboard
Copied
What you should be doing is testing to see if the variables have 'been set' and if they have not then you 'do something else':
if(isset($_GET['tx']) && isset($_GET['amt']) && isset($_GET['cc']) && isset($_GET['st'])) {
$txn_id = $_GET['tx'];
$payment_gross = $_GET['amt'];
$currency_code = $_GET['cc'];
$payment_status = $_GET['st'];
}
else {
echo "Do something else";
}

