⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 paypal_functions.php

📁 Zen Cart是真正的电子商务艺术
💻 PHP
📖 第 1 页 / 共 3 页
字号:
      //break up results into a string
      $info = implode("", $info);
    }
    $status = (strstr($info,'VERIFIED')) ? 'VERIFIED' : (strstr($info,'SUCCESS')) ? 'SUCCESS' : '';

    ipn_debug_email('IPN INFO - Confirmation/Validation response ' . "\n" . ($status != '' ? $status : $header_data . $info));

    return array('info' => $info, 'postdata' => $postdata );
  }

/**
 * Write order-history update to ZC tables denoting the update supplied by the IPN
 */
  function ipn_update_orders_status_and_history($ordersID, $new_status = 1, $txn_type) {
    global $db;
    ipn_debug_email('IPN NOTICE :: Updating order #' . (int)$ordersID . ' to status: ' . (int)$new_status . ' (txn_type: ' . $txn_type . ')');
    $db->Execute("update " . TABLE_ORDERS  . "
                    set orders_status = '" . (int)$new_status . "'
                    where orders_id = '" . (int)$ordersID . "'");

    $sql_data_array = array('orders_id' => (int)$ordersID,
                            'orders_status_id' => (int)$new_status,
                            'date_added' => 'now()',
                            'comments' => 'PayPal status: ' . $_POST['payment_status'] . ' ' . ' @ ' . $_POST['payment_date'] . (($_POST['parent_txn_id'] !='') ? "\n" . ' Parent Trans ID:' . $_POST['parent_txn_id'] : '') . "\n" . ' Trans ID:' . $_POST['txn_id'] . "\n" . ' Amount: ' . $_POST['mc_gross'] . ' ' . $_POST['mc_currency'],
                            'customer_notified' => false
                           );
    zen_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);
    ipn_debug_email('IPN NOTICE :: Update complete.');

/** 
 * Activate any downloads associated with an order which has now been cleared
 */
    if ($txn_type=='echeck-cleared' || $txn_type == 'express-checkout-cleared' || substr($txn_type,0,8) == 'cleared-') {
      $check_status = $db->Execute("select date_purchased from " . TABLE_ORDERS . " where orders_id = '" . (int)$ordersID . "'");
      $zc_max_days = date_diff($check_status->fields['date_purchased'], date('Y-m-d H:i:s', time())) + (int)DOWNLOAD_MAX_DAYS;
      ipn_debug_email('IPN NOTICE :: Updating order #' . (int)$ordersID . ' downloads.  New max days: ' . (int)$zc_max_days . ', New count: ' . (int)DOWNLOAD_MAX_COUNT);
      $update_downloads_query = "update " . TABLE_ORDERS_PRODUCTS_DOWNLOAD . " set download_maxdays='" . (int)$zc_max_days . "', download_count='" . (int)DOWNLOAD_MAX_COUNT . "' where orders_id='" . (int)$ordersID . "'";
      $db->Execute($update_downloads_query);
    }
  }

  /**
   * Prepare subtotal and line-item detail content to send to PayPal
   */
  function ipn_getLineItemDetails() {
error_reporting(E_ALL);
    global $order, $currencies, $order_totals, $order_total_modules;
    $optionsST = array();
    $optionsLI = array();
    $onetimeSum = 0;
    $onetimeTax = 0;
    $creditsApplied = 0;
    $creditsTax_applied = 0;
    $sumOfLineItems = 0;
    $sumOfLineTax = 0;

    // prepare subtotals
    $optionsST['handling'] = 0;
    for ($i=0, $n=sizeof($order_totals); $i<$n; $i++) {
      if ($order_totals[$i]['code'] == 'ot_subtotal') $optionsST['subtotal'] = round($order_totals[$i]['value'],2);
      if ($order_totals[$i]['code'] == 'ot_tax')      $optionsST['tax_cart'] = round($order_totals[$i]['value'],2);
      if ($order_totals[$i]['code'] == 'ot_shipping') $optionsST['shipping'] = round($order_totals[$i]['value'],2);
      if ($order_totals[$i]['code'] == 'ot_total')    $optionsST['amount']   = round($order_totals[$i]['value'],2);
      global $$order_totals[$i]['code'];
      if (isset($$order_totals[$i]['code']->credit_class) && $$order_totals[$i]['code']->credit_class == true) $creditsApplied += round($order_totals[$i]['value'],2);
      // treat all other OT's as if they're related to handling fees
      if (!in_array($order_totals[$i]['code'], array('ot_total','ot_subtotal','ot_tax','ot_shipping')) 
          && !(isset($$order_totals[$i]['code']->credit_class) && $$order_totals[$i]['code']->credit_class == true)) {
          $optionsST['handling'] += $order_totals[$i]['value'];
      }
    }

    // Move shipping tax amount from Tax subtotal into Shipping subtotal for submission to PayPal
    $module = substr($_SESSION['shipping']['id'], 0, strpos($_SESSION['shipping']['id'], '_'));
    if (zen_not_null($order->info['shipping_method'])) {
      if ($GLOBALS[$module]->tax_class > 0) {
        $shipping_tax_basis = (!isset($GLOBALS[$module]->tax_basis)) ? STORE_SHIPPING_TAX_BASIS : $GLOBALS[$module]->tax_basis;
        $shippingOnBilling = zen_get_tax_rate($GLOBALS[$module]->tax_class, $order->billing['country']['id'], $order->billing['zone_id']);
        $shippingOnDelivery = zen_get_tax_rate($GLOBALS[$module]->tax_class, $order->delivery['country']['id'], $order->delivery['zone_id']);
        if ($shipping_tax_basis == 'Billing') {
          $shipping_tax = $shippingOnBilling;
        } elseif ($shipping_tax_basis == 'Shipping') {
          $shipping_tax = $shippingOnDelivery;
        } else {
          if (STORE_ZONE == $order->billing['zone_id']) {
            $shipping_tax = $shippingOnBilling;
          } elseif (STORE_ZONE == $order->delivery['zone_id']) {
            $shipping_tax = $shippingOnDelivery;
          } else {
            $shipping_tax = 0;
          }
        }
        $taxAdjustmentForShipping = zen_calculate_tax($order->info['shipping_cost'], $shipping_tax);
        $optionsST['shipping'] += $taxAdjustmentForShipping;
        $optionsST['tax_cart'] -= $taxAdjustmentForShipping;
      }
    }
ipn_logging('DEBUG Round 1', 'Subtotal Info:' . "\n" . print_r($optionsST, true));

    // loop thru all products to display quantity and price. Appends *** if out-of-stock.
    for ($i=0, $n=sizeof($order->products), $k=1; $i<$n; $i++, $k++) {
      $optionsLI["item_number_$k"] = $order->products[$i]['model'];
      $optionsLI["quantity_$k"]    = (int)$order->products[$i]['qty'];
      $optionsLI["item_name_$k"]   = $order->products[$i]['name'];
      $optionsLI["item_name_$k"]  .= (zen_get_products_stock($order->products[$i]['id']) - $order->products[$i]['qty'] < 0 ? STOCK_MARK_PRODUCT_OUT_OF_STOCK : '');

      // if there are attributes, loop thru them and add to description
      if (isset($order->products[$i]['attributes']) && sizeof($order->products[$i]['attributes']) > 0 ) {
        for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) {
          $optionsLI["item_name_$k"] .= "\n " . $order->products[$i]['attributes'][$j]['option'] . 
                                        ': ' . $order->products[$i]['attributes'][$j]['value'];
        } // end loop
      } // endif attribute-info

      $optionsLI["amount_$k"] = $order->products[$i]['final_price'];
      $optionsLI["tax_$k"]    = zen_calculate_tax($order->products[$i]['final_price'], $order->products[$i]['tax']);
      $optionsLI["shipping_$k"] = 0;

      // track one-time charges
      if ($order->products[$i]['onetime_charges'] != 0 ) {
        $onetimeSum += $order->products[$i]['onetime_charges'];
        $onetimeTax += zen_calculate_tax($order->products[$i]['onetime_charges'], $order->products[$i]['tax']);
      }

      // Replace & and = with * if found. 
      $optionsLI["item_name_$k"] = str_replace(array('&','='), '*', $optionsLI["item_name_$k"]);
      $optionsLI["item_name_$k"] = zen_clean_html($optionsLI["item_name_$k"], 'strong');
      $optionsLI["item_name_$k"] = substr($optionsLI["item_name_$k"], 0, 127);

      // reformat properly
      $optionsLI["item_number_$k"] = substr($optionsLI["item_number_$k"], 0, 127);

    }  // end for loopthru all products

    if ($onetimeSum > 0) {
      $i++; $k++;
      $optionsLI["item_number_$k"] = $k;
      $optionsLI["item_name_$k"]   = 'One-Time Charges';
      $optionsLI["amount_$k"]      = $onetimeSum;
      $optionsLI["tax_$k"]         = $onetimeTax;
      $optionsLI["quantity_$k"]    = 1;
    }
