PayPal IPN Buttons HELP

I have been using PayPal IPN for ages, but with "BuyNow" buttons. I have recently created new buttons that are "Shopping Cart" buttons, and now my IPN doesn't work anymore.

Here is my current code:
if (empty($_POST) || @count($_POST) < 1)
		die("No params");
 
	$query = array('cmd=_notify-validate');
	foreach ($_POST as $key => $val) {
		if (!empty($val))	{
			$query[] = $key .'=' .urlencode($val);
			$$key    = trim(strip_tags($val));
		}
	}
	$query = implode('&', $query);
 
	$has_curl = false;
	if (function_exists('curl_init') && $ch = curl_init()) {
		curl_setopt($ch, CURLOPT_URL, 'http://www.paypal.com/cgi-bin/webscr');
		curl_setopt($ch, CURLOPT_TIMEOUT, 30);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_USERAGENT, 'Codehead + Curl');
		$result = curl_exec($ch);
		curl_close($ch);
		$has_curl = true;
	}
	if (!$has_curl) {
		$header  = "POST /cgi-bin/webscr HTTP/1.0\r\n";
		$header .= "Host: www.paypal.com\r\n";
		$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
		$header .= "Content-Length: " . strlen($query) . "\r\n\r\n";
		if ($fp = fsockopen(www.paypal.com, 80, $errno, $errstr, 30)) {
			socket_set_timeout($fp, 15);
			fwrite($fp, $header . $query);
			while (!feof($fp)) {
				$result = fgets($fp, 1024);
				if (strcmp($result, 'VERIFIED') == 0)
					break;
			}
			fclose($fp);
		}
	}
	
		$paypal = array();
		$paypal['user_id'] = $user_id;
		$paypal['payment_date'] = time();
		$paypal['completed_date'] = ($payment_status == 'Completed' ? time() : '');
		$paypal['item_name'] = $item_name;
		$paypal['item_number1'] = $item_number; //&item_number=TP_S1
		$paypal['payment_type'] = $payment_type;
		$paypal['payment_status'] = $payment_status;
		$paypal['pending_reason'] = $pending_reason;
		$paypal['payment_amount'] = $mc_gross;
		$paypal['paypal_fee'] = (isset($mc_fee) ? $mc_fee : 0);
		$paypal['payment_currency'] = $mc_currency;
		$paypal['txn_id'] = $txn_id; 
		$paypal['receiver_email'] = $receiver_email;
		$paypal['payer_name'] = $first_name .' ' .$last_name;
		$paypal['payer_email'] = $payer_email;		
		$paypal['raw_payment_data'] = serialize($_POST);
		$paypal['custom'] = $custom;

Open in new window


The item_number used to be just item_number with buynow buttons, but with shopping cart it seems to have numbers (like item_number1).
However I have script email me parameters received, and item_number1 shows as blank, even if its listen in IPN message in PayPal history.

Bellow are samples of IPN messages from PayPal history. First its regular buynow:
mc_gross=18.00&protection_eligibility=Ineligible&address_status=confirmed&payer_id=BH6KD672XT7QN&tax=0.00&address_street=484 w 43rd st. 14m&payment_date=22:40:24 Oct 03, 2011 PDT&payment_status=Completed&charset=windows-1252&address_zip=10036&first_name=Jesse&mc_fee=0.96&address_country_code=US&address_name=Jesse McBride&notify_version=3.4&custom=CUSTOM&payer_status=verified&business=&address_country=United States&address_city=&verify_sign=A8AwgDwQw-W3A-XKrA3Y-EaqmjTpO2P3K09PZnl9DCymW&payer_email=&txn_id=9U496046E6211010U&payment_type=instant&btn_id=24843740&last_name=&address_state=NY&receiver_email=fdhfdfsdf&payment_fee=&shipping_discount=0.00&insurance_amount=0.00&receiver_id=dsfsdfsdfds&txn_type=web_accept&item_name=dfdasfd&discount=0.00&mc_currency=EUR&item_number=ITEM&residence_country=US&shipping_method=Default&handling_amount=0.00&transaction_subject=CUSTOM&payment_gross=&shipping=0.00&ipn_track_id=RNjnly6gChPh-8fJdt7ZdA

