需求

现有购物网站支持2种支付方式,但是考虑到会出现如下情况: 在一个优惠活动中,假如有一些订单的总金额为0, 那么这些订单就不必跳转到支付网关,现有支付方式无法处理此种情况。

分析

当customer输入订单的收货信息后,点击确认按钮,页面就会跳转到选择支付方式页面,默认流程是直接给出所有支付方式供customer选择,但是对于上面需求中提到的情况:假如订单总金额为0,那么就不应该直接给出所有支付方式,因为根本没有支付需求嘛。修改后的流程应该是先检测订单总金额,假如订单总金额等于0,则只提供一种支付方式——Free Payment支付方式,供customer选择,Free Payment支付方式无需支付,在用户同意并点击checkout-agreements后直接将订单信息发送至服务器;假如订单总金额大于0,则返回全部原有的支付方式供customer选择(应除去新增的Free Payment支付方式)。

解决方案

我查看了Magento的Payment Module的源码之后,发现Magento1.9原生支持0金额订单支付(如果有经验的话根本不需要看源代码),在后台System->Configration->SALES->Payment Methods->Zero Subtotal Checkout可进行配置以开启此支付方式。

配置选项如下:

  • “Title”控制前端显示的名称
  • “New Order Status”表示通过此方式支付后的订单状态
  • “Automatically Invoice All Items”:自动invoice订单内包含的所有项目

通过配置这些参数,就可以实现上面提出的需求。

源码分析

下面记录了一下我查看Magento支付模块(Payment Module)源码的过程:

Magento返回支付方式是在的URL是base_url/checkout/onepage/saveShippingMethod/, 可以看出,这个动作是在onepageController中的saveShippingMethodAction()方法中完成的。

 //file: base_dir/app/code/core/Mage/Checkout/controllers/onepageController.php
/**
* Shipping method save action
*/
public function saveShippingMethodAction()
{
if ($this->_expireAjax()) {
return;
}
if ($this->getRequest()->isPost()) {
$data = $this->getRequest()->getPost('shipping_method', '');
$result = $this->getOnepage()->saveShippingMethod($data);
// $result will contain error data if shipping method is empty
if (!$result) {
Mage::dispatchEvent(
'checkout_controller_onepage_save_shipping_method',
array(
'request' => $this->getRequest(),
'quote' => $this->getOnepage()->getQuote()));
$this->getOnepage()->getQuote()->collectTotals();
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result)); $result['goto_section'] = 'payment';
$result['update_section'] = array(
'name' => 'payment-method',
'html' => $this->_getPaymentMethodsHtml()
);
}
$this->getOnepage()->getQuote()->collectTotals()->save();
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
}
}

在这个方法中,首先获取了POST过来的 "shipping_method" 数据,检测有否有error,如果没有error就生成$result数组,最后在 Mage_Core_Helper_Data 类的 jsonEncode() 方法中将$result数组编码为JSON格式,最后发送到浏览器。

生成$result['update_section']['html']的方法$this->_getPaymentMethodsHtml()代码如下:

 //file: base_dir/app/code/core/Mage/Checkout/controllers/onepageController.php
/**
* Get payment method step html
*
* @return string
*/
protected function _getPaymentMethodsHtml()
{
$layout = $this->getLayout();
$update = $layout->getUpdate();
$update->load('checkout_onepage_paymentmethod');
$layout->generateXml();
$layout->generateBlocks(); //---------only for debug------------------
/** @var Mage_Core_Block_Template $block */
foreach ($layout->getAllBlocks() as $block) {
Mage::log($block->getTemplate());
}
//---------only for debug------------------ $output = $layout->getOutput();
return $output;
}

此方法生成了供前台页面使用的HTML。可以通过做Log来快速定位PaymentMethod Block的Template。其中,$layout为 Mage_Core_Model_Layout 的实例,查看它的 getOutput() 方法:

 //file: base_url/app/code/core/Mage/Core/Model/Layout.php
