all. I have a problem retrieving certain POST values incoming to a script I have set up. The POST keys are not changeable as they come from a request from PayPal. However I need some way to get these values dynamically.
When a person purchases multiple items, I get POST values returned such as:
item_name=foo
item_name1=bar
item_name2=blah
I was thinking that I'll have to do some sort of Regular Expression to get the values, but I'm not sure about the syntax, or if it's even possible to use RegEx on a superglobal.
maybe something like:
$exp = "/item_name(d+)/";
foreach($_POST as $key => $val)
{
preg_match($exp,$key,$match);
}
As you can tell, I'm really bad with RegEx's. Any help would be greatly appreciated. :)
--EDIT--
Okay, there's two main POST keys that I need to catch. The problem is there may be any number (positive integer) after the key name:
item_name
item_name1
item_name2
item_number
item_number1
item_number2
But the ending digit can go all the way to 10, depending upon the number of products purchased. What I need to do is grab the values for each one of these, and add each item_number to a string to be inserted into a transaction table in my database. Perhaps something closer to:
$itms = '';
foreach($_POST as $key => $val)
{
if (strpos($key, 'item_name') === 0)
{
if($itms = '')
{
$itms = $val;
}
else
{
$itms .= ','.$val;
}
}
// don't really want to do it like this because i'd have to do it 10 times
if (strpos($key, 'item_name1') === 0)
{
if($itms = '')
{
$itms = $val;
}
else
{
$itms .= ','.$val;
}
}
}
// insert into DB after collecting all values
And yes, this is from an IPN.
--EDIT 2 -- This is what I have for my IPN listener script:
case 'ipnHandle' :
$header = '';
$retArray = array();
$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
";
$header .= "Content-Type: application/x-www-form-urlencoded
";
$header .= "Content-Length: " . strlen($req) . "
";
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
// 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 (!$fp)
{
$err_msg = 'Could not open the Paypal site to Verify Transaction';
}
else
{
fputs ($fp, $header . $req);
while (!feof($fp))
{
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0)
{
if($_POST['receiver_email'] == "chaoskreator@gmail.com")
{
if($_POST['payment_status'] == 'Completed')
{
$sql = 'SELECT transaction_id FROM '.SHOP_TRANS_TABLE.' WHERE transaction_pid = '.$_POST['txn_id'];
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
if($row != 0 && $row != null)
{
$id_exp = '/^item_number(\d*)$/';
$qty_exp = '/^quantity(\d*)$/';
$price_exp = '/^mc_gross(\d*)$/';
$items = array();
$qtys = array();
$prices = array();
foreach($_POST as $key => $val)
{
$match = Array();
if(preg_match($id_exp, $key, $match))
{
$items[] = $val;
}
if(preg_match($qty_exp, $key, $match))
{
$qtys[] = $val;
}
if(preg_match($price_exp, $key, $match))
{
$prices[] = $val;
}
}
}
}
}
$itmStr = implode(",", $items);
$qtyStr = implode(",", $qtys);
$priceStr = implode(",", $prices);
$data = '';
$file = "verifyLog.txt";
$fh = fopen($file, "a+");
foreach($_POST as $key => $value)
{
if($data == '')
{
$data = '['.$key.']'.$value;
}
else
{
$data .= ',['.$key.']'.$value;
}
}
$data .= "
".$itmStr."
".$qtyStr."
".$priceStr;
fwrite($fh, $data);
fclose($fh);
}
else if (strcmp ($res, "INVALID") == 0)
{
$data = '';
$file = "failLog.txt";
$fh = fopen($file, "a+");
foreach($_POST as $value)
{
if($data == '')
{
$data = '['.$key.']'.$value;
}
else
{
$data .= ',['.$key.']'.$value;
}
}
fwrite($fh, $data);
fclose($fh);
}
}
fclose ($fp);
}
break;
And this is the response ans logged to verifyLog.txt, with no comma-delimited string appended to the end...:
[test_ipn]1,[payment_type]instant,[payment_date]20:47:04 Apr 19, 2011 PDT,[payment_status]Completed,[payer_status]verified,[first_name]John,[last_name]Smith,[payer_email]buyer@paypalsandbox.com,[payer_id]TESTBUYERID01,[business]seller@paypalsandbox.com,[receiver_email]seller@paypalsandbox.com,[receiver_id]TESTSELLERID1,[residence_country]US,[item_name]something,[item_number]AK-1234,[item_name1]somethingElse,[item_number1]1234346dfg,[quantity]1,[quantity1]1,[shipping]8.50,[tax]2.02,[mc_currency]USD,[mc_fee]0.44,[mc_gross]15.34,[mc_gross_1]12.34,[mc_handling]2.06,[mc_handling1]1.67,[mc_shipping]3.02,[mc_shipping1]1.02,[txn_type]cart,[txn_id]4420347,[notify_version]2.4,[custom]xyz123,[invoice]abc1234,[charset]windows-1252,[verify_sign]XXXXXXXXXXXX
This is drinving me nuts. lol
If you are just matching a prefix, then regular expressions are arguably overkill. A simple string comparison such as the following would allow you to identify the items
if (strpos($key, 'item_name') === 0) {
// $key starts with item_name....
}
The below code will check each one to see if it is one of the item keys, and grab the ID if so. Your example showed one that did not have the digits on it, and since I am not familiar with the Paypal stuff you're dealing with, I went ahead and set the ID to 0 when such a match is made.
<?php
$exp = '/^item_name(\d*)$/';
$values = Array();
foreach( $_POST as $key => $val )
{
$match = Array();
//If this is one of the item name variables
if( preg_match( $exp, $key, $match ) )
{
//then put it into the array of captured values
$values[] = $val;
}
}
$commaSeparatedForDb = implode( ',', $values );
try this
$i = 0;
do {
$key = 'item_name';
if ($i > 0) {
$key .= $i; // append number to key if > 0
}
if (isset($_POST[$key])) {
echo "found $key => ".$_POST[$key];
// do something with it
}
$i++;
} while (isset($_POST[$key]));
BASED ON EDITED QUESTION ABOVE
if($_POST['payment_status'] == 'Completed')
{
$sql = 'SELECT transaction_id FROM '.SHOP_TRANS_TABLE.' WHERE transaction_pid = '.$_POST['txn_id'];
$result = $db->sql_query($sql);
// where is sql error checking, what if this sql has failed??
$row = $db->sql_fetchrow($result);
if($row != 0 && $row != null) {
// have you checked to see if the code is ever reaching this point?
// is it possible your database row doesn't exist
// this part here looks fine for extracting $_POST values
$id_exp = '/^item_number(\d*)$/';
$qty_exp = '/^quantity(\d*)$/';
$price_exp = '/^mc_gross(\d*)$/';
// maybe we should declare these arrays earlier.
// if this test fails, "if($row != 0 && $row != null) "
// you are still imploding the arrays below even though they haven't been declared
$items = array();
$qtys = array();
$prices = array();
foreach($_POST as $key => $val) {
// no need to store the matches as you aren't using them anyway
// $match = Array();
// changed 3x if statements to elseif
// this is not essential and won't effect the outcomes
// but is good practice as there is no point testing all 3 cases if first/second case already matches
if(preg_match($id_exp, $key)) {
$items[] = $val;
} elseif(preg_match($qty_exp, $key)) {
$qtys[] = $val;
} elseif (preg_match($price_exp, $key)) {
$prices[] = $val;
}
}
}
$itmStr = implode(",", $items);
$qtyStr = implode(",", $qtys);
$priceStr = implode(",", $prices);
// find all the matching field names
$fields_to_do = preg_grep('/^item_name\d*$/', $_POST);
// loop over them
foreach($files_to_do as $field) {
// extract what # they have
$id = substr($field, 9); // either blank, or 1,2,3,4,etc...
$name = $_POST["item_name$id"];
$number = $_POST["item_number$id"];
... do stuff ...
}