Open in new window


Now second is Cart Buynow IPN:
mc_gross=18.00&protection_eligibility=Ineligible&address_status=unconfirmed&item_number1=TP_C5000&payer_id=924ZZYRK93BXN&tax=0.00&address_street=Glärnischstrasse 79&payment_date=12:38:05 Oct 04, 2011 PDT&payment_status=Completed&charset=windows-1252&address_zip=8810&mc_shipping=0.00&mc_handling=0.00&first_name=Pius&mc_fee=1.14&address_country_code=CH&address_name=&notify_version=3.4&custom=rasorfrog&payer_status=verified&business=mm&address_country=Switzerland&num_cart_items=1&mc_handling1=0.00&address_city=n&verify_sign=AeC0pIlHDmjsk5A-GAqvtzxGq8K--9UJCyoRzE1FjQrjW&payer_email=&mc_shipping1=0.00&btn_id1=36427581&txn_id=4MF91487RR2074513&payment_type=instant&last_name=&address_state=&item_name1=ITEM Credits&receiver_email=om&payment_fee=&quantity1=1&receiver_id=6696NT7T9DDHW&txn_type=cart&mc_gross_1=18.00&mc_currency=EUR&residence_country=CH&transaction_subject=CUSTOM&payment_gross=&ipn_track_id=7rCDhJ8.x4tOthO2eXKTpg

Open in new window


So what I need is a way to EXTRACT item_numberX and its quantity and than run foreach loop (loop must run for each quantity & for each item_number).

Please help me out, its really important. Thanks a lot.
GVNPublic123Asked:
Who is Participating?
 
Ray PaseurCommented:
Here is how I have done that for shopping carts in the past.  Too bad PayPal doesn't just use an XML string!

HTH, ~Ray
<?php // RAY_paypal_ipn.php - CUSTOM PayPal IPN PROCESSING


// LOCAL FUNCTIONS AND VARIABLES, DB STUFF, ETC. - NO SESSION HERE - FUNCTION warning_RAY() SENDS AN EMAIL MESSAGE
require_once('common.php');


// READ THE POST FROM PayPal AND ADD 'cmd'
$req      = 'cmd=_notify-validate';
$postdata = '';
foreach ($_POST as $key => $value)
{
    $postdata .= PHP_EOL . " $key = $value ";      // SAVE THE COLLECTION
    $$key     = trim(stripslashes($value));        // ASSIGN LOCAL VARIABLES
    $value    = urlencode(stripslashes($value));   // ENCODE FOR BOUNCE-BACK
    $req      .= "&$key=$value";                   // APPEND TO VERIFICATION STRING
}

// SET THE HEADERS FOR THE CONFIRMATION POST BACK TO PayPal
$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 THE HTTP PIPE FOR THE POST BACK TO PayPal
$fp = fsockopen ('www.paypal.com', 80, $errno, $errstr, 30);

// TEST FOR SUCCESSFUL OPENNING OF THE HTTP PIPE
if (!$fp) // HTTP ERROR
{
    warning_RAY("IPN HTTP ERROR", "FSOCKOPEN FAILED \n\n ERRNO=$errno \n\n ERRSTR=$errstr \n\n");
    die();
}

// WITH HTTP OPEN - WRITE HEADER AND REQUEST
fputs ($fp, $header . $req);

// WITH HTTP OPEN - READ PayPal RESPONSE
$paypal_reply   = '';
$paypal_headers = '';
while (!feof($fp))
{
    $paypal_reply    = fgets($fp, 1024);
    $paypal_headers .= $paypal_reply;
}
fclose ($fp);