ipn_logging('DEBUG Round 2', 'Line Item Info:' . "\n" . print_r($optionsLI, true));

    // handle discounts such as gift certificates and coupons
    if ($creditsApplied > 0) {
      $optionsST['handling'] -= $creditsApplied;
    }

    // add all one-time charges
    $optionsST['subtotal'] += $onetimeSum;

    //ensure things are not negative and not carrying any bad precision
    $optionsST['handling'] = abs(strval($optionsST['handling']));

    // subtotals have to add up to AMT
    // Thus, if there is a discrepancy, make adjustment to HANDLINGAMT:
    $st = $optionsST['subtotal'] + $optionsST['tax_cart'] + $optionsST['shipping'] + $optionsST['handling'];
    if ($st != $optionsST['amount']) $optionsST['handling'] += ($optionsST['amount'] - $st);



    // Since the PayPal spec cannot handle mathematically mismatched values caused by one-time charges,
    // must drop line-item details if any one-time charges apply to this order:
    // And, if there are any discounts in this order, do NOT supply line-item details
    if ($onetimeSum > 0) $optionsLI = array();


    // Do sanity check -- if any of the line-item subtotal math doesn't add up properly, skip line-item details,
    // so that the order can go through even though PayPal isn't being flexible to handle Zen Cart's diversity
    $optionsLI['num_cart_items'] = 0;
    for ($j=1; $j<$k; $j++) {
      $itemAMT = $optionsLI["amount_$j"];
      $itemTAX = $optionsLI["tax_$j"];
      $itemQTY = $optionsLI["quantity_$j"];
      $sumOfLineItems += ($itemQTY * $itemAMT);
      $sumOfLineTax += round(($itemQTY * $itemTAX),2);
      $optionsLI['num_cart_items']++;
    }

    if ((float)strval($optionsST['subtotal']) != (float)strval($sumOfLineItems)) {
      $optionsLI = array();
      ipn_logging('getLineItemDetails 1: Order Subtotal does not match sum of line-item prices. Line-item-details skipped.' . "\n" . (float)$optionsST['subtotal'] . ' ' . (float)$sumOfLineItems);
      //die('ITEMAMT != $sumOfLineItems ' . $optionsST['ITEMAMT'] . ' ' . $sumOfLineItems);
    }
    if ((float)strval($optionsST['tax_cart']) != (float)strval($sumOfLineTax)) {
      for ($i=0, $n=sizeof($order->products), $k=1; $i<$n; $i++, $k++) {
        $optionsLI["tax_$k"] = 0;
      }
      $optionsLI["tax_1"] = $optionsST["tax_cart"];
      ipn_logging('getLineItemDetails 2: Tax Subtotal did not match sum of taxes for line-items. Line-item taxes skipped.' . "\n" . $optionsST['tax_cart'] . ' ' . $sumOfLineTax);
      //die('TAXAMT != $sumofLineTax ' . $optionsST['TAXAMT'] . ' ' . $sumOfLineTax);
    }

    // ensure all numbers are non-negative
    // tidy up all values so that they comply with proper format (number_format(xxxx,2) for PayPal US use )
    if (is_array($optionsST)) foreach ($optionsST as $key=>$value) {
      $optionsST[$key] = number_format(abs(strval($value)), 2);
    }
    if (is_array($optionsLI)) foreach ($optionsLI as $key=>$value) {
      if (strstr($key, 'amount')) $optionsLI[$key] = number_format(abs(strval($value)), 2);
    }

    ipn_logging('getLineItemDetails 3: IPN LineItemDetails: ' . "\n" . ($creditsApplied ? 'Credits apply to this order, so all line-item details are NOT being submitted. Thus, the following data is REDUNDANT and probably VERY INACCURATE' . "\n" : '') . 'Details:' . print_r(array_merge($optionsST, $optionsLI), true) . "\n\n" . 'DEFAULT_CURRENCY = ' . DEFAULT_CURRENCY  . "\nSESSION['currency'] = " . $_SESSION['currency'] . "\n" . "order->info['currency'] = " . $order->info['currency'] . "\n\$currencies->currencies[\$_SESSION['currency']]['value'] = " . $currencies->currencies[$_SESSION['currency']]['value'] . "\n" . print_r($currencies, true));

    // if not default currency, do not send subtotals or line-item details
    if (DEFAULT_CURRENCY != $order->info['currency']) {
      ipn_logging('getLineItemDetails 4: Not using default currency. Thus, no line-item details can be submitted.');
      return array();
    }
    if ($currencies->currencies[$_SESSION['currency']]['value'] != 1) {
      ipn_logging('getLineItemDetails 5: currency val not equal to 1.0000 - cannot proceed without coping with currency conversions. Aborting line-item details.');
      return array();
    }

    // if there are any discounts in this order, do not supply subtotals or line-item details
    if (strval($creditsApplied) > 0) return array();
    //$this->zcLog('getLineItemDetails 6', 'no credits - okay');

    // if subtotals are not adding up correctly, then skip sending any line-item or subtotal details to PayPal
    $st = round(strval($optionsST['subtotal'] + $optionsST['tax_cart'] + $optionsST['shipping'] + $optionsST['handling']),2);
    $stDiff = strval($optionsST['amount'] - $st);
    $stDiffRounded = strval(abs($st) - abs(round($optionsST['amount'],2)));


    ipn_logging('getLineItemDetails 7: checking subtotals... '. "\nitemamt: " . $optionsST['subtotal'] . "\ntaxamt: " . $optionsST['tax_cart'] . "\nshippingamt: " . $optionsST['shipping'] . "\nhandlingamt: " . $optionsST['handling'] . "\n-------------------\nsubtotal: " . number_format($st, 2) . "\namount: " . $optionsST['amount'] . "\n-------------------\ndifference: " . $stDiff . '  (abs+rounded: ' . $stDiffRounded . ')');

    if ( $stDiffRounded != 0) return array(); //die('bad subtotals'); //return array();
    ipn_logging('getLineItemDetails 8: subtotals balance - okay');

    if (abs($optionsST['handling']) == 0) unset($optionsST['handling']);

    // Send Subtotal and LineItem results back to be submitted to PayPal
    return array_merge($optionsST, $optionsLI);
  }

/**
 * Debug logging
 */
  function ipn_logging($stage, $message = '') {
    ipn_add_error_log($stage . ($message != '' ? ': ' . $message : ''));
  }
  function ipn_add_error_log($message, $paypal_instance_id = '') {
    if ($paypal_instance_id == '') $paypal_instance_id = date('mdYGi');
    $fp = @fopen('includes/modules/payment/paypal/logs/ipn_' . $paypal_instance_id . (substr($message, 0, 3) == 'PDT' ? '_PDT' : '') . '.log', 'a');
    if ($fp) {
      fwrite($fp, date('M d Y G:i') . ' -- ' . $message . "\n\n");
      fclose($fp);
    }
  }

?>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -