现在的位置: 首页 > 综合 > 正文

修改zen-cart下单和付款流程以防止漏单

2013年07月15日 ⁄ 综合 ⁄ 共 10978字 ⁄ 字号 评论关闭

   zen-cart进入第三方支付网站后,如果不能正常返回,则会造成客户已付款但后台却无订单数据的尴尬局面。本文就针对该问题给出一种解决方案,希望对被同样问题困扰的同行有所帮助。

   用过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页面,这样造成的后果是很严重的,因为订单不能被正常的创建。

   基于上述的分析, 我们希望稍微地改变一下流程,即在支付之前订单已经创建好了,这样就算在支付时不能从第三方支付网站跳转回来,我们也不会存在用户付款成功却在后台没有订单的情况了。经过修改后的蓝图基本是下面这样的:

   1. 在checkour_confirmation页面确认订单后,都会直接proccess,并且进入checkour_success页面,可以在这里进入付款页面。如下图所示:

    

   2. 如果当时客户没能付款,也可进入自己的后台对历史订单进行付款。如下图所示:

    

   下面我们就来看看如何一步一步来实现上述的功能。

   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原有的代码,我们将paypal.php文件拷贝一个副本出来,并命名为paypalsimple.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按钮做准备的。

paypalsimple.php
<?php
/**
 * @package paypalsimple payment module
 * @copyright Copyright 2003-2006 Zen Cart Development Team
 * @copyright Portions Copyright 2003 osCommerce
 * @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0
 * @version $Id: paypalsimple.php 4960 2009-12-29 11:46:46Z gary $
 
*/

// ensure dependencies are loaded
  include_once((IS_ADMIN_FLAG === true ? DIR_FS_CATALOG_MODULES : DIR_WS_MODULES) . 'payment/paypal/paypal_functions.php');
  
  