// IF THIS IS TRULY A POST FROM PAYPAL, PROCESS ORDER NOTIFICATION
if ($paypal_reply == "VERIFIED")
{
    $errormsg = "";

    // IF PAYMENT IS NOT COMPLETED (MAY BE E-CHECK?)
    if ($payment_status != "Completed") { $errormsg .= "\nE: payment_status"; }

    // IF PAYMENT WAS NOT SENT TO ME?
    $receiver_email = strtolower($receiver_email);
    if ($receiver_email == "me@my.org") { } else { $errormsg .= "\nE: receiver_email"; } // ??? SET EMAIL ADDRESS

    // I AM NOT CHECKING SOME THINGS BECAUSE WE ARE USING ENCRYPTED OR STORED BUY-NOW BUTTONS
    if ($mc_currency != 'USD') { $errormsg .= "\nE: mc_currency"; }

    // CHECK FOR TXN_ID ALREADY PROCESSED - NORMAL FOR E-CHECK
    $sql = "SELECT txn_id FROM PAYPAL_ORDER_LOG WHERE txn_id = \"$txn_id\" ";
    if (!$result = mysql_query($sql, $db_connection)) { fatal_query_error($sql); }
    $num_rows = mysql_num_rows($result);
    if ($num_rows  > 0) { $errormsg .= "\nE: Transaction id $txn_id already processed $num_rows time(s)"; }

    // LOG THE TRANSACTION
    $order_date  = date('Y-m-d\TH:i:s');
    $item_number = mysql_real_escape_string($item_number, $db_connection);
    $mc_gross    = mysql_real_escape_string($mc_gross,    $db_connection);
    $address_zip = mysql_real_escape_string($address_zip, $db_connection);
    $txn_id      = mysql_real_escape_string($txn_id,      $db_connection);
    $receipt_id  = mysql_real_escape_string($receipt_id,  $db_connection);
    $last_name   = mysql_real_escape_string($last_name,   $db_connection);
    $payer_email = mysql_real_escape_string($payer_email, $db_connection);
    $postdata    = mysql_real_escape_string($postdata,    $db_connection);
    $sql = "INSERT INTO PAYPAL_ORDER_LOG (    order_date,      item_number,      mc_gross,      address_zip,      txn_id,      receipt_id,      last_name,      payer_email,      postdata  )
            VALUES                       ( \"$order_date\", \"$item_number\", \"$mc_gross\", \"$address_zip\", \"$txn_id\", \"$receipt_id\", \"$last_name\", \"$payer_email\", \"$postdata\")";
    if (!$result = mysql_query($sql)) { fatal_query_error($sql); }

    // ISSUE A MESSAGE TO THE HOME OFFICE ?
    warning_RAY("IPN VERIFIED", "IPN REPLY $paypal_headers \n\n$errormsg \n\nPOST DATA FOLLOWS: $postdata \n\n");

    // GENERATE ARRAYS OF PURCHASE DATA FROM THE WEIRD PAYPAL VARIABLE NAMES
    // NOTE: NO POSITION ZERO IN THESE ARRAYS
    $w_item_number = array();
    $w_quantity    = array();
    $w_mc_gross    = array();
    $w_item_name   = array();

    // IF TRANSACTION TYPE IS CART, MAY BE MULTIPLE ITEMS IN DIFFERENT QUANTITIES - LOAD ARRAYS
    // NOTE NOTE NOTE NO POSITION ZERO IN THESE ARRAYS
    if ($txn_type == "cart")
    {
        while ($num_cart_items > 0)
        {
            $proxy = "item_number" . "$num_cart_items";
            $w_item_number[$num_cart_items] = $$proxy;

            $proxy = "quantity" . "$num_cart_items";
            $w_quantity[$num_cart_items] = $$proxy;

            $proxy = "mc_gross_" . "$num_cart_items";
            $w_mc_gross[$num_cart_items] = $$proxy;

            $proxy = "item_name" . "$num_cart_items";
            $w_item_name[$num_cart_items] = $$proxy;

            $num_cart_items--;
        }
    }
    else
    {
        // NOT A CART - SINGLETON ITEM ONLY - NORMALIZE INTO ARRAY FOR USE WITH ITERATOR
        // NOTE NOTE NOTE NO POSITION ZERO IN THESE ARRAYS
        $w_item_number[1] = $item_number;
        $w_quantity[1]    = $quantity;
        $w_mc_gross[1]    = $mc_gross;
        $w_item_name[1]   = $item_name;
    }

// *****************************************************
// ACTIVATE THIS CODE BLOCK TO SEE WHAT IS IN THE ORDER ARRAYS
//
//    ob_start();
//    echo "<pre>\n";
//    echo "\nW_ITEM_NUMBER"; var_dump($w_item_number);
//    echo "\nW_QUANTITY";    var_dump($w_quantity);
//    echo "\nW_MC_GROSS";    var_dump($w_mc_gross);
//    echo "\nW_ITEM_NAME";   var_dump($w_item_name);
//    $foo = ob_get_contents();
//    ob_end_clean();
//    warning_RAY("IPN VARDUMPS", "$foo \n\n");
// *****************************************************


    // ITERATE OVER THE ARRAYS
    $kount = 0; // NO POSITION ZERO IN THESE ARRAYS
    while ($kount < count($w_item_number))
    {
        $kount++; // BUMP BEFORE WORKING
        $my_item_number = $w_item_number[$kount];
        $my_quantity    = $w_quantity[$kount];
        $my_mc_gross    = $w_mc_gross[$kount];
        $my_item_name   = $w_item_name[$kount];

        //
        // ??? PROCESS THE ORDERS USING YOUR BUSINESS LOGIC
        //

    } // END ITERATION OVER THE ORDERS

    // END OF NORMAL PAYPAL IPN PROCESSING
    die();
}

// NOT NORMAL PROCESSING
// LOG INVALID POSTS FOR MANUAL INVESTIGATION AND INTERVENTION
if ($paypal_reply == "INVALID")
{
    warning_RAY("IPN INVALID", "IPN REPLY $paypal_headers \n\n$errormsg \n\nPOST DATA FOLLOWS: $postdata \n\n");
    die();
}

// OTHERWISE, PayPal RETURNED BAD DATA (OR INTERNET HTTP ERRORS OR TIMEOUT)
warning_RAY("IPN REPLY UNKNOWN", "IPN REPLY $paypal_headers \n\n$errormsg \n\nPOST DATA FOLLOWS: $postdata \n\n");
die();

Open in new window

0
 
GVNPublic123Author Commented:
Ok, stupid me. Its late and Im wasted, its actually variables are created from POST so $item_number is the holder of value and not $paypal['item_number'].

The problem however still exists, how do I get all item numbers and than like array run foreach. Like detect all item_numberx's and quantities of them ordered and than run a loop like foreach($item_number_array as $item_number){for($i=0,$i<$quantity,$i++){/*APPLY PRODUCT*/}}
0
 
GVNPublic123Author Commented:
Maybe I can do something like this, like construct 100 variables for items and quanitities.

for($i=0; $i<100; $i++){
$item_number = ${'item_number'.$i};
for($j=0; $j<100; $j++){
$quantity = ${'quantity'.$j};
//NOW USING $item_number and $quantity perform check of their value and send products if they match
}}

My stoned and tired brain cant think of anything else, so if this post is completely retarded please dont laugh your asses of.
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
GVNPublic123Author Commented:
Ray_Paseur thats is a BEAUTIFUL code. Thanks Ill use it tomorrow... now Im off to bed.
0
 
Ray PaseurCommented:
Thanks for the points and for your kind words.  I hope it still looks good to you in the morning ;-)
0
 
GVNPublic123Author Commented:
Oh yes its good. But I have a problem with it, for some reason it doesn't want to work with item_numbers.
I placed test order having 2 different item's so there are item_number1 and item_number2 in IPN message. But for some reason, cart only processes item_number1. The while loop there doesnt work for me.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.