?
Solved

PayPal IPN Buttons HELP

Posted on 2011-10-04
6
Medium Priority
?
619 Views
Last Modified: 2012-11-04
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.
0
Comment
Question by:GVNPublic123
  • 4
  • 2
6 Comments
 

Author Comment

by:GVNPublic123
ID: 36913041
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
 

Author Comment

by:GVNPublic123
ID: 36913508
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
 
LVL 111

Accepted Solution

by:
Ray Paseur earned 2000 total points
ID: 36913677
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

Author Comment

by:GVNPublic123
ID: 36913698
Ray_Paseur thats is a BEAUTIFUL code. Thanks Ill use it tomorrow... now Im off to bed.
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 36913750
Thanks for the points and for your kind words.  I hope it still looks good to you in the morning ;-)
0
 

Author Comment

by:GVNPublic123
ID: 36918743
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

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many old projects have bad code, but the budget doesn't exist to rewrite the codebase. You can update this code to be safer by introducing contemporary input validation, sanitation, and safer database queries.
The title says it all. Writing any type of PHP Application or API code that provides high throughput, while under a heavy load, seems to be an arcane art form (Black Magic). This article aims to provide some general guidelines for producing this typ…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
Suggested Courses
Course of the Month16 days, 1 hour left to enroll

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question