📄 paypal_functions.php
字号:
//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 + -