[ Index ]

PHP Cross Reference of osCMax 2.0.4

title

Body

[close]

/ext/modules/payment/paypal_ipn/ -> ipn.php (source)

   1  <?php
   2  /*

   3  $Id: ipn.php 3 2006-05-27 04:59:07Z user $

   4  

   5    osCMax Power E-Commerce

   6    http://oscdox.com

   7  

   8    Copyright 2006 osCMax2004 osCommerce

   9  

  10    Released under the GNU General Public License

  11    Original Authors: Harald Ponce de Leon, Mark Evans 

  12    Updates by PandA.nl, Navyhost, Zoeticlight, David, gravyface, AlexStudio, windfjf, Monika in Germany and Terra

  13    v2.3 updated by AlexStudio

  14  */
  15  
  16    chdir('../../../../');
  17    require ('includes/application_top.php');
  18    include(DIR_WS_LANGUAGES . $language . '/' . FILENAME_CHECKOUT_PROCESS);
  19    // BOF configuration keys fix by AlexStudio

  20    require (DIR_WS_CLASSES . 'payment.php');
  21    $payment_modules = new payment(paypal_ipn);
  22    // EOF configuration keys fix by AlexStudio

  23  
  24    $parameters = 'cmd=_notify-validate';
  25  
  26    foreach ($_POST as $key => $value) {
  27      $parameters .= '&' . $key . '=' . urlencode(stripslashes($value));
  28    }
  29  
  30    if (MODULE_PAYMENT_PAYPAL_IPN_GATEWAY_SERVER == 'Live') {
  31      $server = 'www.paypal.com';
  32    } else {
  33      $server = 'www.sandbox.paypal.com';
  34    }
  35  
  36    $fsocket = false;
  37    $curl = false;
  38    $result = false;
  39  
  40    if ( (PHP_VERSION >= 4.3) && ($fp = @fsockopen('ssl://' . $server, 443, $errno, $errstr, 30)) ) {
  41      $fsocket = true;
  42    } elseif (function_exists('curl_exec')) {
  43      $curl = true;
  44    } elseif ($fp = @fsockopen($server, 80, $errno, $errstr, 30)) {
  45      $fsocket = true;
  46    }
  47  
  48    if ($fsocket == true) {
  49      $header = 'POST /cgi-bin/webscr HTTP/1.0' . "\r\n" .
  50                'Host: ' . $server . "\r\n" .
  51                'Content-Type: application/x-www-form-urlencoded' . "\r\n" .
  52                'Content-Length: ' . strlen($parameters) . "\r\n" .
  53                'Connection: close' . "\r\n\r\n";
  54  
  55      @fputs($fp, $header . $parameters);
  56  
  57      $string = '';
  58      while ([email protected]feof($fp)) {
  59        $res = @fgets($fp, 1024);
  60        $string .= $res;
  61  
  62        if ( ($res == 'VERIFIED') || ($res == 'INVALID') ) {
  63          $result = $res;
  64  
  65          break;
  66        }
  67      }
  68  
  69      @fclose($fp);
  70    } elseif ($curl == true) {
  71      $ch = curl_init();
  72  
  73      // BOF add by AlexStudio

  74      // For the poor souls on GoDaddy and the like, set the connection to go through their proxy

  75      if (trim(MODULE_PAYMENT_PAYPAL_IPN_PROXY_SERVER) != '') {
  76        curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
  77        curl_setopt($ch, CURLOPT_PROXY, MODULE_PAYMENT_PAYPAL_IPN_PROXY_SERVER);
  78      }
  79      // Eof add by AlexStudio

  80      curl_setopt($ch, CURLOPT_URL, 'https://' . $server . '/cgi-bin/webscr');
  81      curl_setopt($ch, CURLOPT_POST, true);
  82      curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
  83      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  84      curl_setopt($ch, CURLOPT_HEADER, false);
  85      curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  86      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  87  
  88      $result = curl_exec($ch);
  89  
  90      curl_close($ch);
  91    }
  92  
  93    if ($result == 'VERIFIED') {
  94      if (isset($_POST['invoice']) && is_numeric($_POST['invoice']) && ($_POST['invoice'] > 0)) {
  95        $order_query = tep_db_query("select currency, currency_value from " . TABLE_ORDERS . " where orders_id = '" . $_POST['invoice'] . "' and customers_id = '" . (int)$_POST['custom'] . "'");
  96        if (tep_db_num_rows($order_query) > 0) {
  97          $order_db = tep_db_fetch_array($order_query);
  98  
  99          // let's re-create the required arrays

 100          require (DIR_WS_CLASSES . 'order.php');
 101          $order = new order($_POST['invoice']);
 102  
 103          // let's update the order status

 104          $total_query = tep_db_query("select value from " . TABLE_ORDERS_TOTAL . " where orders_id = '" . $_POST['invoice'] . "' and class = 'ot_total' limit 1");
 105          $total = tep_db_fetch_array($total_query);
 106  
 107          $comment_status = 'payment status: ' . $_POST['payment_status'] . ' (' . ucfirst($_POST['payer_status']) . '; ' . $currencies->format($_POST['mc_gross'], false, $_POST['mc_currency']) . ')';
 108  
 109          if ($_POST['payment_status'] == 'Pending') {
 110            $comment_status .= '; ' . $_POST['pending_reason'];
 111          } elseif ( ($_POST['payment_status'] == 'Reversed') || ($_POST['payment_status'] == 'Refunded') ) {
 112            $comment_status .= '; ' . $_POST['reason_code'];
 113          } elseif ( ($_POST['payment_status'] == 'Completed') && (tep_not_null($_POST['address_street'])) ) {
 114            $comment_status .= ", \n" . PAYPAL_ADDRESS . ": " . $_POST['address_name'] . ", " . $_POST['address_street'] . ", " . $_POST['address_city'] . ", " . $_POST['address_zip'] . ", " . $_POST['address_state'] . ", " . $_POST['address_country'] . ", " . $_POST['address_country_code'] . ", " . $_POST['address_status'];
 115          } 
 116  
 117          $order_status_id = DEFAULT_ORDERS_STATUS_ID;
 118  
 119  // modified AlexStudio's Rounding error bug fix 

 120  // variances of up to 0.05 on either side (plus / minus) are ignored

 121          if ((((number_format($total['value'] * $order_db['currency_value'], $currencies->get_decimal_places($order_db['currency']))) -  $_POST['mc_gross']) <= 0.05)  
 122            &&
 123            (((number_format($total['value'] * $order_db['currency_value'], $currencies->get_decimal_places($order_db['currency']))) -  $_POST['mc_gross']) >= -0.05)) {
 124  
 125  // Terra -> modified update. If payment status is "completed" than a completed order status is chosen based on the admin settings 

 126            if ( (MODULE_PAYMENT_PAYPAL_IPN_COMP_ORDER_STATUS_ID > 0) && ($_POST['payment_status'] == 'Completed') ) {
 127              $order_status_id = MODULE_PAYMENT_PAYPAL_IPN_COMP_ORDER_STATUS_ID;
 128            } elseif (MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID > 0) {
 129              $order_status_id = MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID;
 130            }
 131          }
 132  
 133          // Let's see what the PayPal payment status is and set the notification accordingly

 134          // more info: https://www.paypal.com/IntegrationCenter/ic_ipn-pdt-variable-reference.html

 135          if ( ($_POST['payment_status'] == 'Pending') || ($_POST['payment_status'] == 'Completed')) {
 136            $customer_notified = '1'; 
 137          } else {
 138            $customer_notified = '0'; 
 139          }
 140          tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . $order_status_id . "', last_modified = now() where orders_id = '" . $_POST['invoice'] . "'");
 141  
 142          $sql_data_array = array('orders_id' => $_POST['invoice'],
 143                                  'orders_status_id' => $order_status_id,
 144                                  'date_added' => 'now()',
 145                                  'customer_notified' => $customer_notified,
 146                                  'comments' => 'PayPal IPN Verified [' . $comment_status . ']');
 147  
 148          tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);
 149  // If the order is completed, then we want to send the order email and update the stock

 150          if ($_POST['payment_status'] == 'Completed') { // START STATUS == COMPLETED LOOP
 151  
 152  // initialized for the email confirmation

 153            $products_ordered = '';
 154            $total_tax = 0;
 155  
 156  // let's update the stock  

 157  #######################################################

 158            for ($i=0, $n=sizeof($order->products); $i<$n; $i++) { // PRODUCT LOOP STARTS HERE
 159  // Stock Update - Joao Correia

 160              if (STOCK_LIMITED == 'true') {
 161                if (DOWNLOAD_ENABLED == 'true') {
 162                  $stock_query_raw = "SELECT products_quantity, pad.products_attributes_filename 
 163                                      FROM " . TABLE_PRODUCTS . " p
 164                                      LEFT JOIN " . TABLE_PRODUCTS_ATTRIBUTES . " pa
 165                                      ON p.products_id=pa.products_id
 166                                      LEFT JOIN " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad
 167                                      ON pa.products_attributes_id=pad.products_attributes_id
 168                                      WHERE p.products_id = '" . tep_get_prid($order->products[$i]['id']) . "'";
 169  // Will work with only one option for downloadable products

 170  // otherwise, we have to build the query dynamically with a loop

 171                  $products_attributes = $order->products[$i]['attributes'];
 172                  if (is_array($products_attributes)) {
 173                    $stock_query_raw .= " AND pa.options_id = '" . $products_attributes[0]['option_id'] . "' AND pa.options_values_id = '" . $products_attributes[0]['value_id'] . "'";
 174                  }
 175                  $stock_query = tep_db_query($stock_query_raw);
 176                } else {
 177                  $stock_query = tep_db_query("select products_quantity from " . TABLE_PRODUCTS . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
 178                }
 179                if (tep_db_num_rows($stock_query) > 0) {
 180                  $stock_values = tep_db_fetch_array($stock_query);
 181  // do not decrement quantities if products_attributes_filename exists

 182                  if ((DOWNLOAD_ENABLED != 'true') || (!$stock_values['products_attributes_filename'])) {
 183                    $stock_left = $stock_values['products_quantity'] - $order->products[$i]['qty'];
 184                  } else {
 185                    $stock_left = $stock_values['products_quantity'];
 186                  }
 187                  tep_db_query("update " . TABLE_PRODUCTS . " set products_quantity = '" . $stock_left . "' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
 188                  if ( ($stock_left < 1) && (STOCK_ALLOW_CHECKOUT == 'false') ) {
 189                    tep_db_query("update " . TABLE_PRODUCTS . " set products_status = '0' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
 190                  }
 191                }
 192              }
 193  
 194  // Update products_ordered (for bestsellers list)

 195              tep_db_query("update " . TABLE_PRODUCTS . " set products_ordered = products_ordered + " . sprintf('%d', $order->products[$i]['qty']) . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
 196  
 197  // Let's get all the info together for the email

 198              $total_weight += ($order->products[$i]['qty'] * $order->products[$i]['weight']);
 199              $total_tax += tep_calculate_tax($total_products_price, $products_tax) * $order->products[$i]['qty'];
 200              $total_cost += $total_products_price;
 201  
 202  // Let's get the attributes

 203              $products_ordered_attributes = '';
 204              if ( (isset($order->products[$i]['attributes'])) && (sizeof($order->products[$i]['attributes']) > 0) ) {
 205                for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) {
 206                  $products_ordered_attributes .= "\n\t" . $order->products[$i]['attributes'][$j]['option'] . ' ' . $order->products[$i]['attributes'][$j]['value'];
 207                }
 208              } 
 209  
 210  // Let's format the products model       

 211              $products_model = '';      
 212              if ( !empty($order->products[$i]['model']) ) {
 213                $products_model = ' (' . $order->products[$i]['model'] . ')';
 214              } 
 215  
 216  // Let's put all the product info together into a string

 217              $products_ordered .= $order->products[$i]['qty'] . ' x ' . $order->products[$i]['name'] . $products_model . ' = ' . $currencies->display_price($order->products[$i]['final_price'], $order->products[$i]['tax'], $order->products[$i]['qty']) . $products_ordered_attributes . "\n";
 218            }        // PRODUCT LOOP ENDS HERE

 219  #######################################################

 220  
 221  // lets start with the email confirmation

 222  // BOF content type fix by AlexStudio

 223              $content_type = '';
 224              $content_count = 0;
 225              // BOF order comment fix

 226              $comment_query = tep_db_query("select comments from " . TABLE_ORDERS_STATUS_HISTORY . " where orders_id = '" . $_POST['invoice'] . "'");
 227              $comment_array = tep_db_fetch_array($comment_query);
 228              $comments = $comment_array['comments'];
 229              // EOF order comment fix

 230  
 231              if (DOWNLOAD_ENABLED == 'true') {
 232                $content_query = tep_db_query("select * from " . TABLE_ORDERS_PRODUCTS_DOWNLOAD . " where orders_id = '" . (int)$_POST['invoice'] . "'");
 233                $content_count = tep_db_num_rows($content_query);
 234                if ($content_count > 0) {
 235                  $content_type = 'virtual';
 236                }
 237              }
 238              switch ($content_type) {
 239                case 'virtual':
 240                  if ($content_count != sizeof($order->products)) $content_type = 'mixed'; 
 241                  break;
 242                default:
 243                  $content_type = 'physical';
 244                  break;
 245              }
 246  // EOF content type fix by AlexStudio

 247  // $order variables have been changed from checkout_process to work with the variables from the function query () instead of cart () in the order class

 248            $email_order = STORE_NAME . "\n" . 
 249                           EMAIL_SEPARATOR . "\n" . 
 250                           EMAIL_TEXT_ORDER_NUMBER . ' ' . $_POST['invoice'] . "\n" .
 251                           EMAIL_TEXT_INVOICE_URL . ' ' . tep_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id=' . $_POST['invoice'], 'SSL', false) . "\n" .
 252                           EMAIL_TEXT_DATE_ORDERED . ' ' . strftime(DATE_FORMAT_LONG) . "\n\n";
 253  
 254            // BOF order comment fix by AlexStudio

 255            if ($comments) {
 256              $email_order .= $comments . "\n\n";
 257            }
 258            // EOF order comment fix by AlexStudio

 259  
 260            $email_order .= EMAIL_TEXT_PRODUCTS . "\n" . 
 261                            EMAIL_SEPARATOR . "\n" . 
 262                            $products_ordered . 
 263                            EMAIL_SEPARATOR . "\n";
 264  
 265            for ($i=0, $n=sizeof($order->totals); $i<$n; $i++) {
 266              $email_order .= strip_tags($order->totals[$i]['title']) . ' ' . strip_tags($order->totals[$i]['text']) . "\n";
 267            }
 268  
 269            // BOF content type fix by AlexStudio

 270            if ($content_type != 'virtual') {
 271            // EOF content type fix by AlexStudio

 272              $email_order .= "\n" . EMAIL_TEXT_DELIVERY_ADDRESS . "\n" . 
 273                              EMAIL_SEPARATOR . "\n" .
 274                              tep_address_format($order->delivery['format_id'], $order->delivery,  0, '', "\n") . "\n";
 275            }
 276  
 277            $email_order .= "\n" . EMAIL_TEXT_BILLING_ADDRESS . "\n" .
 278                            EMAIL_SEPARATOR . "\n" .
 279                            tep_address_format($order->billing['format_id'], $order->billing, 0, '', "\n") . "\n\n";
 280            if (is_object($$payment)) {
 281              $email_order .= EMAIL_TEXT_PAYMENT_METHOD . "\n" . 
 282                              EMAIL_SEPARATOR . "\n";
 283              $payment_class = $$payment;
 284              $email_order .= $payment_class->title . "\n\n";
 285              if ($payment_class->email_footer) { 
 286                $email_order .= $payment_class->email_footer . "\n\n";
 287              }
 288            }
 289            tep_mail($order->customer['name'], $order->customer['email_address'], EMAIL_TEXT_SUBJECT, $email_order, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
 290  
 291  // send emails to other people

 292            if (SEND_EXTRA_ORDER_EMAILS_TO != '') {
 293              tep_mail('', SEND_EXTRA_ORDER_EMAILS_TO, EMAIL_TEXT_SUBJECT, $email_order, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
 294            }
 295          } // END STATUS == COMPLETED LOOP

 296  
 297          if ($_POST['payment_status'] == 'Pending') { // START STATUS == PENDING LOOP
 298  
 299            $email_order = STORE_NAME . "\n" . 
 300                           EMAIL_SEPARATOR . "\n" . 
 301                           EMAIL_TEXT_ORDER_NUMBER . ' ' . $_POST['invoice'] . "\n" .
 302                           EMAIL_TEXT_INVOICE_URL . ' ' . tep_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id=' . $_POST['invoice'], 'SSL', false) . "\n" .
 303                           EMAIL_TEXT_DATE_ORDERED . ' ' . strftime(DATE_FORMAT_LONG) . "\n\n" . 
 304                           EMAIL_SEPARATOR . "\n" .
 305                           EMAIL_PAYPAL_PENDING_NOTICE . "\n\n"; 
 306  
 307            tep_mail($order->customer['name'], $order->customer['email_address'], EMAIL_TEXT_SUBJECT, $email_order, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
 308  
 309  // send emails to other people

 310            if (SEND_EXTRA_ORDER_EMAILS_TO != '') {
 311              tep_mail('', SEND_EXTRA_ORDER_EMAILS_TO, EMAIL_TEXT_SUBJECT, $email_order, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
 312            } 
 313          } // END STATUS == PENDING LOOP

 314  //emptying cart for everyone! by Monika in Germany

 315          tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$_POST['custom'] . "'");
 316          tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " where customers_id = '" . (int)$_POST['custom'] . "'");
 317  //end emptying cart for everyone

 318        }
 319      }
 320    } else {
 321      if (tep_not_null(MODULE_PAYMENT_PAYPAL_IPN_DEBUG_EMAIL)) {
 322        $email_body = '$_POST:' . "\n\n";
 323        foreach ($_POST as $key => $value) {
 324          $email_body .= $key . '=' . $value . "\n";
 325        }
 326        $email_body .= "\n" . '$_GET:' . "\n\n";
 327        foreach ($_GET as $key => $value) {
 328          $email_body .= $key . '=' . $value . "\n";
 329        }
 330        tep_mail('', MODULE_PAYMENT_PAYPAL_IPN_DEBUG_EMAIL, 'PayPal IPN Invalid Process', $email_body, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
 331      }
 332  
 333      if (isset($_POST['invoice']) && is_numeric($_POST['invoice']) && ($_POST['invoice'] > 0)) {
 334        $check_query = tep_db_query("select orders_id from " . TABLE_ORDERS . " where orders_id = '" . $_POST['invoice'] . "' and customers_id = '" . (int)$_POST['custom'] . "'");
 335        if (tep_db_num_rows($check_query) > 0) {
 336          $comment_status = $_POST['payment_status'];
 337  
 338          if ($_POST['payment_status'] == 'Pending') {
 339            $comment_status .= '; ' . $_POST['pending_reason'];
 340          } elseif ( ($_POST['payment_status'] == 'Reversed') || ($_POST['payment_status'] == 'Refunded') ) {
 341            $comment_status .= '; ' . $_POST['reason_code'];
 342          }
 343  
 344          tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . ((MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID > 0) ? MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID : DEFAULT_ORDERS_STATUS_ID) . "', last_modified = now() where orders_id = '" . $_POST['invoice'] . "'");
 345  
 346          $sql_data_array = array('orders_id' => $_POST['invoice'],
 347                                  'orders_status_id' => (MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID > 0) ? MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID : DEFAULT_ORDERS_STATUS_ID,
 348                                  'date_added' => 'now()',
 349                                  'customer_notified' => '0',
 350                                  'comments' => 'PayPal IPN Invalid [' . $comment_status . ']');
 351  
 352          tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);
 353        }
 354      }
 355    }
 356  
 357    require ('includes/application_bottom.php');
 358  ?>


Generated: Fri Jan 1 13:43:16 2010 Cross-referenced by PHPXref 0.7