/**
* Get all blocks marked for output
*
* @return string
*/
public function getOutput()
{
$out = '';
if (!empty($this->_output)) {
foreach ($this->_output as $callback) {
//---------only for debug------------------
Mage::log($callback);
Mage::log(get_class($this->getBlock($callback[0])));
Mage::log($this->getBlock($callback[0])->getTemplate());
//---------only for debug------------------
$out .= $this->getBlock($callback[0])->$callback[1]();
}
} return $out;
}

通过对$callback做log,可以知道$callback的结构如下:

 //Mage::log($callback);
Array
(
[0] => root
[1] => toHtml
)
//Mage::log(get_class($this->getBlock($callback[0])));
Mage_Checkout_Block_Onepage_Payment_Methods
//Mage::log($this->getBlock($callback[0])->getTemplate());
checkout/onepage/payment/methods.phtml
*/

进而可以知道Payment Methods的Block是 Mage_Checkout_Block_Onepage_Payment_Methods (如果你有经验的话应该早就猜到了是这个Block了,Magento是通过Block和template文件结合起来渲染页面的)。 结合 Mage_Checkout_Block_Onepage_Payment_Methods 和它的Template文件, 可以确定它是通过 getMethods() 这个方法来获取合适的支付方式的。

 //file: base_dir/app/code/core/Mage/Payment/Block/Form/Container.php
/**
* Retrieve available payment methods
*
* @return array
*/
public function getMethods()
{
$methods = $this->getData('methods');
if ($methods === null) {
$quote = $this->getQuote();
$store = $quote ? $quote->getStoreId() : null;
$methods = array();
foreach ($this->helper('payment')->getStoreMethods($store, $quote) as $method) {
if ($this->_canUseMethod($method) && $method->isApplicableToQuote(
$quote,
Mage_Payment_Model_Method_Abstract::CHECK_ZERO_TOTAL
)) {
$this->_assignMethod($method);
$methods[] = $method;
}
}
$this->setData('methods', $methods);
}
return $methods;
}

在 getMethods() 中,一共有三种方式可以控制某个quote的支付方式:

  • 第一种是$this->helper('payment')->getStoreMethods($store, $quote),这个是“源头”;
  • 第二个是$this->_canUseMethod($method);
  • 第三个是$method->isApplicableToQuote($quote, Mage_Payment_Model_Method_Abstract::CHECKZEROTOTAL);

结合这三种方式,就可以筛选出合适的支付方式。假如你新增了一种支付方式,但是前台显示不出来,就应该从这三个筛选方式着手。

这次的Magento源码“探索之旅”就到这里吧 :D

如果您觉得阅读本文对您有帮助,欢迎转载本文,但是转载文章之后必须在文章页面明显位置保留此段声明,否则保留追究法律责任的权利。

作  者:blog.jpdou.top

原文链接:http://blog.jpdou.top/magento-0-subtotal-payment-method/

