对于zencart网站paypal支付漏单问题的解决方法

时间:2024-04-17 17:34:40

第一种方法:

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页面,可以在这里进入付款页面。如下图所示:
对于zencart网站上paypal漏单问题解决 - ぃ小木の - 喏——╅ぃi小木专属の
    2. 如果当时客户没能付款,也可进入自己的后台对历史订单进行付款。如下图所示:
对于zencart网站上paypal漏单问题解决 - ぃ小木の - 喏——╅ぃi小木专属の
 下面我们就来看看如何一步一步来实现上述的功能。

   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按钮做准备的。
3. 在checkout_success页面中显示pay now按钮。打开文件"includes/modules/pages/checkout_success/header.php",在文件的末尾添加下面的代码(如果你已经掌握zen-cart中的通知者/观察者模式,并且又不想破坏zen-cart核心代码的话,也可以创建一个观察类来监听 NOTIFY_HEADER_END_CHECKOUT_SUCCESS来实现)。
require_once(DIR_WS_CLASSES . \'order.php\');
require_once(DIR_WS_CLASSES . \'payment.php\');
$payment_modules = new payment($orders->fields[\'payment_module_code\']);
  打开文件"includes/modules/templates/template_default/templates /tpl_checkout_success_default.php",并在适当的位置加上如下的代码,这里对订单的状态进行了一个判断,当只有订单的状态在未付款状态,才显示该按钮,
<div id="pay_now">
    
<?php    
    
//&& $orders->fields[\'orders_status\'] == \'1\'
    if(isset($payment_modules->paynow_action_url) && $payment_modules->paynow_action_url != \'\'&& $orders->fields[\'orders_status\'== \'1\'){
        
echo(\'<fieldset id="csNotifications">\');
        
echo(\'<legend>\'.TEXT_PAYNOW.\'</legend>\');
        
echo zen_draw_form(\'checkout_paynow\', $payment_modules->paynow_action_url, \'post\', \'id="checkout_confirmation" onsubmit="submitonce();"\');
        
$selection = $payment_modules->selection();
        
echo(\'<div class="buttonRow payment_method">\'.$selection[0][\'module\'].\'</div>\');
        
echo(\'<div class="buttonRow forward paynow">\');            
        
if (is_array($payment_modules->modules)) {                
            
echo $payment_modules->paynow_button($orders_id);
        }
        
echo(zen_image_submit(BUTTON_IMAGE_PAYNOW, BUTTON_IMAGE_PAYNOW_ALT, \'name="btn_paynow" id="btn_paynow"\'));
        
echo(\'</div>\');
        
echo(\'</form>\');
        
echo(\'</fieldset>\');
    }
    
?>
</div>
4. 在历史订单中显示pay now按钮。需要显示pay now按钮的页面有三个:account, account_history,account_history_info,这里的实现和checkout_success页面的实现大同小异,只是传给$payment_modules的函数paynow_button的参数不一样而已,这里就不再赘述。

 总结: 经过上面的修改,我们的流程如下:

   1. 购物车(shopping cart)

   2. [货运方式(delivery method)]

   3. 支付方式(payment method)

   4. 订单确认(confirmation)  

   5. 订单处理(checkout process)

   6. 下单成功(checkout success)

   7. [第三方网站支付] 

   因为从订单确认到订单处理,都是在我们自己的网站完成的,并且进入支付网站之前,订单已经存在了,这样就不会出现掉单的情况了。

第二种方法:

paypal漏单不知道困扰了多少了,没办法,paypal的流程机制就是那样的,我们没法更改paypal的付款流程,但是我们可以通过添加插件,修改自己的订单生成流程:

除paypal外的其他支付方式进入index.php?main_page=checkout_confirmation这个页面就能生出订单,但是paypal只能是从它的官网返回来是进入checkout_process.php这个文件后才能生出订单,所以我们只要在checkout_confirmation这个页面先生出订单就OK了,这边生出订单很简单,直接调用类:在这个文件的最后部分echo TITLE_CONTINUE_CHECKOUT_PROCEDURE . \'<br />\' . TEXT_CONTINUE_CHECKOUT_PROCEDURE;后面添加代码:
// create the order record  防漏单

if ($_SESSION[\'payment\'] == \'paypal\') {

$insert_id = $order->create($order_totals, 2);
$zco_notifier->notify(\'NOTIFY_CHECKOUT_PROCESS_AFTER_ORDER_CREATE\');
$payment_modules->after_order_create($insert_id);
$zco_notifier->notify(\'NOTIFY_CHECKOUT_PROCESS_AFTER_PAYMENT_MODULES_AFTER_ORDER_CREATE\');
// store the product info to the order
$order->create_add_products($insert_id);
$_SESSION[\'order_number_created\'] = $insert_id;

} ,这边注意,为了避免对其他支付方式产生影响,做了个判断,只有paypal支付会运行这些生成订单的代码,加了这段后就不用担心会漏单了:成功付款后后台订单如图:


GS/AK的为防漏单的订单,只有在出现漏单的时候才会查看这些订单,里面的信息跟正常订单相比会少一个交易号,但是至少是可以看到客户信息及所购买产品的,该方法原理简单,只需要修噶一个文件即可。