class paypalsimple {
    
var $code, $title, $description, $enabled;

// class constructor
    function paypalsimple() {
      
global $order;

      $this->code = 'paypalsimple';
      
$this->title = MODULE_PAYMENT_PAYPAL_SIMPLE_TEXT_TITLE;
      
      
if(IS_ADMIN_FLAG === true){
           
$this->title = MODULE_PAYMENT_PAYPAL_SIMPLE_TEXT_ADMIN_TITLE;
      }
            
      
$this->description = MODULE_PAYMENT_PAYPAL_SIMPLE_TEXT_DESCRIPTION;
      
$this->sort_order = MODULE_PAYMENT_PAYPAL_SIMPLE_SORT_ORDER;
      
$this->enabled = ((MODULE_PAYMENT_PAYPAL_SIMPLE_STATUS == 'True'? true : false);

      if ((int)MODULE_PAYMENT_PAYPAL_SIMPLE_ORDER_STATUS_ID > 0) {
        
$this->order_status = MODULE_PAYMENT_PAYPAL_SIMPLE_ORDER_STATUS_ID;
      }
      
      
$this->paynow_action_url = 'https://' . MODULE_PAYMENT_PAYPAL_SIMPLE_HANDLER;
      
if (is_object($order)) $this->update_status();    
    }

// class methods
    function update_status() {
      
global $order, $db;

      if ( ($this->enabled == true&& ((int)MODULE_PAYMENT_PAYPAL_SIMPLE_ZONE > 0) ) {
        
$check_flag = false;
        
$check = $db->Execute("select zone_id from " . TABLE_ZONES_TO_GEO_ZONES . " where geo_zone_id = '" . MODULE_PAYMENT_PAYPAL_SIMPLE_ZONE . "' and zone_country_id = '" . $order->billing['country']['id'. "' order by zone_id");
        
while (!$check->EOF) {
          
if ($check->fields['zone_id'< 1) {
            
$check_flag = true;
            
break;
          } 
elseif ($check->fields['zone_id'== $order->billing['zone_id']) {
            
$check_flag = true;
            
break;
          }
          
$check->MoveNext();
        }

        if ($check_flag == false) {
          
$this->enabled = false;
        }
      }
    }

    function javascript_validation() {
      
return false;
    }

    function selection() {
      
$text = MODULE_PAYMENT_SIMPLE_PAYPAL_TEXT_CATALOG_LOGO.'&nbsp;&nbsp;'.MODULE_PAYMENT_PAYPAL_SIMPLE_TEXT_TITLE .  '<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;<span class="smallText">' . MODULE_PAYMENT_PAYPAL_SIMPLE_ACCEPTANCE_MARK_TEXT . '</span><br/><br/>';
      
return array('id' => $this->code,
                 
'module' => $text
                 );
    }

    function pre_confirmation_check() {
      
return false;
    }

    function confirmation() {
      
return false;
    }

    function process_button() {
      
return false;
    }

    function before_process() {
      
return false;
    }

    function after_process() {
      
return false;
    }

    function get_error() {
      
return false;
    }

    function check() {
      
global $db;
      
if (!isset($this->_check)) {
        
$check_query = $db->Execute("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = 'MODULE_PAYMENT_PAYPAL_SIMPLE_STATUS'");
        
$this->_check = $check_query->RecordCount();
      }
      
return $this->_check;
    }

    function install() {
      
global $db;
      
$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-Simple Module', 'MODULE_PAYMENT_PAYPAL_SIMPLE_STATUS', 'True', 'Do you want to accept PayPal-Simple payments?', '6', '0', 'zen_cfg_select_option(array(\'True\', \'False\'), ', now())");
      
      
$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_SIMPLE_SORT_ORDER', '0', 'Sort order of display. Lowest is displayed first.', '6', '8', now())");
      
       
$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_SIMPLE_ZONE', '0', 'If a zone is selected, only enable this payment method for that zone.', '6', '2', 'zen_get_zone_class_title', 'zen_cfg_pull_down_zone_classes(', now())");
       
       
$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_SIMPLE_ORDER_STATUS_ID', '0', 'Set the status of orders made with this payment module to this value', '6', '0', 'zen_cfg_pull_down_order_statuses(', 'zen_get_order_status_name', now())");
      
      
$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_SIMPLE_HANDLER', 'www.paypal.com/cgi-bin/webscr', 'Choose the URL for PayPal live processing', '6', '73', '', now())");
    }

    function remove() {
      
global $db;
      
$db->Execute("delete from " . TABLE_CONFIGURATION . " where configuration_key in ('" . implode("', '", $this->keys()) . "')");
    }

    function keys() {
      
return array('MODULE_PAYMENT_PAYPAL_SIMPLE_STATUS','MODULE_PAYMENT_PAYPAL_SIMPLE_SORT_ORDER','MODULE_PAYMENT_PAYPAL_SIMPLE_ZONE','MODULE_PAYMENT_PAYPAL_SIMPLE_ORDER_STATUS_ID', 'MODULE_PAYMENT_PAYPAL_SIMPLE_HANDLER');
    }
    
    
function paynow_button($order_id){
         
global $db, $order, $currencies, $currency;
    
require_once(DIR_WS_CLASSES . 'order.php');
    
$order = new order($order_id);
    
$options = array();
    
$optionsCore = array();
    
$optionsPhone = array();
    
$optionsShip = array();
    
$optionsLineItems = array();
    
$optionsAggregate = array();
    
$optionsTrans = array();
    
$buttonArray = array();

    $this->totalsum = $order->info['total'];

    // save the session stuff permanently in case paypal loses the session
    $_SESSION['ppipn_key_to_remove'= session_id();
    
$db->Execute("delete from " . TABLE_PAYPAL_SESSION . " where session_id = '" . zen_db_input($_SESSION['ppipn_key_to_remove']) . "'");

    $sql = "insert into " . TABLE_PAYPAL_SESSION . " (session_id, saved_session, expiry) values (
            '
" . zen_db_input($_SESSION['ppipn_key_to_remove']) . "',
            '
" . base64_encode(serialize($_SESSION)) . "',
            '
" . (time() + (1*60*60*24*2)) . "')";

    $db->Execute($sql);

    $my_currency = select_pp_currency();
    
$this->transaction_currency = $my_currency;

    $this->transaction_amount = ($this->totalsum * $currencies->get_value($my_currency));

    $telephone = preg_replace('/\D/', '', $order->customer['telephone']);
    
if ($telephone != '') {
      
$optionsPhone['H_PhoneNumber'= $telephone;
      
if (in_array($order->customer['country']['iso_code_2'], array('US','CA'))) {
        
$optionsPhone['night_phone_a'= substr($telephone,0,3);
        
$optionsPhone['night_phone_b'= substr($telephone,3,3);
        
$optionsPhone['night_phone_c'= substr($telephone,6,4);
        
$optionsPhone['day_phone_a'= substr($telephone,0,3);
        
$optionsPhone['day_phone_b'= substr($telephone,3,3);
        
$optionsPhone['day_phone_c'= substr($telephone,6,4);
    } 
else {
        
$optionsPhone['night_phone_b'= $telephone;
        
$optionsPhone['day_phone_b'= $telephone;
      }
    }

    $optionsCore = array(
                   
'charset' => CHARSET,
                   
'lc' => $order->customer['country']['iso_code_2'],
                   
'page_style' => MODULE_PAYMENT_PAYPAL_PAGE_STYLE,
                   
'custom' => zen_session_name() . '=' . zen_session_id(),
                   
'business' => MODULE_PAYMENT_PAYPAL_BUSINESS_ID,
                   
'return' => zen_href_link(FILENAME_PAY_SUCCESS, 'referer=paypal', 'SSL'),
                   
'cancel_return' => zen_href_link(FILENAME_PAY_FAILED, '', 'SSL'),
                   
'shopping_url' => zen_href_link(FILENAME_SHOPPING_CART, '', 'SSL'),
                   
'notify_url' => zen_href_link('ipn_main_handler.php', '', 'SSL',false,false,true),
                   
'redirect_cmd' => '_xclick',
                   
'rm' => 2,
                   
'bn' => 'zencart',
                   
'mrb' => 'R-6C7952342H795591R',
                   
'pal' => '9E82WJBKKGPLQ',
                   );
    
$optionsCust = array(
                   
'first_name' => replace_accents($order->customer['firstname']),
                   
'last_name' => replace_accents($order->customer['lastname']),
                   
'address1' => replace_accents($order->customer['street_address

【上篇】
【下篇】

抱歉!评论已关闭.