Zencart 使用 Paypal 付款,会出现漏单的情况,即 paypal 已经收到客户的付款,但是网站后台没有客户的订单。导致 paypal 漏单的原因大致会是当客户跳转到Paypal 网站付款完毕之后,直接关闭了窗口,或者网络不稳定,没有正常跳转到网站。
解决 Paypal 漏单问题的方案有好几种:
一. 开启 Detailed Line Items in Cart 选项。
原理:在 zencart 后台 Module --> Payment --> PayPal Website Payments Standard - IPN 开启 Detailed Line Items in Cart 选项。这个选项会把你所有的订单物品信息传给 paypal,当客户付款成功而后台未能成功生成订单时,也可以通过 paypal 帐号交易信息看到客户购买了哪些物品。
二. 使用 Paypal Sessions Viewer 插件找回 Paypal 漏掉的订单。
原理:zencart 购物车的物品,通过 paypal 方式付款,会在 paypal_session 表中保存此次付款的所有记录,如果付款成功后,从 paypal 网站跳转到购物网站并生成了订单时,zencart系统会自动删除这条 paypal_session 记录,如果没有成功跳转到购物网站,没有成功生成订单,那这条付款记录数据就会一直保存在数据库,当使用 Paypal Session Viewer 插件,就能查看这条记录的所有数据,包括客户信息,购物时间,商品信息,如果你确定已收到款,就可以把这条 paypal_session 信息转移到订单中,生成一个订单。
插件下载地址:http://www.zen-cart.cn/english-version-modules/admin-tools/paypal-sessions-viewer
三. 修改付款流程,先生成订单后付款。
原理:用过zen-cart的人都知道,zen-cart中下单步骤是下面这样的(其中[]中的表示不是必须的):
1. 购物车(shopping cart)
2. [货运方式(delivery method)]
3. 支付方式(payment method)
4. 订单确认(confirmation)
5. [第三方网站支付]
6. 订单处理(checkout process)——这一步比较重要,因为会在这里将购物车中的信息写入订单
7. 下单成功(checkout success)
这样的流程在正常情况下是没有任何问题的。但是,从第5步到第6部的过程中,用户可能以为付款成功就直接关闭掉网页了,或者由于网络原因造成不能正常跳转到checkout_process页面,这样造成的后果是很严重的,因为订单不能被正常的创建。基于上述的分析, 我们希望稍微地改变一下流程,即在支付之前订单已经创建好了,这样就算在支付时不能从第三方支付网站跳转回来,我们也不会存在用户付款成功却在后台没有订单的情况了。
本人是参照东国先生的这篇 修改zen-cart下单和付款流程以防止漏单 教程去修改的,因为这个教程比较老,而且也没有很全面,所以我根据自己的实际需求,把他做的更完善,更细节化。
经过修改后的蓝图基本是下面这样的:
1. 在checkour_confirmation页面确认订单后,都会直接proccess,并且进入 account_history_info 页面,可以在这里进入付款页面。如下图所示:
2. 如果当时客户没能付款,也可进入自己的后台对历史订单进行付款。如下图所示:
3. 未付款的订单,可以在后台修改价格,像淘宝一样拍下宝贝后,店主给你修改价格后再付款一样。如下图所示:
下面我们来正式修改代码,首先我列举出所有要修改的文件:
1. includes/classes/payment.php
2. includes/modules/payment/paypal.php
3. includes/classes/order.php
4. includes/modules/pages/checkout_process/header_php.php
5. includes/modules/pages/account_history_info/header_php.php
6. includes/templates/你的模板目录/templates/tpl_account_history_info_default.php
7. includes/templates/你的模板目录/templates/tpl_account_history_default.php
8. ipn_main_handler.php
9. admin(后台目录)/orders.php
因为先生成订单再付款,付款步骤就会比原来又多了一步,为了简化付款流程,我安装了 Fast And Easy Checkout For Zencart(快速支付) 插件,安装此插件之前,需要安装另外一个插件 Css Js Loader For Zencart,这是快速支付插件的依赖插件。快速支付与先生成订单后支付没什么因果关系,所以如果你不想安装的话完全可以不理。
按步骤修改上面列举的文件:
1. 首先我们需要对现有的支付模块进行一个改造。需要对支付方式的class增加一个字段paynow_action_url,用来表示进行支付的页面 url,另外还需要增加一个函数,paynow_button($order_id),来获取支付表单的参数隐藏域代码。
要增加 paynow_action_url 变量,请在类payment的构造函数中最后加上下面的代码:
if ( (zen_not_null($module)) && (in_array($module.'.php', $this->modules)) && (isset($GLOBALS[$module]->paynow_action_url)) ) { $this->paynow_action_url = $GLOBALS[$module]->paynow_action_url; }
要增加paynow_button($order_id)函数,请在payment类的最后一个函数之后加上如下的代码:
function paynow_button($order_id){ if (is_array($this->modules)) { if (is_object($GLOBALS[$this->selected_module])) { return $GLOBALS[$this->selected_module]->paynow_button($order_id); } }}
2. 以paypal支付方式为例子,说明如何具体实现。这里直接修改 paypal.php 文件,注意备份此文件。代码如下所示,可以看到,这里去掉了对 form_action_url 的指定,并给定了 paynow_action_url,因为我们希望用户点击“确认订单”后直接进入checkout_process,所以如果不指定 form_action_url,那么确认订单的表单就会直接提交到 checkout_process 页面了,而 paynow_action_url 就是 以前的 form_action_url 的值。paynow_button 函数的实现也很简单,这里只是将原先的 process_button() 函数的内容剪切过来而已,只不过我们没有使用全局的$order变量,而是使用 $order = new order($order_id),来重新构造的一个对象,这样做是为在历史订单中显示pay now按钮做准备的。paypal.php修改后的文件如下:
1 <?php 2 /** 3 * paypal.php payment module class for PayPal Website Payments Standard (IPN) method 4 * 5 * @package paymentMethod 6 * @copyright Copyright 2003-2010 Zen Cart Development Team 7 * @copyright Portions Copyright 2003 osCommerce 8 * @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0 9 * @version $Id: paypal.php 15735 2010-03-29 07:13:53Z drbyte $ 10 */ 11 12 define('MODULE_PAYMENT_PAYPAL_TAX_OVERRIDE', 'true'); 13 14 /** 15 * ensure dependencies are loaded 16 */ 17 include_once((IS_ADMIN_FLAG === true ? DIR_FS_CATALOG_MODULES : DIR_WS_MODULES) . 'payment/paypal/paypal_functions.php'); 18 19 /** 20 * paypal.php payment module class for PayPal Website Payments Standard (IPN) method 21 * 22 */ 23 class paypal extends base { 24 /** 25 * string representing the payment method 26 * 27 * @var string 28 */ 29 var $code; 30 /** 31 * $title is the displayed name for this payment method 32 * 33 * @var string 34 */ 35 var $title; 36 /** 37 * $description is a soft name for this payment method 38 * 39 * @var string 40 */ 41 var $description; 42 /** 43 * $enabled determines whether this module shows or not... in catalog. 44 * 45 * @var boolean 46 */ 47 var $enabled; 48 /** 49 * constructor 50 * 51 * @param int $paypal_ipn_id 52 * @return paypal 53 */ 54 function paypal($paypal_ipn_id = '') { 55 global $order, $messageStack; 56 $this->code = 'paypal'; 57 $this->codeVersion = '1.3.9'; 58 if (IS_ADMIN_FLAG === true) { 59 $this->title = MODULE_PAYMENT_PAYPAL_TEXT_ADMIN_TITLE; // Payment Module title in Admin 60 if (IS_ADMIN_FLAG === true && defined('MODULE_PAYMENT_PAYPAL_IPN_DEBUG') && MODULE_PAYMENT_PAYPAL_IPN_DEBUG != 'Off') $this->title .= '<span class="alert"> (debug mode active)</span>'; 61 if (IS_ADMIN_FLAG === true && MODULE_PAYMENT_PAYPAL_TESTING == 'Test') $this->title .= '<span class="alert"> (dev/test mode active)</span>'; 62 } else { 63 $this->title = MODULE_PAYMENT_PAYPAL_TEXT_CATALOG_TITLE; // Payment Module title in Catalog 64 } 65 $this->description = MODULE_PAYMENT_PAYPAL_TEXT_DESCRIPTION; 66 $this->sort_order = MODULE_PAYMENT_PAYPAL_SORT_ORDER; 67 $this->enabled = ((MODULE_PAYMENT_PAYPAL_STATUS == 'True') ? true : false); 68 if ((int)MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID > 0) { 69 $this->order_status = MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID; 70 } 71 if (is_object($order)) $this->update_status(); 72 $this->paynow_action_url = 'https://' . MODULE_PAYMENT_PAYPAL_HANDLER; 73 74 if (PROJECT_VERSION_MAJOR != '1' && substr(PROJECT_VERSION_MINOR, 0, 3) != '3.9') $this->enabled = false; 75 76 // verify table structure 77 if (IS_ADMIN_FLAG === true) $this->tableCheckup(); 78 } 79 /** 80 * calculate zone matches and flag settings to determine whether this module should display to customers or not 81 * 82 */ 83 function update_status() { 84 global $order, $db; 85 86 if ( ($this->enabled == true) && ((int)MODULE_PAYMENT_PAYPAL_ZONE > 0) ) { 87 $check_flag = false; 88 $check_query = $db->Execute("select zone_id from " . TABLE_ZONES_TO_GEO_ZONES . " where geo_zone_id = '" . MODULE_PAYMENT_PAYPAL_ZONE . "' and zone_country_id = '" . $order->billing['country']['id'] . "' order by zone_id"); 89 while (!$check_query->EOF) { 90 if ($check_query->fields['zone_id'] < 1) { 91 $check_flag = true; 92 break; 93 } elseif ($check_query->fields['zone_id'] == $order->billing['zone_id']) { 94 $check_flag = true; 95 break; 96 } 97 $check_query->MoveNext(); 98 } 99 100 if ($check_flag == false) {101 $this->enabled = false;102 }103 }104 }105 /**106 * JS validation which does error-checking of data-entry if this module is selected for use107 * (Number, Owner, and CVV Lengths)108 *109 * @return string110 */111 function javascript_validation() {112 return false;113 }114 /**115 * Displays payment method name along with Credit Card Information Submission Fields (if any) on the Checkout Payment Page116 *117 * @return array118 */119 function selection() {120 return array('id' => $this->code,121 'module' => MODULE_PAYMENT_PAYPAL_TEXT_CATALOG_LOGO,122 'icon' => MODULE_PAYMENT_PAYPAL_TEXT_CATALOG_LOGO123 );124 }125 /**126 * Normally evaluates the Credit Card Type for acceptance and the validity of the Credit Card Number & Expiration Date127 * Since paypal module is not collecting info, it simply skips this step.128 *129 * @return boolean130 */131 function pre_confirmation_check() {132 return false;133 }134 /**135 * Display Credit Card Information on the Checkout Confirmation Page136 * Since none is collected for paypal before forwarding to paypal site, this is skipped137 *138 * @return boolean139 */140 function confirmation() {141 return false;142 }143 /**144 * Build the data and actions to process when the "Submit" button is pressed on the order-confirmation screen.145 * This sends the data to the payment gateway for processing.146 * (These are hidden fields on the checkout confirmation page)147 *148 * @return string149 */150 function process_button() {151 return false;152 }153 /**154 * Determine the language to use when visiting the PayPal site155 */156 function getLanguageCode() {157 global $order;158 $lang_code = '';159 $orderISO = zen_get_countries($order->customer['country']['id'], true);160 $storeISO = zen_get_countries(STORE_COUNTRY, true);161 if (in_array(strtoupper($orderISO['countries_iso_code_2']), array('US', 'AU', 'DE', 'FR', 'IT', 'GB', 'ES', 'AT', 'BE', 'CA', 'CH', 'CN', 'NL', 'PL'))) {162 $lang_code = strtoupper($orderISO['countries_iso_code_2']);163 } elseif (in_array(strtoupper($storeISO['countries_iso_code_2']), array('US', 'AU', 'DE', 'FR', 'IT', 'GB', 'ES', 'AT', 'BE', 'CA', 'CH', 'CN', 'NL', 'PL'))) {164 $lang_code = strtoupper($storeISO['countries_iso_code_2']);165 } elseif (in_array(strtoupper($_SESSION['languages_code']), array('EN', 'US', 'AU', 'DE', 'FR', 'IT', 'GB', 'ES', 'AT', 'BE', 'CA', 'CH', 'CN', 'NL', 'PL'))) {166 $lang_code = $_SESSION['languages_code'];167 if (strtoupper($lang_code) == 'EN') $lang_code = 'US';168 }169 //return $orderISO['countries_iso_code_2'];170 return strtoupper($lang_code);171 }172 /**173 * Store transaction info to the order and process any results that come back from the payment gateway174 */175 function before_process() {176 return false;177 }178 /**179 * Checks referrer180 *181 * @param string $zf_domain182 * @return boolean183 */184 function check_referrer($zf_domain) {185 return true;186 }187 /**188 * Build admin-page components189 *190 * @param int $zf_order_id191 * @return string192 */193 function admin_notification($zf_order_id) {194 global $db;195 $output = '';196 $sql = "select * from " . TABLE_PAYPAL . " where order_id = '" . (int)$zf_order_id . "' order by paypal_ipn_id DESC LIMIT 1";197 $ipn = $db->Execute($sql);198 if ($ipn->RecordCount() > 0 && file_exists(DIR_FS_CATALOG . DIR_WS_MODULES . 'payment/paypal/paypal_admin_notification.php')) require(DIR_FS_CATALOG . DIR_WS_MODULES . 'payment/paypal/paypal_admin_notification.php');199 return $output;200 }201 /**202 * Post-processing activities203 * When the order returns from the processor, if PDT was successful, this stores the results in order-status-history and logs data for subsequent reference204 *205 * @return boolean206 */207 function after_process() {208 return false;209 }210 /**211 * Used to display error message details212 *213 * @return boolean214 */215 function output_error() {216 return false;217 }218 /**219 * Check to see whether module is installed220 *221 * @return boolean222 */223 function check() {224 global $db;225 if (IS_ADMIN_FLAG === true) {226 global $sniffer;227 if ($sniffer->field_exists(TABLE_PAYPAL, 'zen_order_id')) $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE COLUMN zen_order_id order_id int(11) NOT NULL default '0'");228 }229 if (!isset($this->_check)) {230 $check_query = $db->Execute("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = 'MODULE_PAYMENT_PAYPAL_STATUS'");231 $this->_check = $check_query->RecordCount();232 }233 return $this->_check;234 }235 /**236 * Install the payment module and its configuration settings237 *238 */239 function install() {240 global $db, $messageStack;241 if (defined('MODULE_PAYMENT_PAYPAL_STATUS')) {242 $messageStack->add_session('PayPal Website Payments Standard module already installed.', 'error');243 zen_redirect(zen_href_link(FILENAME_MODULES, 'set=payment&module=paypal', 'NONSSL'));244 return 'failed';245 }246 if (defined('MODULE_PAYMENT_PAYPALWPP_STATUS')) {247 $messageStack->add_session('NOTE: PayPal Express Checkout module already installed. You don\'t need Standard if you have Express installed.', 'error');248 zen_redirect(zen_href_link(FILENAME_MODULES, 'set=payment&module=paypalwpp', 'NONSSL'));249 return 'failed';250 }251 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable PayPal Module', 'MODULE_PAYMENT_PAYPAL_STATUS', 'True', 'Do you want to accept PayPal payments?', '6', '0', 'zen_cfg_select_option(array(\'True\', \'False\'), ', now())");252 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Business ID', 'MODULE_PAYMENT_PAYPAL_BUSINESS_ID','".STORE_OWNER_EMAIL_ADDRESS."', 'Primary email address for your PayPal account.<br />NOTE: This must match <strong>EXACTLY </strong>the primary email address on your PayPal account settings. It <strong>IS case-sensitive</strong>, so please check your PayPal profile preferences at paypal.com and be sure to enter the EXACT same primary email address here.', '6', '2', now())");253 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Transaction Currency', 'MODULE_PAYMENT_PAYPAL_CURRENCY', 'Selected Currency', 'Which currency should the order be sent to PayPal as? <br />NOTE: if an unsupported currency is sent to PayPal, it will be auto-converted to USD.', '6', '3', 'zen_cfg_select_option(array(\'Selected Currency\', \'Only USD\', \'Only AUD\', \'Only CAD\', \'Only EUR\', \'Only GBP\', \'Only CHF\', \'Only CZK\', \'Only DKK\', \'Only HKD\', \'Only HUF\', \'Only JPY\', \'Only NOK\', \'Only NZD\', \'Only PLN\', \'Only SEK\', \'Only SGD\', \'Only THB\', \'Only MXN\', \'Only ILS\', \'Only PHP\', \'Only TWD\', \'Only BRL\', \'Only MYR\'), ', now())");254 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Payment Zone', 'MODULE_PAYMENT_PAYPAL_ZONE', '0', 'If a zone is selected, only enable this payment method for that zone.', '6', '4', 'zen_get_zone_class_title', 'zen_cfg_pull_down_zone_classes(', now())");255 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('Set Pending Notification Status', 'MODULE_PAYMENT_PAYPAL_PROCESSING_STATUS_ID', '" . DEFAULT_ORDERS_STATUS_ID . "', 'Set the status of orders made with this payment module that are not yet completed to this value<br />(\'Pending\' recommended)', '6', '5', 'zen_cfg_pull_down_order_statuses(', 'zen_get_order_status_name', now())");256 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('Set Order Status', 'MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID', '2', 'Set the status of orders made with this payment module that have completed payment to this value<br />(\'Processing\' recommended)', '6', '6', 'zen_cfg_pull_down_order_statuses(', 'zen_get_order_status_name', now())");257 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('Set Refund Order Status', 'MODULE_PAYMENT_PAYPAL_REFUND_ORDER_STATUS_ID', '1', 'Set the status of orders that have been refunded made with this payment module to this value<br />(\'Pending\' recommended)', '6', '7', 'zen_cfg_pull_down_order_statuses(', 'zen_get_order_status_name', now())");258 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort order of display.', 'MODULE_PAYMENT_PAYPAL_SORT_ORDER', '0', 'Sort order of display. Lowest is displayed first.', '6', '8', now())");259 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Address Override', 'MODULE_PAYMENT_PAYPAL_ADDRESS_OVERRIDE', '1', 'If set to 1, the customer shipping address selected in Zen Cart will override the customer PayPal-stored address book. The customer will see their address from Zen Cart, but will NOT be able to edit it at PayPal.<br />(An invalid address will be treated by PayPal as not-supplied, or override=0)<br />0=No Override<br />1=ZC address overrides PayPal address choices', '6', '18', 'zen_cfg_select_option(array(\'0\',\'1\'), ', now())");260 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Shipping Address Requirements?', 'MODULE_PAYMENT_PAYPAL_ADDRESS_REQUIRED', '2', 'The buyers shipping address. If set to 0 your customer will be prompted to include a shipping address. If set to 1 your customer will not be asked for a shipping address. If set to 2 your customer will be required to provide a shipping address.<br />0=Prompt<br />1=Not Asked<br />2=Required<br /><br /><strong>NOTE: If you allow your customers to enter their own shipping address, then MAKE SURE you PERSONALLY manually verify the PayPal confirmation details to verify the proper address when filling orders. When using Website Payments Standard (IPN), Zen Cart does not know if they choose an alternate shipping address at PayPal vs the one entered when placing an order.</strong>', '6', '20', 'zen_cfg_select_option(array(\'0\',\'1\',\'2\'), ', now())");261 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Detailed Line Items in Cart', 'MODULE_PAYMENT_PAYPAL_DETAILED_CART', 'No', 'Do you want to give line-item details to PayPal? If set to True, line-item details will be shared with PayPal if no discounts apply and if tax and shipping are simple. Otherwise an Aggregate cart summary will be sent.', '6', '22', 'zen_cfg_select_option(array(\'No\',\'Yes\'), ', now())");262 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Page Style', 'MODULE_PAYMENT_PAYPAL_PAGE_STYLE', 'Primary', 'Sets the Custom Payment Page Style for payment pages. The value of page_style is the same as the Page Style Name you chose when adding or editing the page style. You can add and edit Custom Payment Page Styles from the Profile subtab of the My Account tab on the PayPal site. If you would like to always reference your Primary style, set this to \"primary.\" If you would like to reference the default PayPal page style, set this to \"paypal\".', '6', '25', now())");263 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Mode for PayPal web services<br /><br />Default:<br /><code>www.paypal.com/cgi-bin/webscr</code><br />or<br /><code>www.paypal.com/us/cgi-bin/webscr</code><br />or for the UK,<br /><code>www.paypal.com/uk/cgi-bin/webscr</code>', 'MODULE_PAYMENT_PAYPAL_HANDLER', 'www.paypal.com/cgi-bin/webscr', 'Choose the URL for PayPal live processing', '6', '73', '', now())");264 // sandbox: www.sandbox.paypal.com/cgi-bin/webscr265 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added, use_function) values ('PDT Token (Payment Data Transfer)', 'MODULE_PAYMENT_PAYPAL_PDTTOKEN', '', 'Enter your PDT Token value here in order to activate transactions immediately after processing (if they pass validation).', '6', '25', now(), 'zen_cfg_password_display')");266 // Paypal testing options here267 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Debug Mode', 'MODULE_PAYMENT_PAYPAL_IPN_DEBUG', 'Off', 'Enable debug logging? <br />NOTE: This can REALLY clutter your email inbox!<br />Logging goes to the /includes/modules/payment/paypal/logs folder<br />Email goes to the store-owner address.<br />Email option NOT recommended.<br /><strong>Leave OFF for normal operation.</strong>', '6', '71', 'zen_cfg_select_option(array(\'Off\',\'Log File\',\'Log and Email\'), ', now())");268 $db->Execute("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Debug Email Address', 'MODULE_PAYMENT_PAYPAL_DEBUG_EMAIL_ADDRESS','".STORE_OWNER_EMAIL_ADDRESS."', 'The email address to use for PayPal debugging', '6', '72', now())");269 270 $this->notify('NOTIFY_PAYMENT_PAYPAL_INSTALLED');271 }272 /**273 * Remove the module and all its settings274 *275 */276 function remove() {277 global $db;278 $db->Execute("delete from " . TABLE_CONFIGURATION . " where configuration_key LIKE 'MODULE\_PAYMENT\_PAYPAL\_%'");279 $this->notify('NOTIFY_PAYMENT_PAYPAL_UNINSTALLED');280 }281 /**282 * Internal list of configuration keys used for configuration of the module283 *284 * @return array285 */286 function keys() {287 $keys_list = array(288 'MODULE_PAYMENT_PAYPAL_STATUS',289 'MODULE_PAYMENT_PAYPAL_BUSINESS_ID',290 'MODULE_PAYMENT_PAYPAL_PDTTOKEN',291 'MODULE_PAYMENT_PAYPAL_CURRENCY',292 'MODULE_PAYMENT_PAYPAL_ZONE',293 'MODULE_PAYMENT_PAYPAL_PROCESSING_STATUS_ID',294 'MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID',295 'MODULE_PAYMENT_PAYPAL_REFUND_ORDER_STATUS_ID',296 'MODULE_PAYMENT_PAYPAL_SORT_ORDER',297 'MODULE_PAYMENT_PAYPAL_DETAILED_CART',298 'MODULE_PAYMENT_PAYPAL_ADDRESS_OVERRIDE' ,299 'MODULE_PAYMENT_PAYPAL_ADDRESS_REQUIRED' ,300 'MODULE_PAYMENT_PAYPAL_PAGE_STYLE' ,301 'MODULE_PAYMENT_PAYPAL_HANDLER',302 'MODULE_PAYMENT_PAYPAL_IPN_DEBUG',303 );304 305 // Paypal testing/debug options go here:306 if (IS_ADMIN_FLAG === true) {307 if (isset($_GET['debug']) && $_GET['debug']=='on') {308 $keys_list[]='MODULE_PAYMENT_PAYPAL_DEBUG_EMAIL_ADDRESS'; /* this defaults to store-owner-email-address */309 }310 }311 return $keys_list;312 }313 314 function _getPDTresults($orderAmount, $my_currency, $pdtTX) {315 global $db;316 $ipnData = ipn_postback('PDT', $pdtTX);317 $respdata = $ipnData['info'];318 319 // parse the data320 $lines = explode("\n", $respdata);321 $this->pdtData = array();322 for ($i=1; $i<count($lines);$i++){323 if (!strstr($lines[$i], "=")) continue;324 list($key,$val) = explode("=", $lines[$i]);325 $this->pdtData[urldecode($key)] = urldecode($val);326 }327 328 if ($this->pdtData['txn_id'] == '' || $this->pdtData['payment_status'] == '') {329 ipn_debug_email('PDT Returned INVALID Data. Must wait for IPN to process instead. ' . "\n" . print_r($this->pdtData, true));330 return FALSE;331 } else {332 ipn_debug_email('PDT Returned Data ' . print_r($this->pdtData, true));333 }334 335 $_POST['mc_gross'] = $this->pdtData['mc_gross'];336 $_POST['mc_currency'] = $this->pdtData['mc_currency'];337 $_POST['business'] = $this->pdtData['business'];338 $_POST['receiver_email'] = $this->pdtData['receiver_email'];339 340 $PDTstatus = (ipn_validate_transaction($respdata, $this->pdtData, 'PDT') && valid_payment($orderAmount, $my_currency, 'PDT') && $this->pdtData['payment_status'] == 'Completed');341 if ($this->pdtData['payment_status'] != '' && $this->pdtData['payment_status'] != 'Completed') {342 ipn_debug_email('PDT WARNING :: Order not marked as "Completed". Check for Pending reasons or wait for IPN to complete.' . "\n" . '[payment_status] => ' . $this->pdtData['payment_status'] . "\n" . '[pending_reason] => ' . $this->pdtData['pending_reason']);343 }344 345 $sql = "SELECT order_id, paypal_ipn_id, payment_status, txn_type, pending_reason346 FROM " . TABLE_PAYPAL . "347 WHERE txn_id = :transactionID OR parent_txn_id = :transactionID348 ORDER BY order_id DESC ";349 $sql = $db->bindVars($sql, ':transactionID', $this->pdtData['txn_id'], 'string');350 $ipn_id = $db->Execute($sql);351 if ($ipn_id->RecordCount() != 0) {352 ipn_debug_email('PDT WARNING :: Transaction already exists. Perhaps IPN already added it. PDT processing ended.');353 $pdtTXN_is_unique = false;354 } else {355 $pdtTXN_is_unique = true;356 }357 358 $PDTstatus = ($pdtTXN_is_unique && $PDTstatus);359 360 return $PDTstatus;361 }362 363 364 function tableCheckup() {365 global $db, $sniffer;366 $fieldOkay1 = (method_exists($sniffer, 'field_type')) ? $sniffer->field_type(TABLE_PAYPAL, 'txn_id', 'varchar(20)', true) : -1;367 $fieldOkay2 = ($sniffer->field_exists(TABLE_PAYPAL, 'module_name')) ? true : -1;368 $fieldOkay3 = ($sniffer->field_exists(TABLE_PAYPAL, 'order_id')) ? true : -1;369 370 if ($fieldOkay1 == -1) {371 $sql = "show fields from " . TABLE_PAYPAL;372 $result = $db->Execute($sql);373 while (!$result->EOF) {374 if ($result->fields['Field'] == 'txn_id') {375 if ($result->fields['Type'] == 'varchar(20)') {376 $fieldOkay1 = true; // exists and matches required type, so skip to other checkup377 } else {378 $fieldOkay1 = $result->fields['Type']; // doesn't match, so return what it "is"379 break;380 }381 }382 $result->MoveNext();383 }384 }385 386 if ($fieldOkay1 !== true) {387 // temporary fix to table structure for v1.3.7.x -- may remove in later release388 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE payment_type payment_type varchar(40) NOT NULL default ''");389 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE txn_type txn_type varchar(40) NOT NULL default ''");390 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE payment_status payment_status varchar(32) NOT NULL default ''");391 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE reason_code reason_code varchar(40) default NULL");392 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE pending_reason pending_reason varchar(32) default NULL");393 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE invoice invoice varchar(128) default NULL");394 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE payer_business_name payer_business_name varchar(128) default NULL");395 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE address_name address_name varchar(64) default NULL");396 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE address_street address_street varchar(254) default NULL");397 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE address_city address_city varchar(120) default NULL");398 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE address_state address_state varchar(120) default NULL");399 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE payer_email payer_email varchar(128) NOT NULL default ''");400 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE business business varchar(128) NOT NULL default ''");401 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE receiver_email receiver_email varchar(128) NOT NULL default ''");402 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE txn_id txn_id varchar(20) NOT NULL default ''");403 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE parent_txn_id parent_txn_id varchar(20) default NULL");404 }405 if ($fieldOkay2 !== true) {406 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " ADD COLUMN module_name varchar(40) NOT NULL default '' after txn_type");407 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " ADD COLUMN module_mode varchar(40) NOT NULL default '' after module_name");408 }409 if ($fieldOkay3 !== true) {410 $db->Execute("ALTER TABLE " . TABLE_PAYPAL . " CHANGE zen_order_id order_id int(11) NOT NULL default '0'");411 }412 }413 414 function paynow_button($order_id) {415 global $db, $order, $currencies, $currency;416 require_once(DIR_WS_CLASSES . 'order.php');417 $order = new order($order_id);418 $options = array();419 $optionsCore = array();420 $optionsPhone = array();421 $optionsShip = array();422 $optionsLineItems = array();423 $optionsAggregate = array();424 $optionsTrans = array();425 $buttonArray = array();426 427 $this->totalsum = $order->info['total'];428 429 // save the session stuff permanently in case paypal loses the session430 $_SESSION['ppipn_key_to_remove'] = session_id();431 $db->Execute("delete from " . TABLE_PAYPAL_SESSION . " where session_id = '" . zen_db_input($_SESSION['ppipn_key_to_remove']) . "'");432 433 $sql = "insert into " . TABLE_PAYPAL_SESSION . " (session_id, saved_session, expiry) values (434 '" . zen_db_input($_SESSION['ppipn_key_to_remove']) . "',435 '" . base64_encode(serialize($_SESSION)) . "',436 '" . (time() + (1*60*60*24*2)) . "')";437 438 $db->Execute($sql);439 440 $my_currency = select_pp_currency();441 if(!empty($order->info['currency'])){442 $my_currency=$order->info['currency'];443 }444 $this->transaction_currency = $my_currency;445 446 $this->transaction_amount = ($this->totalsum * $currencies->get_value($my_currency));447 448 $telephone = preg_replace('/\D/', '', $order->customer['telephone']);449 if ($telephone != '') {450 $optionsPhone['H_PhoneNumber'] = $telephone;451 if (in_array($order->customer['country']['iso_code_2'], array('US','CA'))) {452 $optionsPhone['night_phone_a'] = substr($telephone,0,3);453 $optionsPhone['night_phone_b'] = substr($telephone,3,3);454 $optionsPhone['night_phone_c'] = substr($telephone,6,4);455 $optionsPhone['day_phone_a'] = substr($telephone,0,3);456 $optionsPhone['day_phone_b'] = substr($telephone,3,3);457 $optionsPhone['day_phone_c'] = substr($telephone,6,4);458 } else {459 $optionsPhone['night_phone_b'] = $telephone;460 $optionsPhone['day_phone_b'] = $telephone;461 }462 }463 464 $optionsCore = array(465 'lc' => US,466 //'lc' => $order->customer['country']['iso_code_2'],467 'charset' => CHARSET,468 'page_style' => MODULE_PAYMENT_PAYPAL_PAGE_STYLE,469 'custom' => zen_session_name() . '=' . zen_session_id(),470 'invoice' => $order->info['num'],471 'business' => MODULE_PAYMENT_PAYPAL_BUSINESS_ID,472 'return' => zen_href_link(FILENAME_CHECKOUT_PROCESS, 'referer=paypal', 'SSL'),473 'cancel_return' => zen_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL'),474 'shopping_url' => zen_href_link(FILENAME_SHOPPING_CART, '', 'SSL'),475 'notify_url' => zen_href_link('ipn_main_handler.php', '', 'SSL',false,false,true),476 'redirect_cmd' => '_xclick','rm' => 2,'bn' => 'zencart','mrb' => 'R-6C7952342H795591R','pal' => '9E82WJBKKGPLQ',477 );478 $optionsCust = array(479 'first_name' => replace_accents($order->customer['firstname']),480 'last_name' => replace_accents($order->customer['lastname']),481 'address1' => replace_accents($order->customer['street_address']),482 'city' => replace_accents($order->customer['city']),483 'state' => zen_get_zone_code($order->customer['country']['id'], $order->customer['zone_id'], $order->customer['state']),484 'zip' => $order->customer['postcode'],485 'country' => $order->customer['country']['iso_code_2'],486 'email' => $order->customer['email_address'],487 );488 // address line 2 is optional489 if ($order->customer['suburb'] != '') $optionsCust['address2'] = $order->customer['suburb'];490 // different format for Japanese address layout:491 if ($order->customer['country']['iso_code_2'] == 'JP') $optionsCust['zip'] = substr($order->customer['postcode'], 0, 3) . '-' . substr($order->customer['postcode'], 3);492 if (MODULE_PAYMENT_PAYPAL_ADDRESS_REQUIRED == 2) {493 $optionsCust = array(494 'first_name' => replace_accents($order->delivery['firstname'] != '' ? $order->delivery['firstname'] : $order->billing['firstname']),495 'last_name' => replace_accents($order->delivery['lastname'] != '' ? $order->delivery['lastname'] : $order->billing['lastname']),496 'address1' => replace_accents($order->delivery['street_address'] != '' ? $order->delivery['street_address'] : $order->billing['street_address']),497 'city' => replace_accents($order->delivery['city'] != '' ? $order->delivery['city'] : $order->billing['city']),498 'state' => ($order->delivery['country']['id'] != '' ? zen_get_zone_code($order->delivery['country']['id'], $order->delivery['zone_id'], $order->delivery['state']) : zen_get_zone_code($order->billing['country']['id'], $order->billing['zone_id'], $order->billing['state'])),499 'zip' => ($order->delivery['postcode'] != '' ? $order->delivery['postcode'] : $order->billing['postcode']),500 'country' => ($order->delivery['country']['title'] != '' ? $order->delivery['country']['title'] : $order->billing['country']['title']),501 'country_code' => ($order->delivery['country']['iso_code_2'] != '' ? $order->delivery['country']['iso_code_2'] : $order->billing['country']['iso_code_2']),502 'email' => $order->customer['email_address'],503 );504 if ($order->delivery['suburb'] != '') $optionsCust['address2'] = $order->delivery['suburb'];505 if ($order->delivery['country']['iso_code_2'] == 'JP') $optionsCust['zip'] = substr($order->delivery['postcode'], 0, 3) . '-' . substr($order->delivery['postcode'], 3);506 }507 $optionsShip['no_shipping'] = MODULE_PAYMENT_PAYPAL_ADDRESS_REQUIRED;508 if (MODULE_PAYMENT_PAYPAL_ADDRESS_OVERRIDE == '1') $optionsShip['address_override'] = MODULE_PAYMENT_PAYPAL_ADDRESS_OVERRIDE;509 // prepare cart contents details where possible510 if (MODULE_PAYMENT_PAYPAL_DETAILED_CART == 'Yes') $optionsLineItems = ipn_getLineItemDetails();511 if (sizeof($optionsLineItems) > 0) {512 $optionsLineItems['cmd'] = '_cart';513 // $optionsLineItems['num_cart_items'] = sizeof($order->products);514 if (isset($optionsLineItems['shipping'])) {515 $optionsLineItems['shipping_1'] = $optionsLineItems['shipping'];516 unset($optionsLineItems['shipping']);517 }518 unset($optionsLineItems['subtotal']);519 // if line-item details couldn't be kept due to calculation mismatches or discounts etc, default to aggregate mode520 if (!isset($optionsLineItems['item_name_1']) || $optionsLineItems['creditsExist'] == TRUE) $optionsLineItems = array();521 //if ($optionsLineItems['amount'] != $this->transaction_amount) $optionsLineItems = array();522 // debug:523 //ipn_debug_email('Line Item Details (if blank, this means there was a data mismatch or credits applied, and thus bypassed): ' . "\n" . print_r($optionsLineItems, true));524 unset($optionsLineItems['creditsExist']);525 }526 $optionsAggregate = array(527 'cmd' => '_ext-enter',528 'item_name' => MODULE_PAYMENT_PAYPAL_PURCHASE_DESCRIPTION_TITLE,529 'item_number' => MODULE_PAYMENT_PAYPAL_PURCHASE_DESCRIPTION_ITEMNUM,530 //'num_cart_items' => sizeof($order->products),531 'amount' => number_format($this->transaction_amount, $currencies->get_decimal_places($my_currency)),532 'shipping' => '0.00',533 );534 if (MODULE_PAYMENT_PAYPAL_TAX_OVERRIDE == 'true') $optionsAggregate['tax'] = '0.00';535 if (MODULE_PAYMENT_PAYPAL_TAX_OVERRIDE == 'true') $optionsAggregate['tax_cart'] = '0.00';536 $optionsTrans = array(537 'upload' => (int)(sizeof($order->products) > 0),538 'currency_code' => $my_currency,539 //'paypal_order_id' => $paypal_order_id,540 //'no_note' => '1',541 //'invoice' => '',542 );543 544 // if line-item info is invalid, use aggregate:545 if (sizeof($optionsLineItems) > 0) $optionsAggregate = $optionsLineItems;546 547 // prepare submission548 $options = array_merge($optionsCore, $optionsCust, $optionsPhone, $optionsShip, $optionsTrans, $optionsAggregate);549 //ipn_debug_email('Keys for submission: ' . print_r($options, true));550 551 // build the button fields552 foreach ($options as $name => $value) {553 // remove quotation marks554 $value = str_replace('"', '', $value);555 // check for invalid chars556 if (preg_match('/[^a-zA-Z_0-9]/', $name)) {557 ipn_debug_email('datacheck - ABORTING - preg_match found invalid submission key: ' . $name . ' (' . $value . ')');558 break;559 }560 // do we need special handling for & and = symbols?561 //if (strpos($value, '&') !== false || strpos($value, '=') !== false) $value = urlencode($value);562 563 $buttonArray[] = zen_draw_hidden_field($name, $value);564 }565 $process_button_string = implode("\n", $buttonArray) . "\n";566 567 $_SESSION['paypal_transaction_info'] = array($this->transaction_amount, $this->transaction_currency);568 return $process_button_string;569 }570 571 }
3. 在网站后台 Orders Status(地给你单状态)中,增加一项 Unpaid(未付款)选项。然后修改 Order.php 中 create 方法,指定如果生成订单的时候,客户选择的付款方式是 Paypal,那么此订单的状态将会是 Unpaid状态。代码如下:
1 function create($zf_ot_modules, $zf_mode = 2) { 2 global $db; 3 $t1 = date("YmdGhs"); 4 srand ((float) microtime() * 10000000); 5 $input = array ("1", "2", "3", "4", "5", "6", "7", "8", "9", "0"); 6 $rand_keys = array_rand ($input, 2); 7 $l1 = $input[$rand_keys[0]]; 8 $l2 = $input[$rand_keys[1]]; 9 $r1 = rand(0,9); 10 $ordernum = $t1.$l1.$l2.$r1; 11 12 if ($this->info['total'] == 0) {13 if (DEFAULT_ZERO_BALANCE_ORDERS_STATUS_ID == 0) {14 $this->info['order_status'] = DEFAULT_ORDERS_STATUS_ID;15 } else {16 if ($_SESSION['payment'] != 'freecharger') {17 $this->info['order_status'] = DEFAULT_ZERO_BALANCE_ORDERS_STATUS_ID;18 }19 }20 }21 //在这个位置增加下面的代码,5是后台添加的Unpaid状态的ID号,不尽相同,注意查看。22 if($_SESSION['payment'] == 'paypal'){23 $this->info['order_status'] = 5;24 }
4. 如果是通过Paypal付款后,从Paypal返回网站时,会使用GET方式带入一些数据到 includes/modules/pages/checkout_process/header_php.php 这个页面,而直接生成订单时,并不会有GET数据传输,所以通过 $_GET['referer'] 这条返回值数据,来判断是生成订单,还是付款归来。如果只是生成订单的话,跳转到 tpl_account_history_info_default 页面,如果是付款归来,则跳转到 checkout_success 页面,这样就避免了重复生成订单了。代码如下:
1 $zco_notifier->notify('NOTIFY_HEADER_START_CHECKOUT_PROCESS'); 2 3 if(isset($_GET['referer']) && $_GET['referer'] == 'paypal'){ 4 //如果是来自paypal的付款,就直接跳转到付款成功页面 5 zen_redirect(zen_href_link(FILENAME_CHECKOUT_SUCCESS, (isset($_GET['action']) && $_GET['action'] == 'confirm' ? 'action=confirm' : ''), 'SSL')); 6 } 7 else{ 8 require(DIR_WS_MODULES . zen_get_module_directory('checkout_process.php')); 9 10 // load the after_process function from the payment modules11 $payment_modules->after_process();12 13 $_SESSION['cart']->reset(true);14 15 // unregister session variables used during checkout16 unset($_SESSION['sendto']);17 unset($_SESSION['billto']);18 unset($_SESSION['shipping']);19 unset($_SESSION['payment']);20 unset($_SESSION['comments']);21 $order_total_modules->clear_posts();//ICW ADDED FOR CREDIT CLASS SYSTEM22 23 // This should be before the zen_redirect:24 $zco_notifier->notify('NOTIFY_HEADER_END_CHECKOUT_PROCESS');25 26 zen_redirect(zen_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id='.$insert_id, 'SSL'));27 }28 29 require(DIR_WS_INCLUDES . 'application_bottom.php');
5. 在 tpl_account_history_info_default 页面中显示pay now按钮。打开文件"includes/modules/pages/account_history_info/header.php",在文件的末尾添加下 面的代码:
1 require(DIR_WS_CLASSES . 'order.php');2 $order = new order($_GET['order_id']);3 4 //在这个位置插入下面两行代码5 require_once(DIR_WS_CLASSES . 'payment.php');6 $payment_modules = new payment($order->info['payment_module_code']);
6. 打开文件"includes/templates/template_default/templates /tpl_account_history_info_default.php",并在适当的位置加上如下的代码,这里对订单的状态进行了一个判断,当只有订单的 状态在未付款状态,才显示该按钮。代码如下:
1 <?php 2 //Unpaid是你在后台添加的为付款订单状态 3 if(isset($payment_modules->paynow_action_url) && $payment_modules->paynow_action_url != '' && $order->info['orders_status'] == 'Unpaid'){ 4 echo '<div class="back"><strong>Order has been generated</strong> - please continue to pay</div>'; 5 echo zen_draw_form('checkout_paynow', $payment_modules->paynow_action_url, 'post', 'id="checkout_confirmation" onsubmit="submitonce();" class="right"'); 6 echo('<div>'); 7 if (is_array($payment_modules->modules)) { 8 echo $payment_modules->paynow_button($_GET['order_id']); 9 }10 echo zen_image_submit("button_buy_now.gif", "Pay now this order","name='submit'");11 //echo '<input type="image" src="https://www.sandbox.paypal.com/en_US/i/btn/btn_buynow_LG.gif" border="0" name="submit" alt="PayPal——最安全便捷的在线支付方式!">';12 echo ('</div>');13 echo ('</form>');14 }15 ?>
7. 修改 tpl_account_history_default.php 页面,判断是否为未付款订单,如果是,则增加一个 pay_now 按钮,然后跳转到 tpl_account_history_info_default.php 页面进行付款,其实跟 view 按钮是一样的,只不过换了一个名称,标明是未付款订单而已。
8. 最关键的地方来了,就是 ipn_main_handler.php 这个文件。Paypal 付款接口返回数据方式有两种,一种是PDT,一种是IPN,PDT是同步传输,付款数据会立即返回到网站,并且是一次性的。IPN则是异步传输,而且如果网站没有收到数据,IPN还会再次循环的发送付款信息到你的网站 ipn_main_handler.php 文件进行处理并写入数据库。最终我们在客户订单中,就能看到客户的Paypal付款信息,如下图:
之前的付款流程中,Paypal 付款数据是通过 PDT 方式传输,修改了付款流程之后,我们不能通过 PDT 方式,只能通过 IPN 方式传输。ipn_main_handler.php 文件就是处理 IPN 数据传输方式的文件。不过,当 ipn_main_handler.php 接收到 Paypal 付款数据后,会根据 Paypal 付款数据生成一个订单,但是我们已经有了订单,只需要把 Paypal 付款信息写入到数据库中,与订单对应即可。所以我们需要修改 ipn_main_handler.php 文件。PDT和IPN详细介绍链接:http://wenku.baidu.com/link?url=xI4DZL8mg9R54aJKfn3zNyP9_yFHkHVvxWltEuAZ9-DXXAS3K3z-z6srRlh_P-EmMXYU-U6oQ_uEwNze7An9PBAUgnPMH-b_iF3d2z7LE_G
首先,我们要确定,通过 IPN 方式返回的 Paypal 付款信息是属于哪个订单的,我在 paypal.php 文件中第 470 行增加了 'invoice' => $order->info['id'],作用就是在付款的时候,把这个信息发送给Paypal,付款成功后,Paypal也会通过IPN返回这条信息到 ipn_main_handler.php。根据这个判断,如果接收到了 invoice 数据,则跳过生成订单的步骤,只写入Paypal付款信息即可。代码如下:
1 <?php 2 /** 3 * ipn_main_handler.php callback handler for PayPal IPN notifications 4 * 5 * @package paymentMethod 6 * @copyright Copyright 2003-2010 Zen Cart Development Team 7 * @copyright Portions Copyright 2003 osCommerce 8 * @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0 9 * @version $Id: ipn_main_handler.php 18014 2010-10-22 03:39:17Z drbyte $ 10 */ 11 if (!defined('TEXT_RESELECT_SHIPPING')) define('TEXT_RESELECT_SHIPPING', 'You have changed the items in your cart since shipping was last calculated, and costs may have changed. Please verify/re-select your shipping method.'); 12 13 /** 14 * handle Express Checkout processing: 15 */ 16 if (isset($_GET['type']) && $_GET['type'] == 'ec') { 17 // this is an EC handler request 18 require('includes/application_top.php'); 19 20 // Validate Cart for checkout 21 $_SESSION['valid_to_checkout'] = true; 22 $_SESSION['cart']->get_products(true); 23 if ($_SESSION['valid_to_checkout'] == false || $_SESSION['cart']->count_contents() <= 0) { 24 $messageStack->add_session('shopping_cart', ERROR_CART_UPDATE, 'error'); 25 zen_redirect(zen_href_link(FILENAME_SHOPPING_CART)); 26 } 27 28 // Stock Check to prevent checkout if cart contents rules violations exist 29 if ( STOCK_CHECK == 'true' && STOCK_ALLOW_CHECKOUT != 'true' && isset($_SESSION['cart']) ) { 30 $products = $_SESSION['cart']->get_products(); 31 for ($i=0, $n=sizeof($products); $i<$n; $i++) { 32 if (zen_check_stock($products[$i]['id'], $products[$i]['quantity'])) { 33 zen_redirect(zen_href_link(FILENAME_SHOPPING_CART)); 34 break; 35 } 36 } 37 } 38 // if cart contents has changed since last pass, reset 39 if (isset($_SESSION['cart']->cartID)) { 40 if (isset($_SESSION['cartID'])) { // This will only be set if customer has been to the checkout_shipping page. Will *not* be set if starting via EC Shortcut button, so don't want to redirect in that case. 41 if ($_SESSION['cart']->cartID != $_SESSION['cartID']) { 42 if (isset($_SESSION['shipping'])) { 43 unset($_SESSION['shipping']); 44 $messageStack->add_session('checkout_shipping', TEXT_RESELECT_SHIPPING, 'error'); 45 zen_redirect(zen_href_link(FILENAME_CHECKOUT_SHIPPING, '', 'SSL')); 46 } 47 } 48 } 49 // } else { 50 // zen_redirect(zen_href_link(FILENAME_TIME_OUT)); 51 } 52 53 require(DIR_WS_CLASSES . 'payment.php'); 54 // See if we were sent a request to clear the session for PayPal. 55 if (isset($_GET['clearSess']) || isset($_GET['amp;clearSess']) || isset($_GET['ec_cancel']) || isset($_GET['amp;ec_cancel'])) { 56 // Unset the PayPal EC information. 57 unset($_SESSION['paypal_ec_temp']); 58 unset($_SESSION['paypal_ec_token']); 59 unset($_SESSION['paypal_ec_payer_id']); 60 unset($_SESSION['paypal_ec_payer_info']); 61 } 62 // See if the paypalwpp module is enabled. 63 if (defined('MODULE_PAYMENT_PAYPALWPP_STATUS') && MODULE_PAYMENT_PAYPALWPP_STATUS == 'True') { 64 $paypalwpp_module = 'paypalwpp'; 65 // init the payment object 66 $payment_modules = new payment($paypalwpp_module); 67 // set the payment, if they're hitting us here then we know 68 // the payment method selected right now. 69 $_SESSION['payment'] = $paypalwpp_module; 70 // check to see if we have a token sent back from PayPal. 71 if (!isset($_SESSION['paypal_ec_token']) || empty($_SESSION['paypal_ec_token'])) { 72 // We have not gone to PayPal's website yet in order to grab 73 // a token at this time. This will send the customer over to PayPal's 74 // website to login and return a token 75 $$paypalwpp_module->ec_step1(); 76 } else { 77 // This will push on the second step of the paypal ec payment 78 // module, as we already have a PayPal express checkout token 79 // at this point. 80 $$paypalwpp_module->ec_step2(); 81 } 82 } 83 ?> 84 <html> 85 Processing... 86 </html> 87 <?php 88 89 /** 90 * If we got here, we are an IPN transaction (not Express Checkout): 91 */ 92 93 } else { 94 /** 95 * detect odd cases of extra-url-encoded POST data coming back from PayPal 96 */ 97 foreach(array('receiver_email', 'payer_email', 'business', 'txn_type', 'transaction_subject', 'custom', 'payment_date', 'item_number', 'item_name', 'first_name', 'last_name') as $key) { 98 if (isset($_POST[$key]) && strstr($_POST[$key], '%')) { 99 $_POST[$key] = urldecode($_POST[$key]);100 }101 }102 /**103 * detect type of transaction104 */105 $isECtransaction = ((isset($_POST['txn_type']) && $_POST['txn_type']=='express_checkout') || (isset($_POST['custom']) && in_array(substr($_POST['custom'], 0, 3), array('EC-', 'DP-', 'WPP')))); /*|| $_POST['txn_type']=='cart'*/106 $isDPtransaction = (isset($_POST['custom']) && in_array(substr($_POST['custom'], 0, 3), array('DP-', 'WPP')));107 /**108 * set paypal-specific application_top parameters109 */110 $current_page_base = 'paypalipn';111 $loaderPrefix = 'paypal_ipn';112 $show_all_errors = FALSE;113 require('includes/application_top.php');114 115 $extraDebug = (defined('IPN_EXTRA_DEBUG_DETAILS') && IPN_EXTRA_DEBUG_DETAILS == 'All');116 117 if ( (defined('MODULE_PAYMENT_PAYPALWPP_DEBUGGING') && strstr(MODULE_PAYMENT_PAYPALWPP_DEBUGGING, 'Log')) ||118 (defined('MODULE_PAYMENT_PAYPAL_IPN_DEBUG') && strstr(MODULE_PAYMENT_PAYPAL_IPN_DEBUG, 'Log')) ||119 ($_REQUEST['ppdebug'] == 'on' && strstr(EXCLUDE_ADMIN_IP_FOR_MAINTENANCE, $_SERVER['REMOTE_ADDR'])) || $extraDebug ) {120 $show_all_errors = true;121 $debug_logfile_path = ipn_debug_email('Breakpoint: 0 - Initializing debugging.');122 if ($debug_logfile_path == '') $debug_logfile_path = 'includes/modules/payment/paypal/logs/ipn_debug_php_errors-'.time().'.log';123 @ini_set('log_errors', 1);124 @ini_set('log_errors_max_len', 0);125 @ini_set('display_errors', 0); // do not output errors to screen/browser/client (only to log file)126 @ini_set('error_log', DIR_FS_CATALOG . $debug_logfile_path);127 error_reporting(version_compare(PHP_VERSION, 5.3, '>=') ? E_ALL & ~E_DEPRECATED & ~E_NOTICE : version_compare(PHP_VERSION, 6.0, '>=') ? E_ALL & ~E_DEPRECATED & ~E_NOTICE & ~E_STRICT : E_ALL & ~E_NOTICE);128 }129 130 ipn_debug_email('Breakpoint: Flag Status:' . "\nisECtransaction = " . (int)$isECtransaction . "\nisDPtransaction = " . (int)$isDPtransaction);131 /**132 * do confirmation post-back to PayPal and extract the results for subsequent use133 */134 $info = ipn_postback();135 $new_status = 1;136 ipn_debug_email('Breakpoint: 1 - Collected data from PayPal notification');137 138 /**139 * validate transaction -- email address, matching txn record, etc140 */141 if (!ipn_validate_transaction($info, $_POST, 'IPN') === true) {142 if (!$isECtransaction && $_POST['txn_type'] != '') {143 ipn_debug_email('IPN FATAL ERROR :: Transaction did not validate. ABORTED.');144 die();145 }146 }147 148 if ($isDPtransaction) {149 ipn_debug_email('IPN NOTICE :: This is a Website Payments Pro transaction. The rest of this log file is INFORMATION ONLY, and is not used for real processing.');150 }151 152 ipn_debug_email('Breakpoint: 2 - Validated transaction components');153 if ($_POST ['exchange_rate'] == '') $_POST [exchange_rate] = 1;154 if ($_POST ['num_cart_items'] == '') $_POST [num_cart_items] = 1;155 if ($_POST ['settle_amount'] == '') $_POST [settle_amount] = 0;156 157 /**158 * is this a sandbox transaction?159 */160 if (isset($_POST['test_ipn']) && $_POST['test_ipn'] == 1) {161 ipn_debug_email('IPN NOTICE :: Processing SANDBOX transaction.');162 }163 if (isset($_POST['test_internal']) && $_POST['test_internal'] == 1) {164 ipn_debug_email('IPN NOTICE :: Processing INTERNAL TESTING transaction.');165 }166 if (isset($_POST['pending_reason']) && $_POST['pending_reason'] == 'unilateral') {167 ipn_debug_email('*** NOTE: TRANSACTION IS IN *unilateral* STATUS, pending creation of a PayPal account for this receiver_email address.' . "\n" . 'Please create the account, or make sure the PayPal account is *Verified*.');168 }169 170 ipn_debug_email('Breakpoint: 3 - Communication method verified');171 /**172 * Lookup transaction history information in preparation for matching and relevant updates173 */174 $lookupData = ipn_lookup_transaction($_POST);175 $ordersID = $lookupData['order_id'];176 $paypalipnID = $lookupData['paypal_ipn_id'];177 $txn_type = $lookupData['txn_type'];178 $parentLookup = $txn_type;179 180 ipn_debug_email('Breakpoint: 4 - ' . 'Details: txn_type=' . $txn_type . ' ordersID = '. $ordersID . ' IPN_id=' . $paypalipnID . "\n\n" . ' Relevant data from POST:' . "\n " . 'txn_type = ' . $txn_type . "\n " . 'parent_txn_id = ' . ($_POST['parent_txn_id'] =='' ? 'None' : $_POST['parent_txn_id']) . "\n " . 'txn_id = ' . $_POST['txn_id']);181 182 if (!$isECtransaction && !isset($_POST['parent_txn_id']) && $txn_type != 'cleared-echeck') {183 if (defined('MODULE_PAYMENT_PAYPAL_PDTTOKEN') && MODULE_PAYMENT_PAYPAL_PDTTOKEN != '') {184 ipn_debug_email('IPN NOTICE :: IPN pausing: waiting for PDT to process. Sleeping 10 seconds ...');185 sleep(10);186 }187 if (ipn_get_stored_session($session_stuff) === false) {188 ipn_debug_email('IPN ERROR :: No pending Website Payments Standard session data available. Might be a duplicate transaction already entered via PDT.');189 $ipnFoundSession = false;190 }191 }192 193 if ($ipnFoundSession == FALSE && !$isECtransaction && !$isDPtransaction && $txn_type != 'cleared-echeck') {194 ipn_debug_email('NOTICE: IPN Processing Aborted due to missing matching transaction data, as per earlier debug message. Perhaps this transaction was already entered via PDT? Thus there is no need to process this incoming IPN notification.');195 die();196 }197 198 // this is used to determine whether a record needs insertion. ie: original echeck notice failed, but now we have cleared, so need parent record established:199 $new_record_needed = ($txn_type == 'unique' ? true : false);200 /**201 * evaluate what type of transaction we're processing202 */203 $txn_type = ipn_determine_txn_type($_POST, $txn_type);204 ipn_debug_email('Breakpoint: 5 - Transaction type (txn_type) = ' . $txn_type . ' [parentLookup='.$parentLookup.']');205 206 if ($_POST['payment_type'] == 'instant' && $isDPtransaction && ((isset($_POST['auth_status']) && $_POST['auth_status'] == 'Completed') || $_POST['payment_status'] == 'Completed')) {207 ipn_debug_email('IPN NOTICE :: DP/Website Payments Pro notice -- IPN Ignored');208 die();209 }210 211 /**212 * take action based on transaction type and corresponding requirements213 */214 switch ($txn_type) {215 case ($_POST['txn_type'] == 'send_money'):216 case ($_POST['txn_type'] == 'merch_payment'):217 case ($_POST['txn_type'] == 'new_case'):218 case ($_POST['txn_type'] == 'masspay'):219 // these types are irrelevant to ZC transactions220 ipn_debug_email('IPN NOTICE :: Transaction txn_type not relevant to Zen Cart processing. IPN handler aborted.' . $_POST['txn_type']);221 die();222 break;223 case (substr($_POST['txn_type'],0,7) == 'subscr_'):224 // For now we filter out subscription payments225 ipn_debug_email('IPN NOTICE :: Subscription payment - Not currently supported by Zen Cart. IPN handler aborted.');226 die();227 break;228 229 case 'pending-unilateral':230 // cannot process this order because the merchant's PayPal account isn't valid yet231 ipn_debug_email('IPN NOTICE :: Please create a valid PayPal account and follow the steps to *Verify* it. IPN handler aborted.');232 die();233 break;234 case 'pending-address':235 case 'pending-intl':236 case 'pending-multicurrency':237 case 'pending-verify':238 if (!$isECtransaction) {239 ipn_debug_email('IPN NOTICE :: '.$txn_type.' transaction -- inserting initial record for reference purposes');240 $sql_data_array = ipn_create_order_array($ordersID, $txn_type);241 zen_db_perform(TABLE_PAYPAL, $sql_data_array);242 $sql_data_array = ipn_create_order_history_array($paypalipnID);243 zen_db_perform(TABLE_PAYPAL_PAYMENT_STATUS_HISTORY, $sql_data_array);244 die();245 break;246 }247 case (($txn_type == 'express_checkout' || $isECtransaction) && !strstr($txn_type, 'cleared') && $parentLookup != 'parent'):248 if ($_POST['payment_status'] == 'Completed') {249 // This is an express-checkout transaction -- IPN may not be needed250 if (isset($_POST['auth_status']) && $_POST['auth_status'] == 'Completed') {251 ipn_debug_email('IPN NOTICE :: Express Checkout payment notice on completed order -- IPN Ignored');252 die();253 }254 }255 if ($_POST['payment_type'] == 'instant' && isset($_POST['auth_status']) && $_POST['auth_status'] == 'Pending') {256 ipn_debug_email('IPN NOTICE :: EC/DP notice on pre-auth order -- IPN Ignored');257 die();258 }259 ipn_debug_email('Breakpoint: 5 - midstream checkpoint');260 if (!(substr($txn_type,0,8) == 'pending-' && (int)$ordersID <= 0) && !($new_record_needed && $txn_type == 'echeck-cleared') && $txn_type != 'unique' && $txn_type != 'echeck-denied' && $txn_type != 'voided') {261 ipn_debug_email('Breakpoint: 5 - Record does not need to be processed since it is not new and is not an update. See earlier notices. Processing aborted.');262 break;263 }264 265 case ($txn_type == 'cart'):266 ipn_debug_email('IPN NOTICE :: This is a detailed-cart transaction');267 268 case ($txn_type == 'cart' && !$isECtransaction):269 ipn_debug_email('IPN NOTICE :: This is a detailed-cart transaction (i)');270 271 case (substr($txn_type,0,8) == 'pending-' && (int)$ordersID <= 0):272 case ($new_record_needed && $txn_type == 'echeck-cleared'):273 case 'unique':274 /**275 * delete IPN session from PayPal table -- housekeeping276 */277 $db->Execute("delete from " . TABLE_PAYPAL_SESSION . " where session_id = '" . zen_db_input(str_replace('zenid=', '', $_POST['custom'])) . "'");278 /**279 * require shipping class280 */281 require(DIR_WS_CLASSES . 'shipping.php');282 /**283 * require payment class284 */285 require(DIR_WS_CLASSES . 'payment.php');286 $payment_modules = new payment($_SESSION['payment']);287 $shipping_modules = new shipping($_SESSION['shipping']);288 /**289 * require order class290 */291 //这里判断是否获取到了invoice信息,如果获取到,则提取此订单的信息。292 require(DIR_WS_CLASSES . 'order.php');293 if(isset($_POST['invoice']) && $_POST['invoice'] != ''){294 $order = new order($_POST['invoice']);295 }else{296 $order = new order();297 }298 /**299 * require order_total class300 */301 require(DIR_WS_CLASSES . 'order_total.php');302 $order_total_modules = new order_total();303 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_BEFORE_ORDER_TOTALS_PROCESS');304 $order_totals = $order_total_modules->process();305 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_TOTALS_PROCESS');306 307 if (valid_payment($order->info['total'], $_SESSION['currency']) === false && !$isECtransaction && !$isDPtransaction) {308 ipn_debug_email('IPN NOTICE :: Failed because of currency mismatch.');309 //需要注意此处,这里的付款货币匹配检查,因为在发送付款数据到paypal时,我们就根据顾客的订单货币方式做出了设定。310 //并且客户更改当前默认货币也不能改变以生成的订单的货币种类,所以这里的判断可以取消,不然死在这里。311 //die();312 }313 if ($ipnFoundSession === false && !$isECtransaction && !$isDPtransaction) {314 ipn_debug_email('IPN NOTICE :: Unique but no session - Assumed to be a personal payment, rather than a new Website Payments Standard transaction. Ignoring.');315 die();316 }317 if (!strstr($txn_type, 'denied') && !strstr($txn_type, 'failed') && !strstr($txn_type, 'voided')) {318 //这里判断,如果获取到了invoice,则跳过生产订单的步骤,之写入Paypal付款信息。319 if(isset($_POST['invoice']) && $_POST['invoice'] != ''){320 $insert_id = $_POST['invoice'];321 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_CREATE');322 ipn_debug_email('Breakpoint: 5a - built order -- OID: ' . $insert_id);323 $sql_data_array = ipn_create_order_array($insert_id, $txn_type);324 ipn_debug_email('Breakpoint: 5b - PP table OID: ' . print_r($sql_data_array, true));325 zen_db_perform(TABLE_PAYPAL, $sql_data_array);326 ipn_debug_email('Breakpoint: 5c - PP table OID saved');327 $pp_hist_id = $db->Insert_ID();328 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_AFTER_PAYMENT_MODULES_AFTER_ORDER_CREATE');329 ipn_debug_email('Breakpoint: 5d - PP hist ID: ' . $pp_hist_id);330 $sql_data_array = ipn_create_order_history_array($pp_hist_id);331 ipn_debug_email('Breakpoint: 5e - PP hist_data:' . print_r($sql_data_array, true));332 zen_db_perform(TABLE_PAYPAL_PAYMENT_STATUS_HISTORY, $sql_data_array);333 ipn_debug_email('Breakpoint: 5f - PP hist saved');334 $new_status = MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID;335 ipn_debug_email('Breakpoint: 5g - new status code: ' . $new_status);336 if ($_POST['payment_status'] =='Pending') {337 $new_status = (defined('MODULE_PAYMENT_PAYPAL_PROCESSING_STATUS_ID') && (int)MODULE_PAYMENT_PAYPAL_PROCESSING_STATUS_ID > 0 ? (int)MODULE_PAYMENT_PAYPAL_PROCESSING_STATUS_ID : 2);338 ipn_debug_email('Breakpoint: 5h - newer status code: ' . (int)$new_status);339 $sql = "UPDATE " . TABLE_ORDERS . "340 SET orders_status = " . (int)$new_status . "341 WHERE orders_id = '" . (int)$insert_id . "'";342 $db->Execute($sql);343 ipn_debug_email('Breakpoint: 5i - order table updated');344 }345 $sql_data_array = array('orders_id' => (int)$insert_id,346 'orders_status_id' => (int)$new_status,347 'date_added' => 'now()',348 'comments' => 'PayPal status: ' . $_POST['payment_status'] . ' ' . $_POST['pending_reason']. ' @ '.$_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'],349 'customer_notified' => 0350 );351 if ($_POST['payment_status'] =='Completed') {352 $new_status = (defined('MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID') && (int)MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID > 0 ? (int)MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID : 2);353 ipn_debug_email('Breakpoint: 5h_1 - newer status code: ' . (int)$new_status);354 $sql = "UPDATE " . TABLE_ORDERS . "355 SET orders_status = " . (int)$new_status . "356 WHERE orders_id = '" . (int)$insert_id . "'";357 $db->Execute($sql);358 ipn_debug_email('Breakpoint: 5i_1 - order table updated');359 }360 $sql_data_array = array('orders_id' => (int)$insert_id,361 'orders_status_id' => (int)$new_status,362 'date_added' => 'now()',363 'comments' => 'PayPal status: ' . $_POST['payment_status'] . ' ' . $_POST['pending_reason']. ' @ '.$_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'],364 'customer_notified' => 0365 );366 ipn_debug_email('Breakpoint: 5j - order stat hist update:' . print_r($sql_data_array, true));367 zen_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);368 if (MODULE_PAYMENT_PAYPAL_ADDRESS_OVERRIDE == '1') {369 $sql_data_array['comments'] = '**** ADDRESS OVERRIDE ALERT!!! **** CHECK PAYPAL ORDER DETAILS FOR ACTUAL ADDRESS SELECTED BY CUSTOMER!!';370 $sql_data_array['customer_notified'] = -1;371 }372 zen_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);373 ipn_debug_email('Breakpoint: 5k - OSH update done');374 //$order->create_add_products($insert_id, 2);375 ipn_debug_email('Breakpoint: 5L - adding products');376 $_SESSION['order_number_created'] = $insert_id;377 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_CREATE_ADD_PRODUCTS');378 $order->send_order_email($insert_id, 2);379 ipn_debug_email('Breakpoint: 5m - emailing customer');380 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_AFTER_SEND_ORDER_EMAIL');381 /** Prepare sales-tracking data for use by notifier class **/382 $ototal = $order_subtotal = $credits_applied = 0;383 for ($i=0, $n=sizeof($order_totals); $i<$n; $i++) {384 if ($order_totals[$i]['code'] == 'ot_subtotal') $order_subtotal = $order_totals[$i]['value'];385 if ($$order_totals[$i]['code']->credit_class == true) $credits_applied += $order_totals[$i]['value'];386 if ($order_totals[$i]['code'] == 'ot_total') $ototal = $order_totals[$i]['value'];387 }388 $commissionable_order = ($order_subtotal - $credits_applied);389 $commissionable_order_formatted = $currencies->format($commissionable_order);390 $_SESSION['order_summary']['order_number'] = $insert_id;391 $_SESSION['order_summary']['order_subtotal'] = $order_subtotal;392 $_SESSION['order_summary']['credits_applied'] = $credits_applied;393 $_SESSION['order_summary']['order_total'] = $ototal;394 $_SESSION['order_summary']['commissionable_order'] = $commissionable_order;395 $_SESSION['order_summary']['commissionable_order_formatted'] = $commissionable_order_formatted;396 $_SESSION['order_summary']['coupon_code'] = $order->info['coupon_code'];397 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_HANDLE_AFFILIATES', 'paypalipn');398 $_SESSION['cart']->reset(true);399 ipn_debug_email('Breakpoint: 5n - emptying cart');400 $ordersID = $insert_id;401 $paypalipnID = $pp_hist_id;402 ipn_debug_email('Breakpoint: 6 - Completed IPN order add.' . ' ordersID = '. $ordersID . ' IPN tracking record = ' . $paypalipnID);403 if (!($new_record_needed && $txn_type == 'echeck-cleared')) break;404 }else{405 $insert_id = $order->create($order_totals);406 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_CREATE');407 ipn_debug_email('Breakpoint: 5a - built order -- OID: ' . $insert_id);408 $sql_data_array = ipn_create_order_array($insert_id, $txn_type);409 ipn_debug_email('Breakpoint: 5b - PP table OID: ' . print_r($sql_data_array, true));410 zen_db_perform(TABLE_PAYPAL, $sql_data_array);411 ipn_debug_email('Breakpoint: 5c - PP table OID saved');412 $pp_hist_id = $db->Insert_ID();413 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_AFTER_PAYMENT_MODULES_AFTER_ORDER_CREATE');414 ipn_debug_email('Breakpoint: 5d - PP hist ID: ' . $pp_hist_id);415 $sql_data_array = ipn_create_order_history_array($pp_hist_id);416 ipn_debug_email('Breakpoint: 5e - PP hist_data:' . print_r($sql_data_array, true));417 zen_db_perform(TABLE_PAYPAL_PAYMENT_STATUS_HISTORY, $sql_data_array);418 ipn_debug_email('Breakpoint: 5f - PP hist saved');419 $new_status = MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID;420 ipn_debug_email('Breakpoint: 5g - new status code: ' . $new_status);421 if ($_POST['payment_status'] =='Pending') {422 $new_status = (defined('MODULE_PAYMENT_PAYPAL_PROCESSING_STATUS_ID') && (int)MODULE_PAYMENT_PAYPAL_PROCESSING_STATUS_ID > 0 ? (int)MODULE_PAYMENT_PAYPAL_PROCESSING_STATUS_ID : 2);423 ipn_debug_email('Breakpoint: 5h - newer status code: ' . (int)$new_status);424 $sql = "UPDATE " . TABLE_ORDERS . "425 SET orders_status = " . (int)$new_status . "426 WHERE orders_id = '" . (int)$insert_id . "'";427 $db->Execute($sql);428 ipn_debug_email('Breakpoint: 5i - order table updated');429 }430 $sql_data_array = array('orders_id' => (int)$insert_id,431 'orders_status_id' => (int)$new_status,432 'date_added' => 'now()',433 'comments' => 'PayPal status: ' . $_POST['payment_status'] . ' ' . $_POST['pending_reason']. ' @ '.$_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'],434 'customer_notified' => 0435 );436 ipn_debug_email('Breakpoint: 5j - order stat hist update:' . print_r($sql_data_array, true));437 zen_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);438 if (MODULE_PAYMENT_PAYPAL_ADDRESS_OVERRIDE == '1') {439 $sql_data_array['comments'] = '**** ADDRESS OVERRIDE ALERT!!! **** CHECK PAYPAL ORDER DETAILS FOR ACTUAL ADDRESS SELECTED BY CUSTOMER!!';440 $sql_data_array['customer_notified'] = -1;441 }442 zen_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);443 ipn_debug_email('Breakpoint: 5k - OSH update done');444 $order->create_add_products($insert_id, 2);445 ipn_debug_email('Breakpoint: 5L - adding products');446 $_SESSION['order_number_created'] = $insert_id;447 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_CREATE_ADD_PRODUCTS');448 $order->send_order_email($insert_id, 2);449 ipn_debug_email('Breakpoint: 5m - emailing customer');450 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_AFTER_SEND_ORDER_EMAIL');451 /** Prepare sales-tracking data for use by notifier class **/452 $ototal = $order_subtotal = $credits_applied = 0;453 for ($i=0, $n=sizeof($order_totals); $i<$n; $i++) {454 if ($order_totals[$i]['code'] == 'ot_subtotal') $order_subtotal = $order_totals[$i]['value'];455 if ($$order_totals[$i]['code']->credit_class == true) $credits_applied += $order_totals[$i]['value'];456 if ($order_totals[$i]['code'] == 'ot_total') $ototal = $order_totals[$i]['value'];457 }458 $commissionable_order = ($order_subtotal - $credits_applied);459 $commissionable_order_formatted = $currencies->format($commissionable_order);460 $_SESSION['order_summary']['order_number'] = $insert_id;461 $_SESSION['order_summary']['order_subtotal'] = $order_subtotal;462 $_SESSION['order_summary']['credits_applied'] = $credits_applied;463 $_SESSION['order_summary']['order_total'] = $ototal;464 $_SESSION['order_summary']['commissionable_order'] = $commissionable_order;465 $_SESSION['order_summary']['commissionable_order_formatted'] = $commissionable_order_formatted;466 $_SESSION['order_summary']['coupon_code'] = $order->info['coupon_code'];467 $zco_notifier->notify('NOTIFY_CHECKOUT_PROCESS_HANDLE_AFFILIATES', 'paypalipn');468 $_SESSION['cart']->reset(true);469 ipn_debug_email('Breakpoint: 5n - emptying cart');470 $ordersID = $insert_id;471 $paypalipnID = $pp_hist_id;472 ipn_debug_email('Breakpoint: 6 - Completed IPN order add.' . ' ordersID = '. $ordersID . ' IPN tracking record = ' . $paypalipnID);473 if (!($new_record_needed && $txn_type == 'echeck-cleared')) break;474 }475 }476 case 'parent':477 case 'cleared-address':478 case 'cleared-multicurrency':479 case 'cleared-echeck':480 case 'cleared-authorization':481 case 'cleared-verify':482 case 'cleared-intl':483 case 'cleared-review':484 case 'echeck-denied':485 case 'echeck-cleared':486 case 'denied-address':487 case 'denied-multicurrency':488 case 'denied-echeck':489 case 'failed-echeck':490 case 'denied-intl':491 case 'denied':492 case 'voided':493 case 'express-checkout-cleared':494 ipn_debug_email('IPN NOTICE :: Storing order/update details for order #' . $ordersID . ' txn_id: ' . $_POST['txn_id'] . ' PP IPN ID: ' . $paypalipnID);495 if ($txn_type == 'parent') {496 $sql_data_array = ipn_create_order_array($ordersID, $txn_type);497 zen_db_perform(TABLE_PAYPAL, $sql_data_array);498 $paypalipnID = $db->Insert_ID();499 } else {500 $sql_data_array = ipn_create_order_update_array($txn_type);501 zen_db_perform(TABLE_PAYPAL, $sql_data_array, 'update', "txn_id='" . ($txn_type == 'cleared-authorization' ? $_POST['parent_txn_id'] : $_POST['txn_id']) . "'");502 $sql = "select paypal_ipn_id from " . TABLE_PAYPAL . " where txn_id='" . $_POST['txn_id'] . "'";503 $result = $db->Execute($sql);504 $paypalipnID = $result->fields['paypal_ipn_id'];505 }506 $sql_data_array = ipn_create_order_history_array($paypalipnID);507 zen_db_perform(TABLE_PAYPAL_PAYMENT_STATUS_HISTORY, $sql_data_array);508 ipn_debug_email('IPN NOTICE :: Added PP status-history record for order #' . $ordersID . ' txn_id: ' . $_POST['txn_id'] . ' (updated/child) PP IPN ID: ' . $paypalipnID);509 510 switch ($txn_type) {511 case 'voided':512 case ($_POST['payment_status'] == 'Refunded' || $_POST['payment_status'] == 'Reversed' || $_POST['payment_status'] == 'Voided'):513 //payment_status=Refunded or payment_status=Voided514 $new_status = MODULE_PAYMENT_PAYPALWPP_REFUNDED_STATUS_ID;515 if (defined('MODULE_PAYMENT_PAYPAL_REFUND_ORDER_STATUS_ID') && (int)MODULE_PAYMENT_PAYPAL_REFUND_ORDER_STATUS_ID > 0 && !$isECtransaction) $new_status = MODULE_PAYMENT_PAYPAL_REFUND_ORDER_STATUS_ID;516 break;517 case 'echeck-denied':518 case 'denied-echeck':519 case 'failed-echeck':520 //payment_status=Denied or failed521 $new_status = ($isECtransaction ? MODULE_PAYMENT_PAYPALWPP_REFUNDED_STATUS_ID : MODULE_PAYMENT_PAYPAL_REFUND_ORDER_STATUS_ID);522 break;523 case 'echeck-cleared':524 $new_status = (defined('MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID') ? MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID : 2);525 break;526 case ($txn_type=='express-checkout-cleared' || substr($txn_type,0,8) == 'cleared-'):527 //express-checkout-cleared528 $new_status = ($isECtransaction && defined('MODULE_PAYMENT_PAYPALWPP_ORDER_STATUS_ID') ? MODULE_PAYMENT_PAYPALWPP_ORDER_STATUS_ID : MODULE_PAYMENT_PAYPAL_ORDER_STATUS_ID);529 if ((int)$new_status == 0) $new_status = 2;530 break;531 case 'pending-auth':532 // pending authorization533 $new_status = ($isECtransaction ? MODULE_PAYMENT_PAYPALWPP_REFUNDED_STATUS_ID : MODULE_PAYMENT_PAYPAL_REFUND_ORDER_STATUS_ID);534 break;535 case (substr($txn_type,0,7) == 'denied-'):536 // denied for any other reason - treat as pending for now537 case (substr($txn_type,0,8) == 'pending-'):538 // pending anything539 $new_status = ($isECtransaction ? MODULE_PAYMENT_PAYPALWPP_ORDER_PENDING_STATUS_ID : MODULE_PAYMENT_PAYPAL_PROCESSING_STATUS_ID);540 break;541 }542 // update order status history with new information543 ipn_debug_email('IPN NOTICE :: Set new status ' . $new_status . " for order ID = " . $ordersID . ($_POST['pending_reason'] != '' ? '. Reason_code = ' . $_POST['pending_reason'] : '') );544 if ((int)$new_status == 0) $new_status = 1;545 if (in_array($_POST['payment_status'], array('Refunded', 'Reversed', 'Denied', 'Failed'))546 || substr($txn_type,0,8) == 'cleared-' || $txn_type=='echeck-cleared' || $txn_type == 'express-checkout-cleared') {547 ipn_update_orders_status_and_history($ordersID, $new_status, $txn_type);548 $zco_notifier->notify('NOTIFY_PAYPALIPN_STATUS_HISTORY_UPDATE', array($ordersID, $new_status, $txn_type));549 }550 break;551 default:552 // can't understand result found. Thus, logging and aborting.553 ipn_debug_email('IPN WARNING :: Could not process for txn type: ' . $txn_type . "\n" . ' postdata=' . str_replace('&', " \n&", urldecode(print_r($_POST, TRUE))));554 }555 // debug info only556 switch (TRUE) {557 case ($txn_type == 'pending-echeck' && (int)$ordersID > 0):558 ipn_debug_email('IPN NOTICE :: Pending echeck transaction for existing order. No action required. Waiting for echeck to clear.');559 break;560 case ($txn_type == 'pending-multicurrency' && (int)$ordersID > 0):561 ipn_debug_email('IPN NOTICE :: Pending multicurrency transaction for existing order. No action required. Waiting for merchant to "accept" the order via PayPal account console.');562 break;563 case ($txn_type == 'pending-address' && (int)$ordersID > 0):564 ipn_debug_email('IPN NOTICE :: "Pending address" transaction for existing order. No action required. Waiting for address approval by store owner via PayPal account console.');565 break;566 case ($txn_type == 'pending-paymentreview' && (int)$ordersID > 0):567 ipn_debug_email('IPN NOTICE :: "Pending payment review" transaction for existing order. No action required. Waiting for PayPal to complete their Payment Review. Do not ship order until review is completed.');568 break;569 }570 }
9. 前面的所有流程完成之后,先生成订单后付款的功能就已经搞定了,接下来就是在后台修改为付款订单价格数量及运费的问题了。代码如下:
1 <?php 2 /** 3 * @package admin 4 * @copyright Copyright 2003-2010 Zen Cart Development Team 5 * @copyright Portions Copyright 2003 osCommerce 6 * @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0 7 * @version $Id: orders.php 15994 2010-04-19 17:17:51Z ajeh $ 8 */ 9 10 require('includes/application_top.php'); 11 12 require(DIR_WS_CLASSES . 'currencies.php'); 13 $currencies = new currencies(); 14 15 include(DIR_WS_CLASSES . 'order.php'); 16 17 //订单修改提交后的数据处理代码 EOF 18 19 if(!empty($_POST['ot_total']) && isset($_GET[oID]) && $_GET[oID] !=''){ 20 21 $update_order_id=$_GET[oID]; 22 $products_list=array(); 23 $total_list=array(); 24 foreach($_POST['reference_oid'] as $value1){ 25 $products_list[$value1]=array(); 26 } 27 28 $products_list_loop = $products_list; 29 30 foreach($_POST as $key2=>$value2){ 31 foreach ($products_list_loop as $key3=>$value3){ 32 if($key3 == ltrim(strrchr($key2,'_'),'_')){ 33 $array_key = substr($key2,0,strripos($key2,'_')); 34 if($array_key != 'qty'){ 35 $products_list[$key3][$array_key] = $value2 / $_POST['currencies_value']; 36 }else{ 37 $products_list[$key3][$array_key] = $value2; 38 } 39 } 40 } 41 } 42 43 $order_total_value=$_POST['ot_total'] / $_POST['currencies_value']; 44 $order_total_text=$currencies->format($order_total_value,true,$_POST['currencies_key'],$_POST['currencies_value']); 45 46 $order_subtotal_value=$_POST['ot_subtotal'] / $_POST['currencies_value']; 47 $order_subtotal_text=$currencies->format($order_subtotal_value,true,$_POST['currencies_key'],$_POST['currencies_value']); 48 49 $order_shipping_value=$_POST['ot_shipping'] / $_POST['currencies_value'];; 50 $order_shipping_text=$currencies->format($order_shipping_value,true,$_POST['currencies_key'],$_POST['currencies_value']); 51 52 // $order_gv_text=$_POST['ot_gv']; 53 // $order_gv_value=$_POST['ot_gv']; 54 55 // $order_coupon_text=$_POST['ot_coupon']; 56 // $order_coupon_value=$_POST['ot_coupon']; 57 58 foreach($products_list as $key4=>$value4){ 59 $sql_update_order_products="update " . TABLE_ORDERS_PRODUCTS . " 60 set products_price = " . $products_list[$key4]['price_ex'] . " , final_price = " . $products_list[$key4]['price_ex'] . " , products_quantity = " . $products_list[$key4]['qty'] . " 61 where orders_id = " . $update_order_id . " and products_id = " . $key4; 62 $db->Execute($sql_update_order_products); 63 // echo "更新产品价格和数量: " . $sql_update_order_products . "<br />"; 64 // var_dump($db->Execute($sql_update_order_products)); 65 // echo '<br />'; 66 } 67 68 if($order_subtotal_text){ 69 $sql_update_subtotal="update " . TABLE_ORDERS_TOTAL . " 70 set text = '" . $order_subtotal_text . "' , value = " . $order_subtotal_value ." 71 where orders_id = " . $update_order_id . " and class = 'ot_subtotal'"; 72 $db->Execute($sql_update_subtotal); 73 // echo "更新产品总价: " . $sql_update_subtotal . "<br />"; 74 // var_dump($db->Execute($sql_update_subtotal)); 75 // echo '<br />'; 76 } 77 78 if($order_shipping_text){ 79 $sql_update_shipping="update " . TABLE_ORDERS_TOTAL . " 80 set text = '" . $order_shipping_text . "' , value = " . $order_shipping_value ." 81 where orders_id = " . $update_order_id . " and class = 'ot_shipping'"; 82 $db->Execute($sql_update_shipping); 83 // echo "更新运费价格: " . $sql_update_shipping . "<br />"; 84 // var_dump($db->Execute($sql_update_shipping)); 85 // echo '<br />'; 86 } 87 88 if($order_total_text){ 89 $sql_update_total="update " . TABLE_ORDERS_TOTAL . " 90 set text = '" . $order_total_text . "' , value = " . $order_total_value ." 91 where orders_id = " . $update_order_id . " and class = 'ot_total'"; 92 $db->Execute($sql_update_total); 93 // echo "更新订单总价: " . $sql_update_total . "<br />"; 94 // var_dump($db->Execute($sql_update_total)); 95 // echo '<br />'; 96 97 $sql_update_order="update " . TABLE_ORDERS . " set order_total = " .$order_total_value . " where orders_id = " . $update_order_id; 98 $db->Execute($sql_update_order); 99 // echo "更新订单: " . $sql_update_order . '<br />'; 100 // var_dump($db->Execute($sql_update_order)); 101 // echo '<br />'; 102 } 103 104 echo "<script language=JavaScript> location.replace(location.href);</script>"; 105 // echo '<pre>'; 106 // echo "汇率: ".$_POST['currencies_value'] . '<br />'; 107 // echo "转成默认货币:" . $order_total_value / $_POST['currencies_value'] . '<br />'; 108 // echo '<br />'; 109 // echo "交易货币值: ".$order_total_value."<br />"; 110 // echo "转成交易货币样式: " . $currencies->format(($order_total_value / $_POST['currencies_value']),true,$_POST['currencies_key'],$_POST['currencies_value']); 111 // print_r($products_list); 112 // print_r($_POST); 113 // echo '</pre>'; 114 } 115 116 //订单修改提交后的数据处理代码 BOF 117 118 // prepare order-status pulldown list 119 $orders_statuses = array(); 120 $orders_status_array = array(); 121 $orders_status = $db->Execute("select orders_status_id, orders_status_name 122 from " . TABLE_ORDERS_STATUS . " 123 where language_id = '" . (int)$_SESSION['languages_id'] . "' order by orders_status_id"); 124 while (!$orders_status->EOF) { 125 $orders_statuses[] = array('id' => $orders_status->fields['orders_status_id'], 126 'text' => $orders_status->fields['orders_status_name'] . ' [' . $orders_status->fields['orders_status_id'] . ']'); 127 $orders_status_array[$orders_status->fields['orders_status_id']] = $orders_status->fields['orders_status_name']; 128 $orders_status->MoveNext(); 129 } 130 131 $action = (isset($_GET['action']) ? $_GET['action'] : ''); 132 $order_exists = false; 133 if (isset($_GET['oID']) && trim($_GET['oID']) == '') unset($_GET['oID']); 134 if ($action == 'edit' && !isset($_GET['oID'])) $action = ''; 135 136 if (isset($_GET['oID'])) { 137 $oID = zen_db_prepare_input(trim($_GET['oID'])); 138 139 $orders = $db->Execute("select orders_id from " . TABLE_ORDERS . " 140 where orders_id = '" . $oID . "'"); 141 $order_exists = true; 142 if ($orders->RecordCount() <= 0) { 143 $order_exists = false; 144 if ($action != '') $messageStack->add_session(ERROR_ORDER_DOES_NOT_EXIST . ' ' . $oID, 'error'); 145 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID', 'action')), 'NONSSL')); 146 } 147 } 148 149 if (zen_not_null($action) && $order_exists == true) { 150 switch ($action) { 151 case 'edit': 152 // reset single download to on 153 if ($_GET['download_reset_on'] > 0) { 154 // adjust download_maxdays based on current date 155 $check_status = $db->Execute("select customers_name, customers_email_address, orders_status,orders_num, 156 date_purchased from " . TABLE_ORDERS . " 157 where orders_id = '" . $_GET['oID'] . "'"); 158 $zc_max_days = zen_date_diff($check_status->fields['date_purchased'], date('Y-m-d H:i:s', time())) + DOWNLOAD_MAX_DAYS; 159 160 $update_downloads_query = "update " . TABLE_ORDERS_PRODUCTS_DOWNLOAD . " set download_maxdays='" . $zc_max_days . "', download_count='" . DOWNLOAD_MAX_COUNT . "' where orders_id='" . $_GET['oID'] . "' and orders_products_download_id='" . $_GET['download_reset_on'] . "'"; 161 $db->Execute($update_downloads_query); 162 unset($_GET['download_reset_on']); 163 164 $messageStack->add_session(SUCCESS_ORDER_UPDATED_DOWNLOAD_ON, 'success'); 165 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=edit', 'NONSSL')); 166 } 167 // reset single download to off 168 if ($_GET['download_reset_off'] > 0) { 169 // adjust download_maxdays based on current date 170 // *** fix: adjust count not maxdays to cancel download 171 // $update_downloads_query = "update " . TABLE_ORDERS_PRODUCTS_DOWNLOAD . " set download_maxdays='0', download_count='0' where orders_id='" . $_GET['oID'] . "' and orders_products_download_id='" . $_GET['download_reset_off'] . "'"; 172 $update_downloads_query = "update " . TABLE_ORDERS_PRODUCTS_DOWNLOAD . " set download_count='0' where orders_id='" . $_GET['oID'] . "' and orders_products_download_id='" . $_GET['download_reset_off'] . "'"; 173 unset($_GET['download_reset_off']); 174 $db->Execute($update_downloads_query); 175 176 $messageStack->add_session(SUCCESS_ORDER_UPDATED_DOWNLOAD_OFF, 'success'); 177 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=edit', 'NONSSL')); 178 } 179 break; 180 case 'update_order': 181 // demo active test 182 if (zen_admin_demo()) { 183 $_GET['action']= ''; 184 $messageStack->add_session(ERROR_ADMIN_DEMO, 'caution'); 185 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=edit', 'NONSSL')); 186 } 187 $oID = zen_db_prepare_input($_GET['oID']); 188 $status = zen_db_prepare_input($_POST['status']); 189 $comments = zen_db_prepare_input($_POST['comments']); 190 $tracking_number = zen_db_prepare_input($_POST['tracking_number']); 191 192 $order_updated = false; 193 $check_status = $db->Execute("select customers_name, customers_email_address, orders_status,orders_num,tracking_number, 194 date_purchased from " . TABLE_ORDERS . " 195 where orders_id = '" . $oID . "'"); 196 197 if ( ($check_status->fields['orders_status'] != $status) || zen_not_null($comments)) { 198 $db->Execute("update " . TABLE_ORDERS . " 199 set orders_status = '" . zen_db_input($status) . "', last_modified = now(), tracking_number = '" . zen_db_input($tracking_number) . "' 200 where orders_id = '" . $oID . "'"); 201 202 $customer_notified = '0'; 203 if (isset($_POST['notify']) && ($_POST['notify'] == '1')) { 204 205 $notify_comments = ''; 206 if (isset($_POST['notify_comments']) && ($_POST['notify_comments'] == 'on') && zen_not_null($comments)) { 207 $notify_comments = EMAIL_TEXT_COMMENTS_UPDATE . $comments . "\n\n"; 208 } 209 //send emails 210 $message = 211 EMAIL_TEXT_ORDER_NUMBER . ' ' . $check_status->fields['orders_num'] . "\n\n" . 212 EMAIL_TEXT_INVOICE_URL . ' ' . zen_catalog_href_link(FILENAME_CATALOG_ACCOUNT_HISTORY_INFO, 'order_id=' . $oID, 'SSL') . "\n\n" . 213 EMAIL_TEXT_DATE_ORDERED . ' ' . zen_date_long($check_status->fields['date_purchased']) . "\n\n" . 214 strip_tags($notify_comments) . 215 EMAIL_TEXT_STATUS_UPDATED . sprintf(EMAIL_TEXT_STATUS_LABEL, $orders_status_array[$status] ) . 216 EMAIL_TEXT_STATUS_PLEASE_REPLY; 217 218 $html_msg['EMAIL_CUSTOMERS_NAME'] = $check_status->fields['customers_name']; 219 $html_msg['EMAIL_TEXT_ORDER_NUMBER'] = EMAIL_TEXT_ORDER_NUMBER . ' ' . $check_status->fields['orders_num']; 220 $html_msg['EMAIL_TEXT_INVOICE_URL'] = '<a href="' . zen_catalog_href_link(FILENAME_CATALOG_ACCOUNT_HISTORY_INFO, 'order_id=' . $oID, 'SSL') .'">'.str_replace(':','',EMAIL_TEXT_INVOICE_URL).'</a>'; 221 $html_msg['EMAIL_TEXT_DATE_ORDERED'] = EMAIL_TEXT_DATE_ORDERED . ' ' . zen_date_long($check_status->fields['date_purchased']); 222 $html_msg['EMAIL_TEXT_STATUS_COMMENTS'] = nl2br($notify_comments); 223 $html_msg['EMAIL_TEXT_STATUS_UPDATED'] = str_replace('\n','', EMAIL_TEXT_STATUS_UPDATED); 224 $html_msg['EMAIL_TEXT_STATUS_LABEL'] = str_replace('\n','', sprintf(EMAIL_TEXT_STATUS_LABEL, $orders_status_array[$status] )); 225 $html_msg['EMAIL_TEXT_NEW_STATUS'] = $orders_status_array[$status]; 226 $html_msg['EMAIL_TEXT_STATUS_PLEASE_REPLY'] = str_replace('\n','', EMAIL_TEXT_STATUS_PLEASE_REPLY); 227 228 zen_mail($check_status->fields['customers_name'], $check_status->fields['customers_email_address'], EMAIL_TEXT_SUBJECT . ' #' . $check_status->fields['orders_num'], $message, STORE_NAME, EMAIL_FROM, $html_msg, 'order_status'); 229 $customer_notified = '1'; 230 231 //send extra emails 232 if (SEND_EXTRA_ORDERS_STATUS_ADMIN_EMAILS_TO_STATUS == '1' and SEND_EXTRA_ORDERS_STATUS_ADMIN_EMAILS_TO != '') { 233 zen_mail('', SEND_EXTRA_ORDERS_STATUS_ADMIN_EMAILS_TO, SEND_EXTRA_ORDERS_STATUS_ADMIN_EMAILS_TO_SUBJECT . ' ' . EMAIL_TEXT_SUBJECT . ' #' . $check_status->fields['orders_num'], $message, STORE_NAME, EMAIL_FROM, $html_msg, 'order_status_extra'); 234 } 235 } elseif (isset($_POST['notify']) && ($_POST['notify'] == '-1')) { 236 // hide comment 237 $customer_notified = '-1'; 238 } 239 240 $db->Execute("insert into " . TABLE_ORDERS_STATUS_HISTORY . " 241 (orders_id, orders_status_id, date_added, customer_notified, comments) 242 values ('" . $oID . "', 243 '" . zen_db_input($status) . "', 244 now(), 245 '" . zen_db_input($customer_notified) . "', 246 '" . zen_db_input($comments) . "')"); 247 $order_updated = true; 248 } 249 250 // trigger any appropriate updates which should be sent back to the payment gateway: 251 $order = new order($oID); 252 if ($order->info['payment_module_code']) { 253 if (file_exists(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php')) { 254 require_once(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php'); 255 require_once(DIR_FS_CATALOG_LANGUAGES . $_SESSION['language'] . '/modules/payment/' . $order->info['payment_module_code'] . '.php'); 256 $module = new $order->info['payment_module_code']; 257 if (method_exists($module, '_doStatusUpdate')) { 258 $response = $module->_doStatusUpdate($oID, $status, $comments, $customer_notified, $check_status->fields['orders_status']); 259 } 260 } 261 } 262 263 if ($order_updated == true) { 264 if ($status == DOWNLOADS_ORDERS_STATUS_UPDATED_VALUE) { 265 // adjust download_maxdays based on current date 266 $zc_max_days = zen_date_diff($check_status->fields['date_purchased'], date('Y-m-d H:i:s', time())) + DOWNLOAD_MAX_DAYS; 267 268 $update_downloads_query = "update " . TABLE_ORDERS_PRODUCTS_DOWNLOAD . " set download_maxdays='" . $zc_max_days . "', download_count='" . DOWNLOAD_MAX_COUNT . "' where orders_id='" . $oID . "'"; 269 $db->Execute($update_downloads_query); 270 } 271 $messageStack->add_session(SUCCESS_ORDER_UPDATED, 'success'); 272 } else { 273 $messageStack->add_session(WARNING_ORDER_NOT_UPDATED, 'warning'); 274 } 275 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=edit', 'NONSSL')); 276 break; 277 case 'deleteconfirm': 278 // demo active test 279 if (zen_admin_demo()) { 280 $_GET['action']= ''; 281 $messageStack->add_session(ERROR_ADMIN_DEMO, 'caution'); 282 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID', 'action')), 'NONSSL')); 283 } 284 $oID = zen_db_prepare_input($_GET['oID']); 285 286 zen_remove_order($oID, $_POST['restock']); 287 288 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID', 'action')), 'NONSSL')); 289 break; 290 case 'delete_cvv': 291 $delete_cvv = $db->Execute("update " . TABLE_ORDERS . " set cc_cvv = '" . TEXT_DELETE_CVV_REPLACEMENT . "' where orders_id = '" . (int)$_GET['oID'] . "'"); 292 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=edit', 'NONSSL')); 293 break; 294 case 'mask_cc': 295 $result = $db->Execute("select cc_number from " . TABLE_ORDERS . " where orders_id = '" . (int)$_GET['oID'] . "'"); 296 $old_num = $result->fields['cc_number']; 297 $new_num = substr($old_num, 0, 4) . str_repeat('*', (strlen($old_num) - 8)) . substr($old_num, -4); 298 $mask_cc = $db->Execute("update " . TABLE_ORDERS . " set cc_number = '" . $new_num . "' where orders_id = '" . (int)$_GET['oID'] . "'"); 299 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=edit', 'NONSSL')); 300 break; 301 302 case 'doRefund': 303 $order = new order($oID); 304 if ($order->info['payment_module_code']) { 305 if (file_exists(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php')) { 306 require_once(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php'); 307 require_once(DIR_FS_CATALOG_LANGUAGES . $_SESSION['language'] . '/modules/payment/' . $order->info['payment_module_code'] . '.php'); 308 $module = new $order->info['payment_module_code']; 309 if (method_exists($module, '_doRefund')) { 310 $module->_doRefund($oID); 311 } 312 } 313 } 314 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=edit', 'NONSSL')); 315 break; 316 case 'doAuth': 317 $order = new order($oID); 318 if ($order->info['payment_module_code']) { 319 if (file_exists(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php')) { 320 require_once(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php'); 321 require_once(DIR_FS_CATALOG_LANGUAGES . $_SESSION['language'] . '/modules/payment/' . $order->info['payment_module_code'] . '.php'); 322 $module = new $order->info['payment_module_code']; 323 if (method_exists($module, '_doAuth')) { 324 $module->_doAuth($oID, $order->info['total'], $order->info['currency']); 325 } 326 } 327 } 328 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=edit', 'NONSSL')); 329 break; 330 case 'doCapture': 331 $order = new order($oID); 332 if ($order->info['payment_module_code']) { 333 if (file_exists(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php')) { 334 require_once(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php'); 335 require_once(DIR_FS_CATALOG_LANGUAGES . $_SESSION['language'] . '/modules/payment/' . $order->info['payment_module_code'] . '.php'); 336 $module = new $order->info['payment_module_code']; 337 if (method_exists($module, '_doCapt')) { 338 $module->_doCapt($oID, 'Complete', $order->info['total'], $order->info['currency']); 339 } 340 } 341 } 342 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=edit', 'NONSSL')); 343 break; 344 case 'doVoid': 345 $order = new order($oID); 346 if ($order->info['payment_module_code']) { 347 if (file_exists(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php')) { 348 require_once(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php'); 349 require_once(DIR_FS_CATALOG_LANGUAGES . $_SESSION['language'] . '/modules/payment/' . $order->info['payment_module_code'] . '.php'); 350 $module = new $order->info['payment_module_code']; 351 if (method_exists($module, '_doVoid')) { 352 $module->_doVoid($oID); 353 } 354 } 355 } 356 zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=edit', 'NONSSL')); 357 break; 358 } 359 } 360 ?> 361 <!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"> 362 <html <?php echo HTML_PARAMS; ?>> 363 <head> 364 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo CHARSET; ?>"> 365 <title><?php echo TITLE; ?></title> 366 <link rel="stylesheet" type="text/css" href="includes/stylesheet.css"> 367 <link rel="stylesheet" type="text/css" media="print" href="includes/stylesheet_print.css"> 368 <link rel="stylesheet" type="text/css" href="includes/cssjsmenuhover.css" media="all" id="hoverJS"> 369 <script language="javascript" src="includes/menu.js"></script> 370 <script language="javascript" src="includes/general.js"></script> 371 <script type="text/javascript"> 372 <!-- 373 function init() 374 { 375 cssjsmenu('navbar'); 376 if (document.getElementById) 377 { 378 var kill = document.getElementById('hoverJS'); 379 kill.disabled = true; 380 } 381 } 382 // --> 383 </script> 384 <script language="javascript" type="text/javascript"><!-- 385 function couponpopupWindow(url) { 386 window.open(url,'popupWindow','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,copyhistory=no,width=450,height=280,screenX=150,screenY=150,top=150,left=150') 387 } 388 //--></script> 389 <link rel="stylesheet" type="text/css" href="includes/javascript/spiffyCal/spiffyCal_v2_1.css"> 390 <script language="JavaScript" src="includes/javascript/spiffyCal/spiffyCal_v2_1.js"></script> 391 392 <?php //引入一个jquery库,然后就是控制修改价格的Jquery代码 EOF ?> 393 <script language="JavaScript" src="includes/javascript/jquery.min.js"></script> 394 <script type="text/javascript"> 395 $(document).ready(function(){ 396 $("#orders_edit").click(function(){ 397 $("#orders_submit").show(); 398 $("#orders_reset").show(); 399 $("#orders_edit").hide(); 400 $("#products_list_changes").show(); 401 $("#products_list_default").hide(); 402 }); 403 404 $("#orders_reset").click(function(){ 405 location.replace(location.href); 406 }); 407 408 $("#orders_submit").click(function(){ 409 if($("input[name='ot_total']").val()<0){ 410 alert("总价格为负数,这不符合规定"); 411 return false; 412 } 413 }); 414 415 $("#products_list_changes input").keypress(function(event) { 416 var keyCode = event.which; 417 if (keyCode == 46 || (keyCode >= 48 && keyCode <=57) || keyCode == 8) 418 return true; 419 else 420 return false; 421 }).focus(function() { 422 this.style.imeMode='disabled'; 423 }); 424 }); 425 426 function init() 427 { 428 cssjsmenu('navbar'); 429 if (document.getElementById) 430 { 431 var kill = document.getElementById('hoverJS'); 432 kill.disabled = true; 433 } 434 } 435 436 function selectAll(){ 437 var checklist = document.getElementsByName ("order_id[]"); 438 if(document.getElementById("select_all").checked) 439 { 440 for(var i=0;i<checklist.length;i++) 441 { 442 checklist[i].checked = 1; 443 } 444 }else{ 445 for(var j=0;j<checklist.length;j++) 446 { 447 checklist[j].checked = 0; 448 } 449 } 450 } 451 452 //加法运算 453 function accAdd(arg1,arg2){ 454 var r1,r2,m; 455 try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} 456 try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} 457 m=Math.pow(10,Math.max(r1,r2)) 458 return ((arg1*m+arg2*m)/m).toFixed(2); 459 } 460 461 //减法运算 462 function accSub(arg1, arg2) { 463 var r1, r2, m, n; 464 try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 } 465 try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 } 466 m = Math.pow(10, Math.max(r1, r2)); 467 n = (r1 >= r2) ? r1 : r2; 468 return ((arg1 * m - arg2 * m) / m).toFixed(n); 469 } 470 471 //乘法运算 472 function accMul(arg1,arg2) 473 { 474 var m=0,s1=arg1.toString(),s2=arg2.toString(); 475 try{m+=s1.split(".")[1].length}catch(e){} 476 try{m+=s2.split(".")[1].length}catch(e){} 477 return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m) 478 } 479 480 //除法运算 481 function accDiv(arg1, arg2) { 482 var t1 = 0, t2 = 0, r1, r2; 483 try { t1 = arg1.toString().split(".")[1].length } catch (e) { } 484 try { t2 = arg2.toString().split(".")[1].length } catch (e) { } 485 with (Math) { 486 r1 = Number(arg1.toString().replace(".", "")) 487 r2 = Number(arg2.toString().replace(".", "")) 488 return (r1 / r2) * pow(10, t2 - t1); 489 } 490 } 491 492 function change_price_ex(order_id,final_price){ 493 var products_qty_simple = "qty_"+order_id; 494 var products_qty = $("input[name='"+products_qty_simple+"']").val(); 495 var price_ex_value_simple = "price_ex_"+order_id; 496 var price_ex_value = $("input[name='"+price_ex_value_simple+"']").val(); 497 498 if(isNaN(price_ex_value)){ 499 alert("你输入的不是数字,价格将恢复到原始值,请重新输入正确的价格。"); 500 $("input[name='"+price_ex_value_simple+"']").val(final_price); 501 var price_ex_value = $("input[name='"+price_ex_value_simple+"']").val(); 502 }else{ 503 var numindex = parseInt(price_ex_value.indexOf("."),10); 504 if(numindex > 0){ 505 var head = price_ex_value.substring(0,numindex); 506 var bottom = price_ex_value.substring(numindex,numindex+3); 507 var fianlNum = head+bottom; 508 $("input[name='"+price_ex_value_simple+"']").val(fianlNum); 509 var price_ex_value = fianlNum; 510 } 511 } 512 var total_ex_value = (accMul(price_ex_value,products_qty)).toFixed(2); 513 var total_ex = "total_ex_"+order_id; 514 var total_ex_hidden = "total_ex_hidden_"+order_id; 515 var price_inc = "price_inc_"+order_id; 516 var total_inc = "total_inc_"+order_id; 517 $("input[name='"+total_ex+"']").val(total_ex_value); 518 $("#"+total_ex_hidden).text(total_ex_value); 519 $("input[name='"+price_inc+"']").val(price_ex_value); 520 $("input[name='"+total_inc+"']").val(total_ex_value); 521 522 var str=0; 523 $("#price_total p").each(function (i){ 524 str = accAdd(str,parseFloat($(this).text())); 525 }) 526 527 $("input[name='ot_subtotal']").val(str); 528 529 var ot_subtotal = parseFloat($("input[name='ot_subtotal']").val()); 530 var ot_coupon = $("input[name='ot_coupon']").val(); 531 if(ot_coupon==undefined){ 532 ot_coupon=0; 533 } 534 var ot_gv = $("input[name='ot_gv']").val(); 535 if(ot_gv==undefined){ 536 ot_gv=0; 537 } 538 var ot_shipping = parseFloat($("input[name='ot_shipping']").val()); 539 var ot_total = accSub(accSub(accAdd(ot_subtotal,ot_shipping),ot_coupon),ot_gv); 540 $("input[name='ot_total']").val(ot_total); 541 } 542 543 function change_qty(order_id){ 544 var products_qty_simple = "qty_"+order_id; 545 var products_qty = parseInt($("input[name='"+products_qty_simple+"']").val()); 546 if(isNaN(products_qty) || products_qty==0){ 547 products_qty=""; 548 } 549 var price_ex_value_simple = "price_ex_"+order_id; 550 var price_ex_value = $("input[name='"+price_ex_value_simple+"']").val(); 551 $("input[name='"+products_qty_simple+"']").val(products_qty); 552 553 var total_ex_value = (accMul(price_ex_value,products_qty)).toFixed(2); 554 var total_ex = "total_ex_"+order_id; 555 var total_ex_hidden = "total_ex_hidden_"+order_id; 556 var price_inc = "price_inc_"+order_id; 557 var total_inc = "total_inc_"+order_id; 558 $("input[name='"+total_ex+"']").val(total_ex_value); 559 $("#"+total_ex_hidden).text(total_ex_value); 560 $("input[name='"+total_inc+"']").val(total_ex_value); 561 562 var str=0; 563 $("#price_total p").each(function (i){ 564 str = accAdd(str,parseFloat($(this).text())); 565 }) 566 567 $("input[name='ot_subtotal']").val(str); 568 569 var ot_subtotal = parseFloat($("input[name='ot_subtotal']").val()); 570 var ot_coupon = $("input[name='ot_coupon']").val(); 571 if(ot_coupon==undefined){ 572 ot_coupon=0; 573 } 574 var ot_gv = $("input[name='ot_gv']").val(); 575 if(ot_gv==undefined){ 576 ot_gv=0; 577 } 578 var ot_shipping = parseFloat($("input[name='ot_shipping']").val()); 579 var ot_total = accSub(accSub(accAdd(ot_subtotal,ot_shipping),ot_coupon),ot_gv); 580 $("input[name='ot_total']").val(ot_total); 581 } 582 583 function change_shipping(shipping_total){ 584 var ot_shipping = $("input[name='ot_shipping']").val(); 585 if(isNaN(ot_shipping)){ 586 alert("你输入的不是数字,运费将恢复到原始值,请重新输入正确的运费。"); 587 $("input[name='ot_shipping']").val(shipping_total); 588 var ot_shipping = parseFloat($("input[name='ot_shipping']").val()); 589 }else{ 590 var numindex = parseInt(ot_shipping.indexOf("."),10); 591 if(numindex > 0){ 592 var head = ot_shipping.substring(0,numindex); 593 var bottom = ot_shipping.substring(numindex,numindex+3); 594 var fianlNum = head+bottom; 595 $("input[name='ot_shipping']").val(fianlNum); 596 var ot_shipping = fianlNum; 597 } 598 } 599 var ot_subtotal = parseFloat($("input[name='ot_subtotal']").val()); 600 var ot_coupon = $("input[name='ot_coupon']").val(); 601 if(ot_coupon==undefined){ 602 ot_coupon=0; 603 } 604 var ot_gv = $("input[name='ot_gv']").val(); 605 if(ot_gv==undefined){ 606 ot_gv=0; 607 } 608 var ot_total = accSub(accSub(accAdd(ot_subtotal,ot_shipping),ot_coupon),ot_gv); 609 $("input[name='ot_total']").val(ot_total); 610 } 611 612 function price_ex_onlive(order_id,final_price){ 613 var products_qty_simple = "qty_"+order_id; 614 var products_qty = $("input[name='"+products_qty_simple+"']").val(); 615 var price_ex_value_simple = "price_ex_"+order_id; 616 var price_ex_value = $("input[name='"+price_ex_value_simple+"']").val(); 617 618 if(price_ex_value==""){ 619 alert("你输入的不是数字,价格将恢复到原始值,请重新输入正确的价格。"); 620 $("input[name='"+price_ex_value_simple+"']").val(final_price); 621 var price_ex_value = $("input[name='"+price_ex_value_simple+"']").val(); 622 } 623 var total_ex_value = (accMul(price_ex_value,products_qty)).toFixed(2); 624 var total_ex = "total_ex_"+order_id; 625 var total_ex_hidden = "total_ex_hidden_"+order_id; 626 var price_inc = "price_inc_"+order_id; 627 var total_inc = "total_inc_"+order_id; 628 $("input[name='"+total_ex+"']").val(total_ex_value); 629 $("#"+total_ex_hidden).text(total_ex_value); 630 $("input[name='"+price_inc+"']").val(price_ex_value); 631 $("input[name='"+total_inc+"']").val(total_ex_value); 632 633 var str=0; 634 $("#price_total p").each(function (i){ 635 str = accAdd(str,parseFloat($(this).text())); 636 }) 637 638 $("input[name='ot_subtotal']").val(str); 639 640 var ot_subtotal = parseFloat($("input[name='ot_subtotal']").val()); 641 var ot_coupon = $("input[name='ot_coupon']").val(); 642 if(ot_coupon==undefined){ 643 ot_coupon=0; 644 } 645 var ot_gv = $("input[name='ot_gv']").val(); 646 if(ot_gv==undefined){ 647 ot_gv=0; 648 } 649 var ot_shipping = parseFloat($("input[name='ot_shipping']").val()); 650 var ot_total = accSub(accSub(accAdd(ot_subtotal,ot_shipping),ot_coupon),ot_gv); 651 $("input[name='ot_total']").val(ot_total); 652 } 653 654 function qty_onlive(order_id,qty){ 655 var products_qty_simple = "qty_"+order_id; 656 var products_qty = parseInt($("input[name='"+products_qty_simple+"']").val()); 657 if(isNaN(products_qty) || products_qty==0){ 658 alert("你输入的不是数字,数量将恢复到原始值,请重新输入正确的数量。"); 659 products_qty=qty; 660 } 661 var price_ex_value_simple = "price_ex_"+order_id; 662 var price_ex_value = $("input[name='"+price_ex_value_simple+"']").val(); 663 $("input[name='"+products_qty_simple+"']").val(products_qty); 664 665 var total_ex_value = (accMul(price_ex_value,products_qty)).toFixed(2); 666 var total_ex = "total_ex_"+order_id; 667 var total_ex_hidden = "total_ex_hidden_"+order_id; 668 var price_inc = "price_inc_"+order_id; 669 var total_inc = "total_inc_"+order_id; 670 $("input[name='"+total_ex+"']").val(total_ex_value); 671 $("#"+total_ex_hidden).text(total_ex_value); 672 $("input[name='"+total_inc+"']").val(total_ex_value); 673 674 var str=0; 675 $("#price_total p").each(function (i){ 676 str = accAdd(str,parseFloat($(this).text())); 677 }) 678 679 $("input[name='ot_subtotal']").val(str); 680 681 var ot_subtotal = parseFloat($("input[name='ot_subtotal']").val()); 682 var ot_coupon = $("input[name='ot_coupon']").val(); 683 if(ot_coupon==undefined){ 684 ot_coupon=0; 685 } 686 var ot_gv = $("input[name='ot_gv']").val(); 687 if(ot_gv==undefined){ 688 ot_gv=0; 689 } 690 var ot_shipping = parseFloat($("input[name='ot_shipping']").val()); 691 var ot_total = accSub(accSub(accAdd(ot_subtotal,ot_shipping),ot_coupon),ot_gv); 692 $("input[name='ot_total']").val(ot_total); 693 } 694 695 function shipping_onlive(shipping_total){ 696 var ot_shipping = $("input[name='ot_shipping']").val(); 697 if(ot_shipping==""){ 698 alert("你输入的不是数字,运费将恢复到原始值,请重新输入正确的运费。"); 699 $("input[name='ot_shipping']").val(shipping_total); 700 var ot_shipping = parseFloat($("input[name='ot_shipping']").val()); 701 } 702 var ot_subtotal = parseFloat($("input[name='ot_subtotal']").val()); 703 var ot_coupon = $("input[name='ot_coupon']").val(); 704 if(ot_coupon==undefined){ 705 ot_coupon=0; 706 } 707 var ot_gv = $("input[name='ot_gv']").val(); 708 if(ot_gv==undefined){ 709 ot_gv=0; 710 } 711 var ot_total = accSub(accSub(accAdd(ot_subtotal,ot_shipping),ot_coupon),ot_gv); 712 $("input[name='ot_total']").val(ot_total); 713 } 714 715 <?php //引入一个jquery库,然后就是控制修改价格的Jquery代码 BOF ?> 716 717 </script> 718 </head> 719 <body onLoad="init()"> 720 <div id="spiffycalendar" class="text"></div> 721 <!-- header //--> 722 <div class="header-area"> 723 <?php 724 require(DIR_WS_INCLUDES . 'header.php'); 725 ?> 726 </div> 727 <!-- header_eof //--> 728 729 <!-- body //--> 730 <table border="0" width="100%" cellspacing="2" cellpadding="2"> 731 <tr> 732 <!-- body_text //--> 733 734 <?php if ($action == '') { ?> 735 <!-- search --> 736 <td width="100%" valign="top"><table border="0" width="100%" cellspacing="0" cellpadding="2"> 737 <tr> 738 <td><table border="0" width="100%" cellspacing="0" cellpadding="0"> 739 <tr><?php echo zen_draw_form('search', FILENAME_ORDERS, '', 'get', '', true); ?> 740 <td width="65%" class="pageHeading" align="right"><?php echo zen_draw_separator('pixel_trans.gif', 1, HEADING_IMAGE_HEIGHT); ?></td> 741 <td colspan="2" class="smallText" align="right"> 742 <?php 743 // show reset search 744 if ((isset($_GET['search']) && zen_not_null($_GET['search'])) or $_GET['cID'] !='' or isset($_GET['start']) or isset($_GET['end'])) { 745 echo '<a href="' . zen_href_link(FILENAME_ORDERS, '', 'NONSSL') . '">' . zen_image_button('button_reset.gif', IMAGE_RESET) . '</a><br />'; 746 } 747 ?> 748 <?php 749 echo 'Search by orders num or Customer Information:' . zen_draw_input_field('search') . zen_hide_session_id(); 750 if (isset($_GET['search']) && zen_not_null($_GET['search'])) { 751 $keywords = zen_db_input(zen_db_prepare_input($_GET['search'])); 752 echo '<br/ >' . TEXT_INFO_SEARCH_DETAIL_FILTER . $keywords; 753 } 754 ?> 755 </td> 756 </form> 757 758 759 <?php echo zen_draw_form('search_orders_products', FILENAME_ORDERS, '', 'get', '', true); ?> 760 <td class="pageHeading" align="right"><?php echo zen_draw_separator('pixel_trans.gif', 1, HEADING_IMAGE_HEIGHT); ?></td> 761 <td colspan="2" class="smallText" align="right"> 762 <?php 763 // show reset search orders_products 764 if ((isset($_GET['search_orders_products']) && zen_not_null($_GET['search_orders_products'])) or $_GET['cID'] !='') { 765 echo '<a href="' . zen_href_link(FILENAME_ORDERS, '', 'NONSSL') . '">' . zen_image_button('button_reset.gif', IMAGE_RESET) . '</a><br />'; 766 } 767 ?> 768 <?php 769 echo HEADING_TITLE_SEARCH_DETAIL_ORDERS_PRODUCTS . ' ' . zen_draw_input_field('search_orders_products') . zen_hide_session_id(); 770 if (isset($_GET['search_orders_products']) && zen_not_null($_GET['search_orders_products'])) { 771 $keywords_orders_products = zen_db_input(zen_db_prepare_input($_GET['search_orders_products'])); 772 echo '<br/ >' . TEXT_INFO_SEARCH_DETAIL_FILTER_ORDERS_PRODUCTS . zen_db_prepare_input($keywords_orders_products); 773 } 774 ?> 775 </td> 776 </form> 777 778 </table></td> 779 </tr> 780 <tr> 781 <td width="100%"> 782 <table cellspacing="0" cellpadding="0" width="100%" border="0"> 783 <tbody> 784 <tr> 785 <td class="pageHeading"></td> 786 <td class="pageHeading" align="right"><?php echo zen_draw_separator('pixel_trans.gif', 1, HEADING_IMAGE_HEIGHT); ?></td> 787 <td align="right"> 788 <table cellspacing="0" cellpadding="0" width="0%" border="0"> 789 <tbody> 790 <form method="get" action="orders.php" name="new_special"> 791 <?php if(!empty($_GET['cID'])) {?> 792 <input type="hidden" name="cID" value=<?php echo $_GET['cID']; ?>> 793 <?php } ?> 794 <script language="javascript"> 795 var StartDate = new ctlSpiffyCalendarBox("StartDate", "new_special", "start", "btnDate1","<?php echo (($sInfo->specials_date_available == '0001-01-01') ? '' : zen_date_short($sInfo->specials_date_available)); ?>",scBTNMODE_CUSTOMBLUE); 796 var EndDate = new ctlSpiffyCalendarBox("EndDate", "new_special", "end", "btnDate2","<?php echo (($sInfo->expires_date == '0001-01-01') ? '' : zen_date_short($sInfo->expires_date)); ?>",scBTNMODE_CUSTOMBLUE); 797 </script> 798 <tr> 799 <script> 800 document.onreadystatechange = function () { 801 if(document.readyState=="complete") { 802 var obj=document.getElementById("total").innerHTML; 803 document.getElementById("allOrderTotal").innerHTML="$"+obj; 804 } 805 } 806 function showTotal(){ 807 var obj=document.getElementById("total").innerHTML; 808 document.getElementById("allOrderTotal").innerHTML="$"+obj; 809 } 810 </script> 811 <td align="left" colspan=2>All Order Total: <span id="allOrderTotal"></span></td> 812 <td width="5%" align="right"></td> 813 <td align="right"><?php echo "Orders start date"; ?> </td> 814 <td align="right"><script language="javascript">StartDate.writeControl(); StartDate.dateFormat="<?php echo "yyyy/MM/dd"; ?>";</script></td> 815 <td width="5%" align="right"></td> 816 <td align="right"><?php echo "Orders end date"; ?> </td> 817 <td align="right"><script language="javascript">EndDate.writeControl(); EndDate.dateFormat="<?php echo "yyyy/MM/dd"; ?>";</script></td> 818 <td width="180px" align="center"><?php echo zen_image_submit('button_search.gif','')?></td> 819 </tr> 820 </form> 821 </tbody> 822 </table> 823 </td> 824 </tr> 825 </tbody> 826 </table> 827 </td> 828 </tr> 829 <!-- search --> 830 <?php } ?> 831 832 833 <?php 834 if (($action == 'edit') && ($order_exists == true)) { 835 $order = new order($oID); 836 if ($order->info['payment_module_code']) { 837 if (file_exists(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php')) { 838 require(DIR_FS_CATALOG_MODULES . 'payment/' . $order->info['payment_module_code'] . '.php'); 839 require(DIR_FS_CATALOG_LANGUAGES . $_SESSION['language'] . '/modules/payment/' . $order->info['payment_module_code'] . '.php'); 840 $module = new $order->info['payment_module_code']; 841 // echo $module->admin_notification($oID); 842 } 843 } 844 ?> 845 <tr> 846 <td width="100%"><table border="0" width="100%" cellspacing="0" cellpadding="0"> 847 <tr> 848 <td class="pageHeading"><?php echo HEADING_TITLE; ?></td> 849 <td class="pageHeading" align="right"><?php echo zen_draw_separator('pixel_trans.gif', 1, HEADING_IMAGE_HEIGHT); ?></td> 850 <td class="pageHeading" align="right"><?php echo '<a href="javascript:history.back()">' . zen_image_button('button_back.gif', IMAGE_BACK) . '</a>'; ?></td> 851 </tr> 852 </table></td> 853 </tr> 854 <tr> 855 <td><table width="100%" border="0" cellspacing="0" cellpadding="2"> 856 <tr> 857 <td colspan="3"><?php echo zen_draw_separator(); ?></td> 858 </tr> 859 <tr> 860 <td valign="top"><table width="100%" border="0" cellspacing="0" cellpadding="2"> 861 <tr> 862 <td class="main" valign="top"><strong><?php echo ENTRY_CUSTOMER; ?></strong></td> 863 <td class="main"><?php echo zen_address_format($order->customer['format_id'], $order->customer, 1, '', '<br />'); ?></td> 864 </tr> 865 <tr> 866 <td colspan="2"><?php echo zen_draw_separator('pixel_trans.gif', '1', '5'); ?></td> 867 </tr> 868 <tr> 869 <td class="main"><strong><?php echo ENTRY_TELEPHONE_NUMBER; ?></strong></td> 870 <td class="main"><?php echo $order->customer['telephone']; ?></td> 871 </tr> 872 <tr> 873 <td class="main"><strong><?php echo ENTRY_EMAIL_ADDRESS; ?></strong></td> 874 <td class="main"><?php echo '<a href="mailto:' . $order->customer['email_address'] . '">' . $order->customer['email_address'] . '</a>'; ?></td> 875 </tr> 876 <tr> 877 <td class="main"><strong><?php echo TEXT_INFO_IP_ADDRESS; ?></strong></td> 878 <td class="main"><?php echo $order->info['ip_address']; ?></td> 879 </tr> 880 </table></td> 881 <td valign="top"><table width="100%" border="0" cellspacing="0" cellpadding="2"> 882 <tr> 883 <td class="main" valign="top"><strong><?php echo ENTRY_SHIPPING_ADDRESS; ?></strong></td> 884 <td class="main"><?php echo zen_address_format($order->delivery['format_id'], $order->delivery, 1, '', '<br />'); ?></td> 885 </tr> 886 </table></td> 887 <td valign="top"><table width="100%" border="0" cellspacing="0" cellpadding="2"> 888 <tr> 889 <td class="main" valign="top"><strong><?php echo ENTRY_BILLING_ADDRESS; ?></strong></td> 890 <td class="main"><?php echo zen_address_format($order->billing['format_id'], $order->billing, 1, '', '<br />'); ?></td> 891 </tr> 892 </table></td> 893 </tr> 894 </table></td> 895 </tr> 896 <tr> 897 <td><?php echo zen_draw_separator('pixel_trans.gif', '1', '10'); ?></td> 898 </tr> 899 <tr> 900 <td class="main"><strong><?php echo ENTRY_ORDER_ID . $order->info['num']; ?></strong></td> 901 </tr> 902 <tr> 903 <td><table border="0" cellspacing="0" cellpadding="2"> 904 <tr> 905 <td class="main"><strong><?php echo ENTRY_DATE_PURCHASED; ?></strong></td> 906 <td class="main"><?php echo zen_date_long($order->info['date_purchased']); ?></td> 907 </tr> 908 <tr> 909 <td class="main"><strong><?php echo ENTRY_PAYMENT_METHOD; ?></strong></td> 910 <td class="main"><?php echo $order->info['payment_method']; ?></td> 911 </tr> 912 <?php 913 if (zen_not_null($order->info['cc_type']) || zen_not_null($order->info['cc_owner']) || zen_not_null($order->info['cc_number'])) { 914 ?> 915 <tr> 916 <td colspan="2"><?php echo zen_draw_separator('pixel_trans.gif', '1', '10'); ?></td> 917 </tr> 918 <tr> 919 <td class="main"><?php echo ENTRY_CREDIT_CARD_TYPE; ?></td> 920 <td class="main"><?php echo $order->info['cc_type']; ?></td> 921 </tr> 922 <tr> 923 <td class="main"><?php echo ENTRY_CREDIT_CARD_OWNER; ?></td> 924 <td class="main"><?php echo $order->info['cc_owner']; ?></td> 925 </tr> 926 <tr> 927 <td class="main"><?php echo ENTRY_CREDIT_CARD_NUMBER; ?></td> 928 <td class="main"><?php echo $order->info['cc_number'] . (zen_not_null($order->info['cc_number']) && !strstr($order->info['cc_number'],'X') && !strstr($order->info['cc_number'],'********') ? ' <a href="' . zen_href_link(FILENAME_ORDERS, '&action=mask_cc&oID=' . $oID, 'NONSSL') . '" class="noprint">' . TEXT_MASK_CC_NUMBER . '</a>' : ''); ?><td> 929 </tr> 930 <?php if (zen_not_null($order->info['cc_cvv'])) { ?> 931 <tr> 932 <td class="main"><?php echo ENTRY_CREDIT_CARD_CVV; ?></td> 933 <td class="main"><?php echo $order->info['cc_cvv'] . (zen_not_null($order->info['cc_cvv']) && !strstr($order->info['cc_cvv'],TEXT_DELETE_CVV_REPLACEMENT) ? ' <a href="' . zen_href_link(FILENAME_ORDERS, '&action=delete_cvv&oID=' . $oID, 'NONSSL') . '" class="noprint">' . TEXT_DELETE_CVV_FROM_DATABASE . '</a>' : ''); ?><td> 934 </tr> 935 <?php } ?> 936 <tr> 937 <td class="main"><?php echo ENTRY_CREDIT_CARD_EXPIRES; ?></td> 938 <td class="main"><?php echo $order->info['cc_expires']; ?></td> 939 </tr> 940 <?php 941 } 942 ?> 943 </table></td> 944 </tr> 945 <?php 946 if (method_exists($module, 'admin_notification')) { 947 ?> 948 <tr> 949 <td><?php echo zen_draw_separator('pixel_trans.gif', '1', '10'); ?></td> 950 </tr> 951 <tr> 952 <?php echo $module->admin_notification($oID); ?> 953 </tr> 954 <tr> 955 <td><?php echo zen_draw_separator('pixel_trans.gif', '1', '10'); ?></td> 956 </tr> 957 <?php 958 } 959 ?> 960 961 <?php 962 //从这里开始,设定为付款订单才能修改价格,5为为付款选项的ID 963 if($order->info['orders_status'] == 5){ 964 ?> 965 <tr><form action="" method="post"><td align="right"><input type="hidden" name="currencies_key" value="<?php echo $order->info['currency']; ?>"><input type="hidden" name="currencies_value" value="<?php echo $order->info['currency_value']; ?>"><input type="button" value="编辑" id="orders_edit"><input style="display: none" type="submit" value="提交" id="orders_submit"><input style="display: none" type="button" value="取消" id="orders_reset"></td></tr> 966 <tr id="products_list_changes" style="display: none"> 967 <td><table border="0" width="100%" cellspacing="0" cellpadding="2"> 968 <tr class="dataTableHeadingRow"> 969 <td class="dataTableHeadingContent"><?php echo Image; ?></td> 970 <td class="dataTableHeadingContent" colspan="2"><?php echo TABLE_HEADING_PRODUCTS; ?></td> 971 <td class="dataTableHeadingContent"><?php echo TABLE_HEADING_PRODUCTS_MODEL; ?></td> 972 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TAX; ?></td> 973 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_PRICE_EXCLUDING_TAX; ?></td> 974 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_PRICE_INCLUDING_TAX; ?></td> 975 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TOTAL_EXCLUDING_TAX; ?></td> 976 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TOTAL_INCLUDING_TAX; ?></td> 977 </tr> 978 979 <?php 980 981 for ($i=0, $n=sizeof($order->products); $i<$n; $i++) { 982 $price_input='<input onblur="price_ex_onlive('.$order->products[$i]['id'].','.preg_replace( '/[^\d\.]/', '',$currencies->format($order->products[$i]['final_price'], true, $order->info['currency'], $order->info['currency_value'])).')" onKeyUp="change_price_ex('.$order->products[$i]['id'].','.preg_replace( '/[^\d\.]/', '',$currencies->format($order->products[$i]['final_price'], true, $order->info['currency'], $order->info['currency_value'])).')" size="6" type="text" value="'; 983 $qty_input = '<input onblur="qty_onlive('.$order->products[$i]['id'].','.$order->products[$i]['qty'].')" onKeyUp="change_qty('.$order->products[$i]['id'].')" size="6" type="text" value="'; 984 $total_input='<input readonly size="6" type="text" value="'; 985 echo ' <tr class="dataTableRow">' . "\n" . 986 ' <td><img src="../images/'.$order->products[$i]['image'].'" heiht="80" width="80"/></td>'. 987 ' <td class="dataTableContent" valign="top" align="right" style="color:c00">' . $qty_input . $order->products[$i]['qty'] . '" name="qty_'.$order->products[$i]['id'].'"> x</td>' . "\n" . 988 ' <td class="dataTableContent" valign="top"><a href="'.HTTP_SERVER.DIR_WS_CATALOG.'index.php?main_page=product_info&products_id='.$order->products[$i]['id'].'" target=_blank>'. $order->products[$i]['name']; 989 990 if (isset($order->products[$i]['attributes']) && (sizeof($order->products[$i]['attributes']) > 0)) { 991 for ($j = 0, $k = sizeof($order->products[$i]['attributes']); $j < $k; $j++) { 992 echo '<br /><nobr><small> <i> - ' . $order->products[$i]['attributes'][$j]['option'] . ': ' . nl2br(zen_output_string_protected($order->products[$i]['attributes'][$j]['value'])); 993 if ($order->products[$i]['attributes'][$j]['price'] != '0') echo ' (' . $order->products[$i]['attributes'][$j]['prefix'] . $currencies->format($order->products[$i]['attributes'][$j]['price'] * $order->products[$i]['qty'], true, $order->info['currency'], $order->info['currency_value']) . ')'; 994 if ($order->products[$i]['attributes'][$j]['product_attribute_is_free'] == '1' and $order->products[$i]['product_is_free'] == '1') echo TEXT_INFO_ATTRIBUTE_FREE; 995 echo '</i></small></nobr>'; 996 } 997 } 998 999 echo ' </a></td>' . "\n" .1000 ' <td class="dataTableContent" valign="top">' . $order->products[$i]['model'] . '</td>' . "\n" .1001 ' <td class="dataTableContent" align="right" valign="top">' . zen_display_tax_value($order->products[$i]['tax']) . '%</td>' . "\n" .1002 ' <td class="dataTableContent" align="right" valign="top"><strong>' .$price_input.1003 preg_replace( '/[^\d\.]/', '',$currencies->format($order->products[$i]['final_price'], true, $order->info['currency'], $order->info['currency_value'])).1004 '" name="price_ex_'.$order->products[$i]['id'].'">'.1005 ($order->products[$i]['onetime_charges'] != 0 ? '<br />' . $currencies->format($order->products[$i]['onetime_charges'], true, $order->info['currency'], $order->info['currency_value']) : '') .1006 '</strong></td>' . "\n" .1007 ' <td class="dataTableContent" align="right" valign="top"><strong><strong>' . $total_input.1008 preg_replace( '/[^\d\.]/', '',$currencies->format(zen_add_tax($order->products[$i]['final_price'], $order->products[$i]['tax']), true, $order->info['currency'], $order->info['currency_value'])).1009 '" name="price_inc_'.$order->products[$i]['id'].'">'.1010 ($order->products[$i]['onetime_charges'] != 0 ? '<br />' . $currencies->format(zen_add_tax($order->products[$i]['onetime_charges'], $order->products[$i]['tax']), true, $order->info['currency'], $order->info['currency_value']) : '') .1011 '</strong></td>' . "\n" .1012 ' <td class="dataTableContent" align="right" valign="top"><strong>' . $total_input.1013 preg_replace( '/[^\d\.]/', '',$currencies->format($order->products[$i]['final_price'] * $order->products[$i]['qty'], true, $order->info['currency'], $order->info['currency_value'])) .1014 '" name="total_ex_'.$order->products[$i]['id'].'">'.1015 ($order->products[$i]['onetime_charges'] != 0 ? '<br />' . $currencies->format($order->products[$i]['onetime_charges'], true, $order->info['currency'], $order->info['currency_value']) : '') .1016 '</strong></td>' . "\n" .1017 ' <td class="dataTableContent" align="right" valign="top"><strong>' .$total_input.1018 preg_replace( '/[^\d\.]/', '',$currencies->format(zen_add_tax($order->products[$i]['final_price'], $order->products[$i]['tax']) * $order->products[$i]['qty'], true, $order->info['currency'], $order->info['currency_value'])) .1019 '" name="total_inc_'.$order->products[$i]['id'].'">'.1020 ($order->products[$i]['onetime_charges'] != 0 ? '<br />' . $currencies->format(zen_add_tax($order->products[$i]['onetime_charges'], $order->products[$i]['tax']), true, $order->info['currency'], $order->info['currency_value']) : '') .1021 '</strong></td>' . "\n";1022 echo ' </tr>' . "\n";1023 echo ' <input type="hidden" name="reference_oid[]" value="'.$order->products[$i]['id'].'">';1024 }1025 1026 echo '<div style="display:none" id="price_total">';1027 for ($i=0, $n=sizeof($order->products); $i<$n; $i++){1028 echo '<p id="total_ex_hidden_'.$order->products[$i]['id'].'" >'.preg_replace( '/[^\d\.]/', '',$currencies->format($order->products[$i]['final_price'], true, $order->info['currency'], $order->info['currency_value'])) * $order->products[$i]['qty'].'</p>';1029 }1030 echo '<div>';1031 ?>1032 <tr>1033 <td align="right" colspan="9"><table border="0" cellspacing="0" cellpadding="2">1034 <?php1035 for ($i = 0, $n = sizeof($order->totals); $i < $n; $i++) {1036 echo ' <tr>' . "\n" .1037 ' <td align="right" class="'. str_replace('_', '-', $order->totals[$i]['class']) . '-Text">' . $order->totals[$i]['title'] . '</td>' . "\n" ;1038 if($order->totals[$i]['class'] == "ot_shipping"){1039 echo ' <td align="right" class="'. str_replace('_', '-', $order->totals[$i]['class']) . '-Amount"><input onblur="shipping_onlive('.preg_replace("/[^\d\.]/", "", $order->totals[$i]['text']).')" onKeyUp="change_shipping('.preg_replace("/[^\d\.]/", "", $order->totals[$i]['text']).')" size="6" type="text" value="' . preg_replace("/[^\d\.]/", "", $order->totals[$i]['text']) . '" name="'.$order->totals[$i]['class'].'"></td>' . "\n";1040 }1041 else{1042 echo ' <td align="right" class="'. str_replace('_', '-', $order->totals[$i]['class']) . '-Amount"><input readonly size="6" type="text" value="' . preg_replace("/[^\d\.]/", "", $order->totals[$i]['text']) . '" name="'.$order->totals[$i]['class'].'"></td>' . "\n";1043 }1044 echo ' </tr>' . "\n";1045 }1046 ?>1047 </table></td>1048 </tr>1049 </table></td>1050 </tr>1051 </form>1052 <?php1053 }1054 ?>1055 <?php //修改为付款订单代码从这里结束 ?>1056 1057 <tr id="products_list_default">1058 <td><table border="0" width="100%" cellspacing="0" cellpadding="2">1059 <tr class="dataTableHeadingRow">1060 <td class="dataTableHeadingContent"><?php echo Image; ?></td>1061 <td class="dataTableHeadingContent" colspan="2"><?php echo TABLE_HEADING_PRODUCTS; ?></td>1062 <td class="dataTableHeadingContent"><?php echo TABLE_HEADING_PRODUCTS_MODEL; ?></td>1063 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TAX; ?></td>1064 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_PRICE_EXCLUDING_TAX; ?></td>1065 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_PRICE_INCLUDING_TAX; ?></td>1066 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TOTAL_EXCLUDING_TAX; ?></td>1067 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_TOTAL_INCLUDING_TAX; ?></td>1068 </tr>1069 <?php1070 for ($i=0, $n=sizeof($order->products); $i<$n; $i++) { 1071 echo ' <tr class="dataTableRow">' . "\n" .1072 ' <td><img src="../images/'.$order->products[$i]['image'].'" heiht="80" width="80"/></td>'.1073 ' <td class="dataTableContent" valign="top" align="right" style="color:c00">' . $order->products[$i]['qty'] . ' x</td>' . "\n" .1074 ' <td class="dataTableContent" valign="top"><a href="'.HTTP_SERVER.DIR_WS_CATALOG.'index.php?main_page=product_info&products_id='.$order->products[$i]['id'].'" target=_blank>'. $order->products[$i]['name'];1075 1076 if (isset($order->products[$i]['attributes']) && (sizeof($order->products[$i]['attributes']) > 0)) {1077 for ($j = 0, $k = sizeof($order->products[$i]['attributes']); $j < $k; $j++) {1078 echo '<br /><nobr><small> <i> - ' . $order->products[$i]['attributes'][$j]['option'] . ': ' . nl2br(zen_output_string_protected($order->products[$i]['attributes'][$j]['value']));1079 if ($order->products[$i]['attributes'][$j]['price'] != '0') echo ' (' . $order->products[$i]['attributes'][$j]['prefix'] . $currencies->format($order->products[$i]['attributes'][$j]['price'] * $order->products[$i]['qty'], true, $order->info['currency'], $order->info['currency_value']) . ')';1080 if ($order->products[$i]['attributes'][$j]['product_attribute_is_free'] == '1' and $order->products[$i]['product_is_free'] == '1') echo TEXT_INFO_ATTRIBUTE_FREE;1081 echo '</i></small></nobr>';1082 }1083 }1084 1085 echo ' </a></td>' . "\n" .1086 ' <td class="dataTableContent" valign="top">' . $order->products[$i]['model'] . '</td>' . "\n" .1087 ' <td class="dataTableContent" align="right" valign="top">' . zen_display_tax_value($order->products[$i]['tax']) . '%</td>' . "\n" .1088 ' <td class="dataTableContent" align="right" valign="top"><strong>' .1089 $currencies->format($order->products[$i]['final_price'], true, $order->info['currency'], $order->info['currency_value']) .1090 ($order->products[$i]['onetime_charges'] != 0 ? '<br />' . $currencies->format($order->products[$i]['onetime_charges'], true, $order->info['currency'], $order->info['currency_value']) : '') .1091 '</strong></td>' . "\n" .1092 ' <td class="dataTableContent" align="right" valign="top"><strong>' .1093 $currencies->format(zen_add_tax($order->products[$i]['final_price'], $order->products[$i]['tax']), true, $order->info['currency'], $order->info['currency_value']) .1094 ($order->products[$i]['onetime_charges'] != 0 ? '<br />' . $currencies->format(zen_add_tax($order->products[$i]['onetime_charges'], $order->products[$i]['tax']), true, $order->info['currency'], $order->info['currency_value']) : '') .1095 '</strong></td>' . "\n" .1096 ' <td class="dataTableContent" align="right" valign="top"><strong>' .1097 $currencies->format($order->products[$i]['final_price'] * $order->products[$i]['qty'], true, $order->info['currency'], $order->info['currency_value']) .1098 ($order->products[$i]['onetime_charges'] != 0 ? '<br />' . $currencies->format($order->products[$i]['onetime_charges'], true, $order->info['currency'], $order->info['currency_value']) : '') .1099 '</strong></td>' . "\n" .1100 ' <td class="dataTableContent" align="right" valign="top"><strong>' .1101 $currencies->format(zen_add_tax($order->products[$i]['final_price'], $order->products[$i]['tax']) * $order->products[$i]['qty'], true, $order->info['currency'], $order->info['currency_value']) .1102 ($order->products[$i]['onetime_charges'] != 0 ? '<br />' . $currencies->format(zen_add_tax($order->products[$i]['onetime_charges'], $order->products[$i]['tax']), true, $order->info['currency'], $order->info['currency_value']) : '') .1103 '</strong></td>' . "\n";1104 echo ' </tr>' . "\n";1105 }1106 ?>1107 <tr>1108 <td align="right" colspan="9"><table border="0" cellspacing="0" cellpadding="2">1109 <?php1110 for ($i = 0, $n = sizeof($order->totals); $i < $n; $i++) {1111 echo ' <tr>' . "\n" .1112 ' <td align="right" class="'. str_replace('_', '-', $order->totals[$i]['class']) . '-Text">' . $order->totals[$i]['title'] . '</td>' . "\n" .1113 ' <td align="right" class="'. str_replace('_', '-', $order->totals[$i]['class']) . '-Amount">' . $order->totals[$i]['text'] . '</td>' . "\n" .1114 ' </tr>' . "\n";1115 }1116 ?>1117 </table></td>1118 </tr>1119 </table></td>1120 </tr>1121 1122 <?php1123 // show downloads1124 require(DIR_WS_MODULES . 'orders_download.php');1125 ?>1126 1127 <tr>1128 <td><?php echo zen_draw_separator('pixel_trans.gif', '1', '10'); ?></td>1129 </tr>1130 <tr>1131 <td class="main"><table border="1" cellspacing="0" cellpadding="5">1132 <tr>1133 <td class="smallText" align="center"><strong><?php echo TABLE_HEADING_DATE_ADDED; ?></strong></td>1134 <td class="smallText" align="center"><strong><?php echo TABLE_HEADING_CUSTOMER_NOTIFIED; ?></strong></td>1135 <td class="smallText" align="center"><strong><?php echo TABLE_HEADING_STATUS; ?></strong></td>1136 <td class="smallText" align="center"><strong><?php echo TABLE_HEADING_COMMENTS; ?></strong></td>1137 </tr>1138 <?php1139 $orders_history = $db->Execute("select orders_status_id, date_added, customer_notified, comments1140 from " . TABLE_ORDERS_STATUS_HISTORY . "1141 where orders_id = '" . zen_db_input($oID) . "'1142 order by date_added");1143 1144 if ($orders_history->RecordCount() > 0) {1145 while (!$orders_history->EOF) {1146 echo ' <tr>' . "\n" .1147 ' <td class="smallText" align="center">' . zen_datetime_short($orders_history->fields['date_added']) . '</td>' . "\n" .1148 ' <td class="smallText" align="center">';1149 if ($orders_history->fields['customer_notified'] == '1') {1150 echo zen_image(DIR_WS_ICONS . 'tick.gif', TEXT_YES) . "</td>\n";1151 } else if ($orders_history->fields['customer_notified'] == '-1') {1152 echo zen_image(DIR_WS_ICONS . 'locked.gif', TEXT_HIDDEN) . "</td>\n";1153 } else {1154 echo zen_image(DIR_WS_ICONS . 'unlocked.gif', TEXT_VISIBLE) . "</td>\n";1155 }1156 echo ' <td class="smallText">' . $orders_status_array[$orders_history->fields['orders_status_id']] . '</td>' . "\n";1157 echo ' <td class="smallText">' . nl2br(zen_db_output($orders_history->fields['comments'])) . ' </td>' . "\n" .1158 ' </tr>' . "\n";1159 $orders_history->MoveNext();1160 }1161 } else {1162 echo ' <tr>' . "\n" .1163 ' <td class="smallText" colspan="5">' . TEXT_NO_ORDER_HISTORY . '</td>' . "\n" .1164 ' </tr>' . "\n";1165 }1166 ?>1167 </table></td>1168 </tr>1169 <tr>1170 <td class="main noprint"><br /><strong><?php echo TABLE_HEADING_COMMENTS; ?></strong></td>1171 </tr>1172 <tr>1173 <td class="noprint"><?php echo zen_draw_separator('pixel_trans.gif', '1', '5'); ?></td>1174 </tr>1175 <tr><?php echo zen_draw_form('status', FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=update_order', 'post', '', true); ?>1176 <td class="main noprint"><?php echo zen_draw_textarea_field('comments', 'soft', '60', '5'); ?></td>1177 </tr>1178 <tr>1179 <td><?php echo zen_draw_separator('pixel_trans.gif', '1', '10'); ?></td>1180 </tr>1181 <tr>1182 <td><table border="0" cellspacing="0" cellpadding="2" class="noprint">1183 <tr>1184 <td><table border="0" cellspacing="0" cellpadding="2">1185 <tr>1186 <td class="main"><strong><?php echo "Tracking Number:"; ?></strong> <?php echo zen_draw_input_field('tracking_number', $order->info['tracking_number']); ?></td>1187 </tr> 1188 <tr>1189 <td class="main"><strong><?php echo ENTRY_STATUS; ?></strong> <?php echo zen_draw_pull_down_menu('status', $orders_statuses, $order->info['orders_status']); ?></td>1190 </tr>1191 <tr>1192 <td class="main"><strong><?php echo ENTRY_NOTIFY_CUSTOMER; ?></strong> [<?php echo zen_draw_radio_field('notify', '1', true) . '-' . TEXT_EMAIL . ' ' . zen_draw_radio_field('notify', '0', FALSE) . '-' . TEXT_NOEMAIL . ' ' . zen_draw_radio_field('notify', '-1', FALSE) . '-' . TEXT_HIDE; ?>] </td>1193 <td class="main"><strong><?php echo ENTRY_NOTIFY_COMMENTS; ?></strong> <?php echo zen_draw_checkbox_field('notify_comments', '', true); ?></td>1194 </tr>1195 <tr><td><br /></td></tr>1196 </table></td>1197 <td valign="top"><?php echo zen_image_submit('button_update.gif', IMAGE_UPDATE); ?></td>1198 </tr>1199 </table></td>1200 </form></tr>1201 <tr>1202 <td colspan="2" align="right" class="noprint"><?php echo '<a href="' . zen_href_link(FILENAME_ORDERS_INVOICE, 'oID=' . $_GET['oID']) . '" TARGET="_blank">' . zen_image_button('button_invoice.gif', IMAGE_ORDERS_INVOICE) . '</a> <a href="' . zen_href_link(FILENAME_ORDERS_PACKINGSLIP, 'oID=' . $_GET['oID']) . '" TARGET="_blank">' . zen_image_button('button_packingslip.gif', IMAGE_ORDERS_PACKINGSLIP) . '</a> <a href="' . zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('action'))) . '">' . zen_image_button('button_orders.gif', IMAGE_ORDERS) . '</a>'; ?></td>1203 </tr>1204 <?php1205 // check if order has open gv1206 $gv_check = $db->Execute("select order_id, unique_id1207 from " . TABLE_COUPON_GV_QUEUE ."1208 where order_id = '" . $_GET['oID'] . "' and release_flag='N' limit 1");1209 if ($gv_check->RecordCount() > 0) {1210 $goto_gv = '<a href="' . zen_href_link(FILENAME_GV_QUEUE, 'order=' . $_GET['oID']) . '">' . zen_image_button('button_gift_queue.gif',IMAGE_GIFT_QUEUE) . '</a>';1211 echo ' <tr><td align="right"><table width="225"><tr>';1212 echo ' <td align="center">';1213 echo $goto_gv . ' ';1214 echo ' </td>';1215 echo ' </tr></table></td></tr>';1216 }1217 ?>1218 <?php1219 } else {1220 ?>1221 <tr>1222 <td width="100%"><table border="0" width="100%" cellspacing="0" cellpadding="0">1223 <tr>1224 <td class="pageHeading"><?php echo HEADING_TITLE; ?></td>1225 <td class="pageHeading" align="right"><?php echo zen_draw_separator('pixel_trans.gif', 1, HEADING_IMAGE_HEIGHT); ?></td>1226 <td align="right"><table border="0" width="100%" cellspacing="0" cellpadding="0">1227 <tr><?php echo zen_draw_form('orders_num', FILENAME_ORDERS, '', 'get', '', true); ?>1228 <td class="smallText" align="right"><?php echo 'order_num' . ' ' . zen_draw_input_field('orders_num', '', 'size="12"') . zen_hide_session_id(); ?></td>1229 </form></tr>1230 <tr><?php echo zen_draw_form('status', FILENAME_ORDERS, '', 'get', '', true); ?>1231 <td class="smallText" align="right">1232 <?php1233 echo HEADING_TITLE_STATUS . ' ' . zen_draw_pull_down_menu('status', array_merge(array(array('id' => '', 'text' => TEXT_ALL_ORDERS)), $orders_statuses), $_GET['status'], 'onChange="this.form.submit();"');1234 echo zen_hide_session_id();1235 ?>1236 </td>1237 </form></tr>1238 </table></td>1239 </tr>1240 </table></td>1241 </tr>1242 <tr>1243 <td><table border="0" width="100%" cellspacing="0" cellpadding="0">1244 <tr>1245 <td class="smallText">1246 <?php echo TEXT_LEGEND . ' ' . zen_image(DIR_WS_IMAGES . 'icon_status_red.gif', TEXT_BILLING_SHIPPING_MISMATCH, 10, 10) . ' ' . TEXT_BILLING_SHIPPING_MISMATCH; ?>1247 <?php echo zen_image(DIR_WS_IMAGES . 'icon_green_on.gif', IMAGE_ICON_STATUS_ON)."PCB Order"; ?>1248 <?php echo zen_image(DIR_WS_IMAGES . 'icon_red_on.gif', IMAGE_ICON_STATUS_ON)."PRE Order"; ?>1249 <?php echo zen_image(DIR_WS_IMAGES . 'icon_yellow_on.gif', IMAGE_ICON_STATUS_ON)."Customer Comments"; ?>1250 </td>1251 <tr>1252 <td valign="top"><table border="0" width="100%" cellspacing="0" cellpadding="2">1253 <tr class="dataTableHeadingRow">1254 <?php1255 // Sort Listing1256 switch ($_GET['list_order']) {1257 case "id-asc":1258 $disp_order = "c.customers_id";1259 break;1260 case "firstname":1261 $disp_order = "c.customers_firstname";1262 break;1263 case "firstname-desc":1264 $disp_order = "c.customers_firstname DESC";1265 break;1266 case "lastname":1267 $disp_order = "c.customers_lastname, c.customers_firstname";1268 break;1269 case "lastname-desc":1270 $disp_order = "c.customers_lastname DESC, c.customers_firstname";1271 break;1272 case "company":1273 $disp_order = "a.entry_company";1274 break;1275 case "company-desc":1276 $disp_order = "a.entry_company DESC";1277 break;1278 default:1279 $disp_order = "c.customers_id DESC";1280 }1281 ?>1282 <td class="dataTableHeadingContent" align="center"><?php echo TABLE_HEADING_ORDERS_ID; ?></td>1283 <td class="dataTableHeadingContent" align="left" width="50"><?php echo TABLE_HEADING_PAYMENT_METHOD; ?></td>1284 <td class="dataTableHeadingContent"><?php echo TABLE_HEADING_CUSTOMERS; ?></td>1285 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_ORDER_TOTAL; ?></td>1286 <td class="dataTableHeadingContent" align="center"><?php echo TABLE_HEADING_DATE_PURCHASED; ?></td>1287 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_STATUS; ?></td>1288 <td class="dataTableHeadingContent" align="center"><?php echo TABLE_HEADING_CUSTOMER_COMMENTS; ?></td>1289 <td class="dataTableHeadingContent" align="center"><input type="checkbox" id="select_all" onclick="selectAll()"></td>1290 <td class="dataTableHeadingContent" align="right"><?php echo TABLE_HEADING_ACTION; ?> </td>1291 </tr>1292 1293 <?php1294 // Only one or the other search1295 // create search_orders_products filter1296 $search = '';1297 $new_table = '';1298 $new_fields = '';1299 if (isset($_GET['search_orders_products']) && zen_not_null($_GET['search_orders_products'])) {1300 $new_fields = '';1301 $search_distinct = ' distinct ';1302 $new_table = " left join " . TABLE_ORDERS_PRODUCTS . " op on (op.orders_id = o.orders_id) ";1303 $keywords = zen_db_input(zen_db_prepare_input($_GET['search_orders_products']));1304 $search = " and (op.products_model like '%" . $keywords . "%' or op.products_name like '%" . $keywords . "%')";1305 if (substr(strtoupper($_GET['search_orders_products']), 0, 3) == 'ID:') {1306 $keywords = TRIM(substr($_GET['search_orders_products'], 3));1307 $search = " and op.products_id ='" . (int)$keywords . "'";1308 }1309 } else {1310 ?>1311 <?php1312 // create search filter1313 $search = '';1314 if (isset($_GET['search']) && zen_not_null($_GET['search'])) {1315 $search_distinct = ' ';1316 $keywords = zen_db_input(zen_db_prepare_input($_GET['search']));1317 $search = " and (o.customers_city like '%" . $keywords . "%' or o.orders_num like '%" . $keywords ."%' or o.customers_postcode like '%" . $keywords . "%' or o.date_purchased like '%" . $keywords . "%' or o.billing_name like '%" . $keywords . "%' or o.billing_company like '%" . $keywords . "%' or o.billing_street_address like '%" . $keywords . "%' or o.delivery_city like '%" . $keywords . "%' or o.delivery_postcode like '%" . $keywords . "%' or o.delivery_name like '%" . $keywords . "%' or o.delivery_company like '%" . $keywords . "%' or o.delivery_street_address like '%" . $keywords . "%' or o.billing_city like '%" . $keywords . "%' or o.billing_postcode like '%" . $keywords . "%' or o.customers_email_address like '%" . $keywords . "%' or o.customers_name like '%" . $keywords . "%' or o.customers_company like '%" . $keywords . "%' or o.customers_street_address like '%" . $keywords . "%' or o.customers_telephone like '%" . $keywords . "%' or o.ip_address like '%" . $keywords . "%')";1318 $new_table = '';1319 // $new_fields = ", o.customers_company, o.customers_email_address, o.customers_street_address, o.delivery_company, o.delivery_name, o.delivery_street_address, o.billing_company, o.billing_name, o.billing_street_address, o.payment_module_code, o.shipping_module_code, o.ip_address ";1320 }1321 if(isset($_GET['orders_num']) && zen_not_null($_GET['orders_num'])){1322 $search_distinct = ' ';1323 $keywords = zen_db_input(zen_db_prepare_input($_GET['orders_num']));1324 $search = " and (o.orders_num like '%" .$keywords ."%') ";1325 $new_table = '';1326 }1327 } // eof: search orders or orders_products1328 $new_fields = ", o.customers_company, o.customers_email_address, o.customers_street_address, o.delivery_company, o.delivery_name, o.delivery_street_address, o.billing_company, o.billing_name, o.billing_street_address, o.payment_module_code, o.shipping_module_code, o.ip_address ";1329 ?>1330 <?php1331 if (isset($_GET['cID'])) {1332 $cID = zen_db_prepare_input($_GET['cID']);1333 //add code1334 if(isset($_GET['start']) || isset($_GET['end'])){1335 if(!empty($_GET['start']) && empty($_GET['end'])){1336 $start_time = strtr($_GET['start'], "/", "-");1337 $order_time = " and o.date_purchased >= '".$start_time."' ";1338 }1339 if(empty($_GET['start']) && !empty($_GET['end'])){1340 $end_time = strtr($_GET['end'], "/", "-");1341 $order_time = " and o.date_purchased <= '".$end_time."' ";1342 }1343 if(!empty($_GET['start']) && !empty($_GET['end'])){1344 $start_time = strtr($_GET['start'], "/", "-");1345 $end_time = strtr($_GET['end'], "/", "-")." 23:59:59";1346 $order_time = " and o.date_purchased >= ' " .$start_time. "' and o.date_purchased <= '".$end_time."' ";1347 }1348 1349 $orders_query_raw = "select o.orders_id, orders_num, o.customers_id, o.customers_name, o.payment_method, o.shipping_method, o.date_purchased, o.last_modified, o.currency, o.currency_value, o.date_purchased, o.order_total as total, s.orders_status_name, ot.text as order_total" .1350 $new_fields . "1351 from (" . TABLE_ORDERS_STATUS . " s, " .1352 TABLE_ORDERS . " o " .1353 $new_table . ")1354 left join " . TABLE_ORDERS_TOTAL . " ot on (o.orders_id = ot.orders_id and ot.class = 'ot_total') " . "1355 where o.customers_id = '" . (int)$cID . "' and o.orders_status = s.orders_status_id ".$order_time." and s.language_id = '" . (int)$_SESSION['languages_id'] . "' order by orders_id DESC";1356 }else{ 1357 $orders_query_raw = "select o.orders_id, orders_num, o.customers_id, o.customers_name, o.payment_method, o.shipping_method, o.date_purchased, o.last_modified, o.currency, o.currency_value, o.order_total as total, s.orders_status_name, ot.text as order_total" .1358 $new_fields . "1359 from (" . TABLE_ORDERS_STATUS . " s, " .1360 TABLE_ORDERS . " o " .1361 $new_table . ")1362 left join " . TABLE_ORDERS_TOTAL . " ot on (o.orders_id = ot.orders_id and ot.class = 'ot_total') " . "1363 where o.customers_id = '" . (int)$cID . "' and o.orders_status = s.orders_status_id and s.language_id = '" . (int)$_SESSION['languages_id'] . "' order by orders_id DESC";1364 }1365 1366 } 1367 elseif ($_GET['status'] != '') {1368 $status = zen_db_prepare_input($_GET['status']);1369 $orders_query_raw = "select o.orders_id, orders_num, o.customers_id, o.customers_name, o.payment_method, o.shipping_method, o.date_purchased, o.last_modified, o.currency, o.currency_value, o.order_total as total, s.orders_status_name, ot.text as order_total" .1370 $new_fields . "1371 from (" . TABLE_ORDERS_STATUS . " s, " .1372 TABLE_ORDERS . " o " .1373 $new_table . ")1374 left join " . TABLE_ORDERS_TOTAL . " ot on (o.orders_id = ot.orders_id and ot.class = 'ot_total') " . "1375 where o.orders_status = s.orders_status_id and s.language_id = '" . (int)$_SESSION['languages_id'] . "' and s.orders_status_id = '" . (int)$status . "' " .1376 $search . " order by o.orders_id DESC";1377 1378 }1379 else {1380 //add code1381 if(isset($_GET['start']) || isset($_GET['end'])){1382 if(!empty($_GET['start']) && empty($_GET['end'])){1383 $start_time = strtr($_GET['start'], "/", "-");1384 $order_time = " and orders_status <> 11 and o.date_purchased >= '".$start_time."' ";1385 }1386 if(empty($_GET['start']) && !empty($_GET['end'])){1387 $end_time = strtr($_GET['end'], "/", "-");1388 $order_time = " and orders_status <> 11 and o.date_purchased <= '".$end_time."' ";1389 }1390 if(!empty($_GET['start']) && !empty($_GET['end'])){1391 $start_time = strtr($_GET['start'], "/", "-");1392 $end_time = strtr($_GET['end'], "/", "-")." 23:59:59";1393 $order_time = " and orders_status <> 11 and o.date_purchased >= ' " .$start_time. "' and o.date_purchased <= '".$end_time."' ";1394 }1395 $orders_query_raw = "select " . $search_distinct . " o.orders_id, orders_num, o.customers_id, o.customers_name, o.payment_method, o.shipping_method, o.date_purchased, o.last_modified, o.currency, o.currency_value, o.date_purchased, o.date_purchased, o.order_total as total, s.orders_status_name, ot.text as order_total" .1396 $new_fields . "1397 from (" . TABLE_ORDERS_STATUS . " s, " .1398 TABLE_ORDERS . " o " .1399 $new_table . ")1400 left join " . TABLE_ORDERS_TOTAL . " ot on (o.orders_id = ot.orders_id and ot.class = 'ot_total') " . "1401 where (o.orders_status = s.orders_status_id and s.language_id = '" . (int)$_SESSION['languages_id'] . "') " .1402 $search . $order_time. " order by o.orders_id DESC";1403 }else{ 1404 $orders_query_raw = "select " . $search_distinct . " o.orders_id, orders_num, o.customers_id, o.customers_name, o.payment_method, o.shipping_method, o.date_purchased, o.last_modified, o.currency, o.currency_value, o.date_purchased, o.order_total as total, s.orders_status_name, ot.text as order_total" .1405 $new_fields . "1406 from (" . TABLE_ORDERS_STATUS . " s, " .1407 TABLE_ORDERS . " o " .1408 $new_table . ")1409 left join " . TABLE_ORDERS_TOTAL . " ot on (o.orders_id = ot.orders_id and ot.class = 'ot_total') " . "1410 where (o.orders_status = s.orders_status_id and s.language_id = '" . (int)$_SESSION['languages_id'] . "') " .1411 $search . " order by o.orders_id DESC";1412 }1413 }1414 1415 // Split Page1416 // reset page when page is unknown1417 if (($_GET['page'] == '' or $_GET['page'] <= 1) and $_GET['oID'] != '') {1418 $check_page = $db->Execute($orders_query_raw);1419 $check_count=1;1420 if ($check_page->RecordCount() > MAX_DISPLAY_SEARCH_RESULTS_ORDERS) {1421 while (!$check_page->EOF) {1422 if ($check_page->fields['orders_id'] == $_GET['oID']) {1423 break;1424 }1425 $check_count++;1426 $check_page->MoveNext();1427 }1428 $_GET['page'] = round((($check_count/MAX_DISPLAY_SEARCH_RESULTS_ORDERS)+(fmod_round($check_count,MAX_DISPLAY_SEARCH_RESULTS_ORDERS) !=0 ? .5 : 0)),0);1429 } else {1430 $_GET['page'] = 1;1431 }1432 }1433 1434 //all order total1435 $orders = $db->Execute($orders_query_raw);1436 $total="";1437 while (!$orders->EOF) {1438 $total+=$orders->fields['total'];1439 $orders->MoveNext();1440 }1441 if(!empty($total)){1442 echo '<div id="total" style="display:none">'.$total.'</div>';1443 }1444 1445 // $orders_query_numrows = '';1446 $orders_split = new splitPageResults($_GET['page'], MAX_DISPLAY_SEARCH_RESULTS_ORDERS, $orders_query_raw, $orders_query_numrows);1447 $orders = $db->Execute($orders_query_raw);1448 echo zen_draw_form('status', FILENAME_ORDERS, '', 'post', '', true);1449 while (!$orders->EOF) {1450 if ((!isset($_GET['oID']) || (isset($_GET['oID']) && ($_GET['oID'] == $orders->fields['orders_id']))) && !isset($oInfo)) {1451 $oInfo = new objectInfo($orders->fields);1452 }1453 1454 if (isset($oInfo) && is_object($oInfo) && ($orders->fields['orders_id'] == $oInfo->orders_id)) {1455 echo ' <tr id="defaultSelected" class="dataTableRowSelected" onmouseover="rowOverEffect(this)" onmouseout="rowOutEffect(this)" onclick="document.location.href=\'' . zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID', 'action')) . 'oID=' . $oInfo->orders_id . '&action=edit', 'NONSSL') . '\'">' . "\n";1456 } else {1457 //echo ' <tr class="dataTableRow" onmouseover="rowOverEffect(this)" onmouseout="rowOutEffect(this)" onclick="document.location.href=\'' . zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID')) . 'oID=' . $orders->fields['orders_id'], 'NONSSL') . '\'">' . "\n";1458 echo ' <tr class="dataTableRow" onmouseover="rowOverEffect(this)" onmouseout="rowOutEffect(this)">' . "\n";1459 }1460 1461 $show_difference = '';1462 if (($orders->fields['delivery_name'] != $orders->fields['billing_name'] and $orders->fields['delivery_name'] != '')) {1463 $show_difference = zen_image(DIR_WS_IMAGES . 'icon_status_red.gif', TEXT_BILLING_SHIPPING_MISMATCH, 10, 10) . ' ';1464 }1465 if (($orders->fields['delivery_street_address'] != $orders->fields['billing_street_address'] and $orders->fields['delivery_street_address'] != '')) {1466 $show_difference = zen_image(DIR_WS_IMAGES . 'icon_status_red.gif', TEXT_BILLING_SHIPPING_MISMATCH, 10, 10) . ' ';1467 }1468 $show_payment_type = $orders->fields['payment_module_code'] . '<br />' . $orders->fields['shipping_module_code'];1469 ?>1470 <?php1471 if(!empty($_GET['cID']) || !empty($_GET['search']) || !empty($_GET['orders_num']) || !empty($_GET['search_orders_products'])){1472 1473 $attributes = $db->Execute("select products_options_id1474 from " . TABLE_ORDERS_PRODUCTS_ATTRIBUTES . "1475 where orders_id = '" . $orders->fields['orders_id'] . "' and products_options_id ='5'");1476 1477 $order_products = $db->Execute("select products_total_quantity1478 from ". TABLE_ORDERS_PRODUCTS ."1479 where orders_id=" .$orders->fields['orders_id'] . " AND products_total_quantity < 0 ORDER BY products_total_quantity ");1480 1481 }1482 else{1483 $attributes = $db->Execute("select products_options_id1484 from " . TABLE_ORDERS_PRODUCTS_ATTRIBUTES . "1485 where orders_id = '" . $orders->fields['orders_id'] . "' and products_options_id ='5'");1486 if(!empty($attributes->fields)){1487 $orders->MoveNext();1488 continue;1489 }1490 1491 $order_products = $db->Execute("select products_total_quantity1492 from ". TABLE_ORDERS_PRODUCTS ."1493 where orders_id=" .$orders->fields['orders_id'] . " AND products_total_quantity < 0 ORDER BY products_total_quantity ");1494 if($order_products->fields) {1495 $orders->MoveNext();1496 continue;1497 }1498 }1499 1500 $onclick = 'onclick="document.location.href=\'' . zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID')) . 'oID=' . $orders->fields['orders_id'], 'NONSSL') . '\'"';1501 1502 if(empty($show_difference)) $p='    ';1503 else $p='';1504 ?>1505 <td class="dataTableContent" align="left" <?php echo $onclick; ?> ><?php echo $show_difference.$p.$orders->fields['orders_num']; ?></td>1506 <td class="dataTableContent" align="left" width="50" <?php echo $onclick; ?> ><?php echo $show_payment_type; ?></td>1507 <td class="dataTableContent" <?php echo $onclick; ?> ><?php echo '<a href="' . zen_href_link(FILENAME_CUSTOMERS, 'cID=' . $orders->fields['customers_id'], 'NONSSL') . '">' . zen_image(DIR_WS_ICONS . 'preview.gif', ICON_PREVIEW . ' ' . TABLE_HEADING_CUSTOMERS) . '</a> ' . $orders->fields['customers_name'] . ($orders->fields['customers_company'] != '' ? '<br />' . $orders->fields['customers_company'] : ''); ?></td>1508 <td class="dataTableContent" align="right" <?php echo $onclick; ?> ><?php echo strip_tags($orders->fields['order_total']); ?></td>1509 <td class="dataTableContent" align="center" <?php echo $onclick; ?> ><?php echo zen_datetime_short($orders->fields['date_purchased']); ?></td>1510 <td class="dataTableContent" align="right" <?php echo $onclick; ?> ><?php echo $orders->fields['orders_status_name']; ?></td>1511 <td class="dataTableContent" align="center" <?php echo $onclick; ?> ><?php echo (zen_get_orders_comments($orders->fields['orders_id']) == '' ? '' : zen_image(DIR_WS_IMAGES . 'icon_yellow_on.gif', TEXT_COMMENTS_YES, 16, 16)); ?><?php echo (!empty($attributes->fields) ? zen_image(DIR_WS_IMAGES . 'icon_green_on.gif', IMAGE_ICON_STATUS_ON):''); ?><?php echo (!empty($order_products->fields) ? zen_image(DIR_WS_IMAGES . 'icon_red_on.gif', ICON_EDIT) : ""); ?></td>1512 <td class="dataTableContent" align="center"><input type="checkbox" name="order_id[]" value="<?php echo $orders->fields['orders_id']; ?>"></td>1513 <td class="dataTableContent" align="right" <?php echo $onclick; ?> ><?php echo '<a href="' . zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID', 'action')) . 'oID=' . $orders->fields['orders_id'] . '&action=edit', 'NONSSL') . '">' . zen_image(DIR_WS_IMAGES . 'icon_edit.gif', ICON_EDIT) . '</a>'; ?><?php if (isset($oInfo) && is_object($oInfo) && ($orders->fields['orders_id'] == $oInfo->orders_id)) { echo zen_image(DIR_WS_IMAGES . 'icon_arrow_right.gif', ''); } else { echo '<a href="' . zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID')) . 'oID=' . $orders->fields['orders_id'], 'NONSSL') . '">' . zen_image(DIR_WS_IMAGES . 'icon_info.gif', IMAGE_ICON_INFO) . '</a>'; } ?></td>1514 </tr>1515 <?php1516 $orders->MoveNext();1517 }1518 ?>1519 <tr>1520 <td class="smallText" align="right" colspan="8"><input type="submit" value="Export Orders"></form></td>1521 </tr>1522 <tr>1523 <td colspan="5"><table border="0" width="100%" cellspacing="0" cellpadding="2">1524 <tr>1525 <td class="smallText" valign="top"><?php echo $orders_split->display_count($orders_query_numrows, MAX_DISPLAY_SEARCH_RESULTS_ORDERS, $_GET['page'], TEXT_DISPLAY_NUMBER_OF_ORDERS); ?></td>1526 <td class="smallText" align="right"><?php echo $orders_split->display_links($orders_query_numrows, MAX_DISPLAY_SEARCH_RESULTS_ORDERS, MAX_DISPLAY_PAGE_LINKS, $_GET['page'], zen_get_all_get_params(array('page', 'oID', 'action'))); ?></td>1527 </tr>1528 <?php1529 if (isset($_GET['search']) && zen_not_null($_GET['search'])) {1530 ?>1531 <tr>1532 <td class="smallText" align="right" colspan="2">1533 <?php1534 echo '<a href="' . zen_href_link(FILENAME_ORDERS, '', 'NONSSL') . '">' . zen_image_button('button_reset.gif', IMAGE_RESET) . '</a>';1535 if (isset($_GET['search']) && zen_not_null($_GET['search'])) {1536 $keywords = zen_db_input(zen_db_prepare_input($_GET['search']));1537 echo '<br/ >' . TEXT_INFO_SEARCH_DETAIL_FILTER . $keywords;1538 }1539 ?>1540 </td>1541 </tr>1542 <?php1543 }1544 ?>1545 </table></td>1546 </tr>1547 </table></td>1548 <?php1549 $heading = array();1550 $contents = array();1551 1552 switch ($action) {1553 case 'delete':1554 $heading[] = array('text' => '<strong>' . TEXT_INFO_HEADING_DELETE_ORDER . '</strong>');1555 1556 $contents = array('form' => zen_draw_form('orders', FILENAME_ORDERS, zen_get_all_get_params(array('oID', 'action')) . 'oID=' . $oInfo->orders_id . '&action=deleteconfirm', 'post', '', true));1557 // $contents[] = array('text' => TEXT_INFO_DELETE_INTRO . '<br /><br /><strong>' . $cInfo->customers_firstname . ' ' . $cInfo->customers_lastname . '</strong>');1558 $contents[] = array('text' => TEXT_INFO_DELETE_INTRO . '<br /><br /><strong>' . ENTRY_ORDER_ID . $oInfo->orders_num . '<br />' . $oInfo->order_total . '<br />' . $oInfo->customers_name . ($oInfo->customers_company != '' ? '<br />' . $oInfo->customers_company : '') . '</strong>');1559 $contents[] = array('text' => '<br />' . zen_draw_checkbox_field('restock') . ' ' . TEXT_INFO_RESTOCK_PRODUCT_QUANTITY);1560 $contents[] = array('align' => 'center', 'text' => '<br />' . zen_image_submit('button_delete.gif', IMAGE_DELETE) . ' <a href="' . zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID', 'action')) . 'oID=' . $oInfo->orders_id, 'NONSSL') . '">' . zen_image_button('button_cancel.gif', IMAGE_CANCEL) . '</a>');1561 break;1562 default:1563 if (isset($oInfo) && is_object($oInfo)) {1564 $heading[] = array('text' => '<strong>[' . $oInfo->orders_id . '] ' . zen_datetime_short($oInfo->date_purchased) . '</strong>');1565 1566 $contents[] = array('align' => 'center', 'text' => '<a href="' . zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID', 'action')) . 'oID=' . $oInfo->orders_id . '&action=edit', 'NONSSL') . '">' . zen_image_button('button_edit.gif', IMAGE_EDIT) . '</a> <a href="' . zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID', 'action')) . 'oID=' . $oInfo->orders_id . '&action=delete', 'NONSSL') . '">' . zen_image_button('button_delete.gif', IMAGE_DELETE) . '</a>');1567 $contents[] = array('align' => 'center', 'text' => '<a href="' . zen_href_link(FILENAME_ORDERS_INVOICE, 'oID=' . $oInfo->orders_id) . '" TARGET="_blank">' . zen_image_button('button_invoice.gif', IMAGE_ORDERS_INVOICE) . '</a> <a href="' . zen_href_link(FILENAME_ORDERS_PACKINGSLIP, 'oID=' . $oInfo->orders_id) . '" TARGET="_blank">' . zen_image_button('button_packingslip.gif', IMAGE_ORDERS_PACKINGSLIP) . '</a>');1568 $contents[] = array('align' => 'center', 'text' => '<a href="' . zen_href_link(FILENAME_ORDERS, 'cID=' . $oInfo->customers_id) . '" ">' . zen_image_button('button_allroder.gif', "All order") . '</a>');1569 $contents[] = array('text' => '<br />' . TEXT_DATE_ORDER_CREATED . ' ' . zen_date_short($oInfo->date_purchased));1570 $contents[] = array('text' => '<br />' . $oInfo->customers_email_address);1571 $contents[] = array('text' => TEXT_INFO_IP_ADDRESS . ' ' . $oInfo->ip_address);1572 if (zen_not_null($oInfo->last_modified)) $contents[] = array('text' => TEXT_DATE_ORDER_LAST_MODIFIED . ' ' . zen_date_short($oInfo->last_modified));1573 $contents[] = array('text' => '<br />' . TEXT_INFO_PAYMENT_METHOD . ' ' . $oInfo->payment_method);1574 $contents[] = array('text' => '<br />' . ENTRY_SHIPPING . ' ' . $oInfo->shipping_method);1575 1576 // check if order has open gv1577 $gv_check = $db->Execute("select order_id, unique_id1578 from " . TABLE_COUPON_GV_QUEUE ."1579 where order_id = '" . $oInfo->orders_id . "' and release_flag='N' limit 1");1580 if ($gv_check->RecordCount() > 0) {1581 $goto_gv = '<a href="' . zen_href_link(FILENAME_GV_QUEUE, 'order=' . $oInfo->orders_id) . '">' . zen_image_button('button_gift_queue.gif',IMAGE_GIFT_QUEUE) . '</a>';1582 $contents[] = array('text' => '<br />' . zen_image(DIR_WS_IMAGES . 'pixel_black.gif','','100%','3'));1583 $contents[] = array('align' => 'center', 'text' => $goto_gv);1584 }1585 }1586 1587 // indicate if comments exist1588 $orders_history_query = $db->Execute("select orders_status_id, date_added, customer_notified, comments from " . TABLE_ORDERS_STATUS_HISTORY . " where orders_id = '" . $oInfo->orders_id . "' and comments !='" . "'" );1589 if ($orders_history_query->RecordCount() > 0) {1590 $contents[] = array('align' => 'left', 'text' => '<br />' . TABLE_HEADING_COMMENTS);1591 }1592 1593 $contents[] = array('text' => '<br />' . zen_image(DIR_WS_IMAGES . 'pixel_black.gif','','100%','3'));1594 $order = new order($oInfo->orders_id);1595 $contents[] = array('text' => 'Products Ordered: ' . sizeof($order->products) );1596 for ($i=0; $i<sizeof($order->products); $i++) {1597 $contents[] = array('text' => $order->products[$i]['qty'] . ' x ' . $order->products[$i]['name']);1598 1599 if (sizeof($order->products[$i]['attributes']) > 0) {1600 for ($j=0; $j<sizeof($order->products[$i]['attributes']); $j++) {1601 $contents[] = array('text' => ' <i> - ' . $order->products[$i]['attributes'][$j]['option'] . ': ' . nl2br(zen_output_string_protected($order->products[$i]['attributes'][$j]['value'])) . '</i></nobr>' );1602 }1603 }1604 if ($i > MAX_DISPLAY_RESULTS_ORDERS_DETAILS_LISTING and MAX_DISPLAY_RESULTS_ORDERS_DETAILS_LISTING != 0) {1605 $contents[] = array('align' => 'left', 'text' => TEXT_MORE);1606 break;1607 }1608 }1609 1610 if (sizeof($order->products) > 0) {1611 $contents[] = array('align' => 'center', 'text' => '<a href="' . zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(array('oID', 'action')) . 'oID=' . $oInfo->orders_id . '&action=edit', 'NONSSL') . '">' . zen_image_button('button_edit.gif', IMAGE_EDIT) . '</a>');1612 }1613 break;1614 }1615 1616 if ( (zen_not_null($heading)) && (zen_not_null($contents)) ) {1617 echo ' <td width="25%" valign="top">' . "\n";1618 1619 $box = new box;1620 echo $box->infoBox($heading, $contents);1621 1622 echo ' </td>' . "\n";1623 }1624 ?>1625 </tr>1626 </table></td>1627 </tr>1628 <?php1629 }1630 ?>1631 </table></td>1632 <!-- body_text_eof //-->1633 </tr>1634 </table>1635 <!-- body_eof //-->1636 1637 <!-- footer //-->1638 <div class="footer-area">1639 <?php require(DIR_WS_INCLUDES . 'footer.php'); ?>1640 </div>1641 <!-- footer_eof //-->1642 <br />1643 </body>1644 </html>1645 <?php require(DIR_WS_INCLUDES . 'application_bottom.php'); ?>
10. 修改付款后,给客户发送邮件的问题。注销 includes/modules/checkout_process.php 文件的 $order->send_order_email($insert_id, 2); 这是生成订单的时候发送订单邮件,不是付款成功时发送邮件,所以需要注销掉,当然你也可以自己写邮件,当订单生成后,可以发送提示邮件给客户。付款成功后发送邮件功能调用在 ipn_main_handler.php 文件中。发送邮件函数是在 includes/classes/order.php 文件的 send_order_email($zf_insert_id, $zf_mode) 函数,代码修改如下:
1 function send_order_email($zf_insert_id, $zf_mode) { 2 global $currencies, $order_totals; 3 if( !empty($this->totals) ){ 4 $order_totals = $this->totals; 5 } 6 if ($this->email_low_stock != '' and SEND_LOWSTOCK_EMAIL=='1') { 7 // send an email 8 $email_low_stock = SEND_EXTRA_LOW_STOCK_EMAIL_TITLE . "\n\n" . $this->email_low_stock; 9 zen_mail('', SEND_EXTRA_LOW_STOCK_EMAILS_TO, EMAIL_TEXT_SUBJECT_LOWSTOCK, $email_low_stock, STORE_OWNER, EMAIL_FROM, array('EMAIL_MESSAGE_HTML' => nl2br($email_low_stock)),'low_stock'); 10 } 11 12 // lets start with the email confirmation 13 // make an array to store the html version 14 $html_msg=array(); 15 16 //intro area 17 $email_order = EMAIL_TEXT_HEADER . EMAIL_TEXT_FROM . STORE_NAME . "\n\n" . 18 $this->customer['firstname'] . ' ' . $this->customer['lastname'] . "\n\n" . 19 EMAIL_THANKS_FOR_SHOPPING . "\n" . EMAIL_DETAILS_FOLLOW . "\n" . 20 EMAIL_SEPARATOR . "\n" . 21 EMAIL_TEXT_ORDER_NUMBER . ' ' . zen_get_order_orders_number($zf_insert_id) . "\n" . 22 EMAIL_TEXT_DATE_ORDERED . ' ' . strftime(DATE_FORMAT_LONG) . "\n" . 23 EMAIL_TEXT_INVOICE_URL . ' ' . zen_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id=' . $zf_insert_id, 'SSL', false) . "\n\n"; 24 $html_msg['EMAIL_TEXT_HEADER'] = EMAIL_TEXT_HEADER; 25 $html_msg['EMAIL_TEXT_FROM'] = EMAIL_TEXT_FROM; 26 $html_msg['INTRO_STORE_NAME'] = STORE_NAME; 27 $html_msg['EMAIL_THANKS_FOR_SHOPPING'] = EMAIL_THANKS_FOR_SHOPPING; 28 $html_msg['EMAIL_DETAILS_FOLLOW'] = EMAIL_DETAILS_FOLLOW; 29 $html_msg['INTRO_ORDER_NUM_TITLE'] = EMAIL_TEXT_ORDER_NUMBER; 30 $html_msg['INTRO_ORDER_NUMBER'] = zen_get_order_orders_number($zf_insert_id); 31 $html_msg['INTRO_DATE_TITLE'] = EMAIL_TEXT_DATE_ORDERED; 32 $html_msg['INTRO_DATE_ORDERED'] = strftime(DATE_FORMAT_LONG); 33 $html_msg['INTRO_URL_TEXT'] = EMAIL_TEXT_INVOICE_URL_CLICK; 34 $html_msg['INTRO_URL_VALUE'] = zen_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id=' . $zf_insert_id, 'SSL', false); 35 36 //comments area 37 if ($this->info['comments']) { 38 $email_order .= zen_db_output($this->info['comments']) . "\n\n"; 39 $html_msg['ORDER_COMMENTS'] = nl2br(zen_db_output($this->info['comments'])); 40 } else { 41 $html_msg['ORDER_COMMENTS'] = ''; 42 } 43 44 //products area 45 $email_order .= EMAIL_TEXT_PRODUCTS . "\n" . 46 EMAIL_SEPARATOR . "\n" . 47 $this->products_ordered . 48 EMAIL_SEPARATOR . "\n"; 49 $html_msg['PRODUCTS_TITLE'] = EMAIL_TEXT_PRODUCTS; 50 $html_msg['PRODUCTS_DETAIL']='<table class="product-details" border="0" width="100%" cellspacing="0" cellpadding="2">' . $this->products_ordered_html . '</table>'; 51 52 //order totals area 53 $html_ot .= '<td class="order-totals-text" align="right" width="100%">' . ' ' . '</td> ' . "\n" . '<td class="order-totals-num" align="right" nowrap="nowrap">' . '---------' .'</td> </tr>' . "\n" . '<tr>'; 54 for ($i=0, $n=sizeof($order_totals); $i<$n; $i++) { 55 $email_order .= strip_tags($order_totals[$i]['title']) . ' ' . strip_tags($order_totals[$i]['text']) . "\n"; 56 $html_ot .= '<td class="order-totals-text" align="right" width="100%">' . $order_totals[$i]['title'] . '</td> ' . "\n" . '<td class="order-totals-num" align="right" nowrap="nowrap">' .($order_totals[$i]['text']) .'</td> </tr>' . "\n" . '<tr>'; 57 } 58 $html_msg['ORDER_TOTALS'] = '<table border="0" width="100%" cellspacing="0" cellpadding="2"> ' . $html_ot . ' </table>'; 59 60 //addresses area: Delivery 61 $html_msg['HEADING_ADDRESS_INFORMATION']= HEADING_ADDRESS_INFORMATION; 62 $html_msg['ADDRESS_DELIVERY_TITLE'] = EMAIL_TEXT_DELIVERY_ADDRESS; 63 if(empty($this->delivery)){ 64 $html_msg['ADDRESS_DELIVERY_DETAIL'] = ($this->content_type != 'virtual') ? zen_address_label($_SESSION['customer_id'], $_SESSION['sendto'], true, '', "<br />") : 'n/a'; 65 }else{ 66 $delivery = $this->delivery; 67 $html_msg['ADDRESS_DELIVERY_DETAIL'] = $delivery['company'] . "<br />" . $delivery['name'] . "<br />" . $delivery['suburb'] . " " . $delivery['street_address'] . "<br />" . $delivery['city'] . ", " . $delivery['postcode'] . "<br />" . $delivery['state'] . ", " . $delivery['country']; 68 } 69 $html_msg['SHIPPING_METHOD_TITLE'] = HEADING_SHIPPING_METHOD; 70 $html_msg['SHIPPING_METHOD_DETAIL'] = (zen_not_null($this->info['shipping_method'])) ? $this->info['shipping_method'] : 'n/a'; 71 72 if ($this->content_type != 'virtual') { 73 $email_order .= "\n" . EMAIL_TEXT_DELIVERY_ADDRESS . "\n" . 74 EMAIL_SEPARATOR . "\n" . 75 zen_address_label($_SESSION['customer_id'], $_SESSION['sendto'], 0, '', "\n") . "\n"; 76 } 77 78 //addresses area: Billing 79 $email_order .= "\n" . EMAIL_TEXT_BILLING_ADDRESS . "\n" . 80 EMAIL_SEPARATOR . "\n" . 81 zen_address_label($_SESSION['customer_id'], $_SESSION['billto'], 0, '', "\n") . "\n\n"; 82 $html_msg['ADDRESS_BILLING_TITLE'] = EMAIL_TEXT_BILLING_ADDRESS; 83 if(empty($this->billing)){ 84 $html_msg['ADDRESS_BILLING_DETAIL'] = zen_address_label($_SESSION['customer_id'], $_SESSION['billto'], true, '', "<br />"); 85 }else{ 86 $billing = $this->billing; 87 $html_msg['ADDRESS_BILLING_DETAIL'] = $billing['company'] . "<br />" . $billing['name'] . "<br />" . $billing['suburb'] . " " . $billing['street_address'] . "<br />" . $billing['city'] . ", " . $billing['postcode'] . "<br />" . $billing['state'] . ", " . $billing['country']; 88 } 89 90 if (is_object($GLOBALS[$_SESSION['payment']])) { 91 $cc_num_display = (isset($this->info['cc_number']) && $this->info['cc_number'] != '') ? /*substr($this->info['cc_number'], 0, 4) . */ str_repeat('X', (strlen($this->info['cc_number']) - 8)) . substr($this->info['cc_number'], -4) . "\n\n" : ''; 92 $email_order .= EMAIL_TEXT_PAYMENT_METHOD . "\n" . 93 EMAIL_SEPARATOR . "\n"; 94 $payment_class = $_SESSION['payment']; 95 $email_order .= $GLOBALS[$payment_class]->title . "\n\n"; 96 $email_order .= (isset($this->info['cc_type']) && $this->info['cc_type'] != '') ? $this->info['cc_type'] . ' ' . $cc_num_display . "\n\n" : ''; 97 $email_order .= ($GLOBALS[$payment_class]->email_footer) ? $GLOBALS[$payment_class]->email_footer . "\n\n" : ''; 98 } else { 99 $email_order .= EMAIL_TEXT_PAYMENT_METHOD . "\n" .100 EMAIL_SEPARATOR . "\n";101 $email_order .= PAYMENT_METHOD_GV . "\n\n";102 }103 $html_msg['PAYMENT_METHOD_TITLE'] = EMAIL_TEXT_PAYMENT_METHOD;104 $html_msg['PAYMENT_METHOD_DETAIL'] = (is_object($GLOBALS[$_SESSION['payment']]) ? $GLOBALS[$payment_class]->title : PAYMENT_METHOD_GV );105 $html_msg['PAYMENT_METHOD_FOOTER'] = (is_object($GLOBALS[$_SESSION['payment']]) && $GLOBALS[$payment_class]->email_footer != '') ? nl2br($GLOBALS[$payment_class]->email_footer) : (isset($this->info['cc_type']) && $this->info['cc_type'] != '' ? $this->info['cc_type'] . ' ' . $cc_num_display . "\n\n" : '');106 107 // include disclaimer108 if (defined('EMAIL_DISCLAIMER') && EMAIL_DISCLAIMER != '') $email_order .= "\n-----\n" . sprintf(EMAIL_DISCLAIMER, STORE_OWNER_EMAIL_ADDRESS) . "\n\n";109 // include copyright110 if (defined('EMAIL_FOOTER_COPYRIGHT')) $email_order .= "\n-----\n" . EMAIL_FOOTER_COPYRIGHT . "\n\n";111 112 while (strstr($email_order, ' ')) $email_order = str_replace(' ', ' ', $email_order);113 114 if(!empty($this->customer['firstname'])){115 $html_msg['EMAIL_FIRST_NAME'] = $this->customer['firstname'];116 $html_msg['EMAIL_LAST_NAME'] = $this->customer['lastname'];117 }elseif($this->customer['name']){118 $html_msg['EMAIL_FIRST_NAME'] = $this->customer['name'];119 $html_msg['EMAIL_LAST_NAME'] = '';120 }121 // $html_msg['EMAIL_TEXT_HEADER'] = EMAIL_TEXT_HEADER;122 $html_msg['EXTRA_INFO'] = '';123 $this->notify('NOTIFY_ORDER_INVOICE_CONTENT_READY_TO_SEND', array('zf_insert_id' => $zf_insert_id, 'text_email' => $email_order, 'html_email' => $html_msg));124 zen_mail($this->customer['firstname'] . ' ' . $this->customer['lastname'], $this->customer['email_address'], EMAIL_TEXT_SUBJECT . EMAIL_ORDER_NUMBER_SUBJECT . zen_get_order_orders_number($zf_insert_id), $email_order, STORE_NAME, EMAIL_FROM, $html_msg, 'checkout', $this->attachArray);125 126 // send additional emails127 if (SEND_EXTRA_ORDER_EMAILS_TO != '') {128 $extra_info=email_collect_extra_info('','', $this->customer['firstname'] . ' ' . $this->customer['lastname'], $this->customer['email_address'], $this->customer['telephone']);129 $html_msg['EXTRA_INFO'] = $extra_info['HTML'];130 131 // include authcode and transaction id in admin-copy of email132 if ($GLOBALS[$_SESSION['payment']]->auth_code || $GLOBALS[$_SESSION['payment']]->transaction_id) {133 $pmt_details = ($GLOBALS[$_SESSION['payment']]->auth_code != '' ? 'AuthCode: ' . $GLOBALS[$_SESSION['payment']]->auth_code . ' ' : '') . ($GLOBALS[$_SESSION['payment']]->transaction_id != '' ? 'TransID: ' . $GLOBALS[$_SESSION['payment']]->transaction_id : '') . "\n\n";134 $email_order = $pmt_details . $email_order;135 $html_msg['EMAIL_TEXT_HEADER'] = nl2br($pmt_details) . $html_msg['EMAIL_TEXT_HEADER'];136 }137 138 zen_mail('', SEND_EXTRA_ORDER_EMAILS_TO, SEND_EXTRA_NEW_ORDERS_EMAILS_TO_SUBJECT . ' ' . EMAIL_TEXT_SUBJECT . EMAIL_ORDER_NUMBER_SUBJECT . zen_get_order_orders_number($zf_insert_id),139 $email_order . $extra_info['TEXT'], STORE_NAME, EMAIL_FROM, $html_msg, 'checkout_extra', $this->attachArray);140 }141 $this->notify('NOTIFY_ORDER_AFTER_SEND_ORDER_EMAIL', array($zf_insert_id, $email_order, $extra_info, $html_msg));142 }143 144 }
11. 未付款订单不需要永久保存,我们规定未付款订单超过三天自动删除,而且未付款订单在生成半小时后,或距离删除时间还有12小时的时候,都会自动发送一封邮件给客户,提醒他及时付款,以及订单将被删除。现在需要在订单表 orders 中增加 payment_reminder, delete_reminder两个字段,类型为TINYINT,用0或1表示发送和未发送,在 includes/init_includes 中增加一个文件,或者在 includes/init_includes 目录下的某个文件中添加代码都可以。我是在 init_special_funcs.php 这个文件末尾增加代码,因为当网站被点击一次,这些代码将会被执行一次,其实完全没必要,所以使用了 if(rand(1,10) == 5) 这个方法来限制代码执行次数,如果你的PV量越大,随机数设置就要相应的大些即可。代码如下:
1 if(rand(1,10) == 5){ 2 $unpaid_order = "select orders_id, orders_num, customers_name, customers_email_address, payment_reminder, delete_reminder, date_purchased from " . TABLE_ORDERS . " where orders_status = 11"; 3 $unpaid_order = $db->Execute($unpaid_order); 4 while (!$unpaid_order->EOF) { 5 $now=date("Y-m-d H:i:s"); 6 $delete_order = date("Y-m-d H:i:s",strtotime("+3days",strtotime($unpaid_order->fields['date_purchased']))); 7 $payment_reminder = date("Y-m-d H:i:s",strtotime("+5Minute",strtotime($unpaid_order->fields['date_purchased']))); 8 $delete_reminder = date("Y-m-d H:i:s",strtotime("+60Hour",strtotime($unpaid_order->fields['date_purchased']))); 9 10 if($now > $delete_order){11 $db->Execute("delete from " . TABLE_ORDERS . " where orders_id = '" . (int)$unpaid_order->fields['orders_id'] . "'");12 $db->Execute("delete from " . TABLE_ORDERS_PRODUCTS . "13 where orders_id = '" . (int)$unpaid_order->fields['orders_id'] . "'");14 15 $db->Execute("delete from " . TABLE_ORDERS_PRODUCTS_ATTRIBUTES . "16 where orders_id = '" . (int)$unpaid_order->fields['orders_id'] . "'");17 18 $db->Execute("delete from " . TABLE_ORDERS_PRODUCTS_DOWNLOAD . "19 where orders_id = '" . (int)$unpaid_order->fields['orders_id'] . "'");20 21 $db->Execute("delete from " . TABLE_ORDERS_STATUS_HISTORY . "22 where orders_id = '" . (int)$unpaid_order->fields['orders_id'] . "'");23 24 $db->Execute("delete from " . TABLE_ORDERS_TOTAL . "25 where orders_id = '" . (int)$unpaid_order->fields['orders_id'] . "'");26 }27 28 if($unpaid_order->fields['payment_reminder'] == 0 && $now > $payment_reminder){29 $to_name = $unpaid_order->fields['customers_name'];30 $to_address = $unpaid_order->fields['customers_email_address'];31 $email_subject="Your Pending Order No: " . $unpaid_order->fields['orders_num'];32 $email_text='<p>Dear '.$unpaid_order->fields['customers_name'].',<br /></p>33 <p>Thanks for choosing Geeetech, your order has been generated, however, we are still waiting for your payment, please finish the payment timely.</p>34 <p>We will keep your order for 3 days, during that time, you can continue to pay at my order on www.geeetech.com.</p>35 <p>If you do not pay in 3 days, your order will be deleted automatically, If there is any problem during the payment, please let us know as soon as possible.</p>36 <p>37 <a href="'.zen_href_link(FILENAME_ACCOUNT_HISTORY).'" style="height:30px; line-height:30px; border:1px #000 solid; display:block; width:100px; text-align:center; background:#ccc;">Check My Order</a>38 39 <a href="'.zen_href_link(FILENAME_ACCOUNT_HISTORY_INFO,"order_id=".$unpaid_order->fields["orders_id"]).'" style="height:30px; line-height:30px; border:1px #000 solid; display:block; width:100px; text-align:center; background:#ccc;">Pay Now</a>40 </p>41 ';42 $block=array("EMAIL_MESSAGE_HTML" => $email_text);43 zen_mail($to_name, $to_address, $email_subject, $email_text, STORE_NAME, EMAIL_FROM, $block);44 $db->Execute("update " . TABLE_ORDERS . "45 set payment_reminder = 1 46 where orders_id = '" . (int)$unpaid_order->fields['orders_id'] . "'");47 }48 49 if($unpaid_order->fields['delete_reminder'] == 0 && $now > $delete_reminder){50 $to_name = $unpaid_order->fields['customers_name'];51 $to_address = $unpaid_order->fields['customers_email_address'];52 $email_subject="Your Pending Order No: " . $unpaid_order->fields['orders_num'];53 $email_text='<p>Dear '.$unpaid_order->fields['customers_name'].',<br /></p>54 <p>You have placed an order at Geeetech on ' . strftime(DATE_TIME_FORMAT,strtotime($unpaid_order->fields['date_purchased'])) .' [-0600GMT], however, we are still waiting for your payment. </p>55 <p>Your order will be deleted automatically in 12 hours, please finish the payment timely. If there is any problem during the payment, please let us know as soon as possible. </p>56 </p>57 <a href="'.zen_href_link(FILENAME_ACCOUNT_HISTORY).'" style="height:30px; line-height:30px; border:1px #000 solid; display:block; width:100px; text-align:center; background:#ccc;">Check My Order</a>58 59 <a href="'.zen_href_link(FILENAME_ACCOUNT_HISTORY_INFO,"order_id=".$unpaid_order->fields["orders_id"]).'" style="height:30px; line-height:30px; border:1px #000 solid; display:block; width:100px; text-align:center; background:#ccc;">Pay Now</a>60 </p>61 ';62 $block=array("EMAIL_MESSAGE_HTML" => $email_text);63 zen_mail($to_name, $to_address, $email_subject, $email_text, STORE_NAME, EMAIL_FROM, $block);64 $db->Execute("update " . TABLE_ORDERS . "65 set delete_reminder = 166 where orders_id = '" . (int)$unpaid_order->fields['orders_id'] . "'");67 }68 69 $unpaid_order->MoveNext();70 }71 72 $special_count = "select specials_id, specials_date_available from " . TABLE_SPECIALS . " where specials_date_available > '" . date('Y-m-d') . "' and counter > 0";73 $special_count = $db->Execute($special_count);74 while(!$special_count->EOF){75 $update_specials = "update " . TABLE_SPECIALS . " set counter = 0 where specials_id = ". $special_count->fields['specials_id'];76 $db->Execute($update_specials);77 $special_count->MoveNext();78 }79 }
经过上面的修改,我们的流程如下:
1. 购物车(shopping cart)
2. [货运方式(delivery method)]
3. 支付方式(payment method)
4. 订单确认(confirmation)
5. 订单处理(checkout process)
6. 下单成功(checkout success)
7. [第三方网站支付]
因为从订单确认到订单处理,都是在我们自己的网站完成的,并且进入支付网站之前,订单已经存在了,这样就不会出现漏单的情况了。
在测试过程中,我们不可能直接使用自己的Paypal去测试订单,这样手续费都要扣很大部分,Paypal为了给IT人员测试接口,开发了虚拟Paypal帐号,可以通过Paypal虚拟帐号测试功能。具体申请使用教程链接如下:http://blog.sina.com.cn/s/blog_7285f5d30101fq05.html
总结:
以上修改,完成了网站四个新功能。
1. 快速支付功能
2. 先生成订单后付款功能
3. 按指定时间自动删除未付款订单以及自动发送提示邮件功能
4. 实现和淘宝一样,后台修改未付款订单价格功能
最后:可能还有些代码细节没有一一说到,但是上传的这些代码里面都有体现,需要自己仔细看。有什么问题可以给我留言!
- 1楼miketwais
- zencart 代码看起来怕怕的这代码。