Magento 0元订单 支付方式 -- Magento 0 Subtotal Payment Method的更多相关文章

  1. Magento代码之订单创建流程

    Magento代码之订单创建流程         直接看代码吧.下面的代码是如何通过程序创建一个完美订单.        <?php        require_once 'app/Mage. ...

  2. hexo + Github Page 0元建立博客攻略

    传送门: 5分钟 0元搭建个人独立博客网站(一):https://mp.weixin.qq.com/s/69isJE191WV2gaVbjrwTtw 5分钟 0元搭建个人独立博客网站(二):https ...

  3. 推荐:国产etl调度工具Taskctl web应用版,0元永久授权

    写在前面 2020年疫情席卷全球,更是对整个市场经济造成了严重影响,年初疫情肆虐,西方世界单方面的科技.经济封锁,国际关系吃紧.....导致很多中小型企业业务链受阻,大型企业经费资金吃紧,轮班制导致公 ...

  4. 如何迁移测试的MAGENTO到正式运行的MAGENTO

    或者这个题目叫做如何改变MAGENTO的运行目录 第一,我们需要在PHPMYADMIN备份整个MAGENTO的数据.备份数据并且存为.SQL. 在这儿假设你的测试网站在http://dev.site. ...

  5. 深入理解Magento - 第六章 - 高级Magento模型

    我们讲过Magento有两种模型,简单模型和EAV(Entity Attribute Value)模型.上一章我们讲过所有的Magento模型都是继承自Mage_Core_Model_Abstract ...

  6. C# 8.0和.NET Core 3.0高级编程 分享笔记二:编程基础第一部分

    基础部分被我分为了2篇,因为实在太多了,但是每一个知识点我都不舍得删除,所以越写越多,这一篇博客整理了4个夜晚,内容有点多建议慢慢看.本章涵盖以下主题: 介绍C# 理解C#的基础知识 使用变量 处理空 ...

  7. 关于一体机打印新加菜按钮更改为下单小票打印设置FAQ(适用正餐6.0.1.0+,轻餐4.0.6.2+)

    适用版本:正餐6.0.1.0+,轻餐4.0.6.2+ 实际场景:更新后小票设置中的打印新加菜按钮更换为下单小票打印设置,更换后,设置中,有3个选项: 1.仅打印新加菜    (选中后,订单加菜后前台小 ...

  8. PHP build notes - WARNING: This bison version is not supported for regeneration of the Zend/PHP parsers (found: 3.0, min: 204, excluded: 3.0).

     WARNING: This bison version is not supported for regeneration of the Zend/PHP parsers (found: 3.0, ...

  9. CentOS 7.0编译安装Nginx1.6.0+MySQL5.6.19+PHP5.5.14

    准备篇: CentOS 7.0系统安装配置图解教程 http://www.osyunwei.com/archives/7829.html 一.配置防火墙,开启80端口.3306端口 CentOS 7. ...

随机推荐

  1. SQL Server中查询CPU占用高的SQL语句

    SQL Server中查询CPU占用高的情况,会用到sys.sysprocesses ,dm_exec_sessions ,dm_exec_requests 一.查看当前的数据库用户连接有多少 USE ...

  2. 4月超棒的JavaScript游戏开发框架推荐(1) – 51CTO.COM

    基于JavaScript开发的游戏是唯一一个能够跨桌面,Web和移动三种平台的.… 查阅全文 ›

  3. ununtu 下安装 Nvidia 显卡驱动

    本人电脑硬件配置:CPU : AMD Athlon(tm) II X2 215 Processor × 2 显示卡 : GeForce 6150SE nForce 430/integrated/SSE ...

  4. dubbo框架介绍

    1.背景 (#) 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进. 单一应用架构 当网站流量很小 ...

  5. linux中的调试知识---基础gdb和strace查看系统调用信息,top性能分析,ps进程查看,内存分析工具

    1 调试一般分为两种,可以通过在程序中插入打印语句.有点能够显示程序的动态过程,比较容易的检查出源程序中的有关信息.缺点就是效率比较低了,而且需要输入大量无关的数据. 2 借助相关的调试工具. 3 有 ...

  6. 技术胖Flutter第三季-14布局RowWidget的详细讲解

    flutter总的地址: https://jspang.com/page/freeVideo.html 视频地址: https://www.bilibili.com/video/av35800108/ ...

  7. httpd基础

    hpptd http服务器应用 http服务器程序 httpd apache nginx lighttpd 应用程序服务器 IIS .asp tomcat .jsp jetty 开源的servlet容 ...

  8. QDUOJ 生化危机 邻接表存图+BFS

    生化危机 发布时间: 2015年10月10日 18:05   时间限制: 1000ms   内存限制: 256M 描述 X博士想造福人类, 研发一种可以再生肢体的药物, 可是很不幸......研究失败 ...

  9. Fitnesse + Xebium环境搭建

    1.在搭建Fitnesse + Xebium环境之前先将selenium基础环境搭建完成并调试成功 参照:http://www.cnblogs.com/moonpool/p/5480724.html ...

  10. bat 批处理之提取带有关键字的整行数据

    用于在log中检索出insert sql语句,主要用于数据恢复 前言: a.txt 里面存放的是 需要查找的关键字 b.bat limian 存放的是执行程序 生成的文件存放在 c.txt(自动创建) ...