Magento购物车Checkout Onepage页面的SaveBilling处理过程

by Web全栈工程师 on 2011 年 09 月 01 日

在Magento Checkout Onepage 中SaveBilling处理大致可分以下几步

1、通过Ajax提交到OnePageController.php的saveBillingAction方法

//在billing.phtml中利用Javascript对Billing类进行创建,并在该页面中通过billing.save()来进行Ajax请求
 var billing = new Billing('co-billing-form', '<?php echo $this->getUrl('checkout/onepage/getAddress') ?>address/', '<?php echo $this->getUrl('checkout/onepage/saveBilling') ?>');
//javascript'save方法
save: function(){
        if (checkout.loadWaiting!=false) return;
        var validator = new Validation(this.form);
        if (validator.validate()) {
            if (checkout.method=='register' && $('billing:customer_password').value != $('billing:confirm_password').value) {
                alert(Translator.translate('Error: Passwords do not match'));
                return;
            }
            checkout.setLoadWaiting('billing');
//            if ($('billing:use_for_shipping') && $('billing:use_for_shipping').checked) {
//                $('billing:use_for_shipping').value=1;
//            }
            var request = new Ajax.Request(
                this.saveUrl,
                {
                    method: 'post',
                    onComplete: this.onComplete,
                    onSuccess: this.onSave,
                    onFailure: checkout.ajaxFailure.bind(checkout),
                    parameters: Form.serialize(this.form)
                }
            );
        }
    }

 

2、处理saveBillingAction中saveBilling方法

$result = $this->getOnepage()->saveBilling($data, $customerAddressId);

2.1 分析sales_flat_quote_address表中有无addressid(一条billing信息就有一个addressid与之相对应),有则更新,无则追加

 $address = $this->getQuote()->getBillingAddress();
        if (!empty($customerAddressId)) {
            $customerAddress = Mage::getModel('customer/address')->load($customerAddressId);
            if ($customerAddress->getId()) {
                if ($customerAddress->getCustomerId() != $this->getQuote()->getCustomerId()) {
                    return array('error' => 1,
                        'message' => Mage::helper('checkout')->__('Customer Address is not valid.')
                    );
                }
                $address->importCustomerAddress($customerAddress);
            }
        } else {
            unset($data['address_id']);
            $address->addData($data);
            //$address->setId(null);
        }

2.2$this->getQuote()->collectTotals();进行金额计算

展开这个方法,会发现这个方法是在 app/code/core/Mage/Sales/Model/Quote/Address.php中定义,其内用反射来找到当前需要计算的模块,而 collect函数则在app/code/core/Mage/Sales/Model/Quote/Address/Total/下(通过 getTotalModels可以看到其命名空间),也就是说,不管是shipping、subtotal、grand、handling fee、tax、discount等运算规则,其内的运算方法名是统一的,名为collect()。这也就是模板模式。

public function collectTotals()
    {
        foreach ($this->getTotalModels() as $model) {
            if (is_callable(array($model, 'collect'))) {
                $model->collect($this);
            }
        }
        return $this;
    }

3、根据用户是否选择the same as shipping information来决定执行_getShippingMethodsHtml

4、执行_getShippingMethodsHtml

返回layout中的checkout_onepage_shippingmethod 块信息(其内有显示available.phtml与additional.phtml的信息。具体请参见layout/checkout.xml下 block=”checkout_onepage_shippingmethod”下的附属块结点所对应模板的phtml文件)

  protected function _getShippingMethodsHtml()
    {
        $layout = $this->getLayout();
        $update = $layout->getUpdate();
        $update->load('checkout_onepage_shippingmethod');
        $layout->generateXml();
        $layout->generateBlocks();
        $output = $layout->getOutput();
        return $output;
    }

5、将块信息进行json编码,返回给opcheckout.js的savebilling的ajax

 $result['update_section'] = array(
                        'name' => 'shipping-method',
                        'html' => $this->_getShippingMethodsHtml()
                    );
$this->getResponse()->setBody(Zend_Json::encode($result));

6、在opcheckout.js中 savebilling成功后调用onSave,而onSave指向的是nextstep函数

 nextStep: function(transport){
        if (transport && transport.responseText){
            try{
                response = eval('(' + transport.responseText + ')');
            }
            catch (e) {
                response = {};
            }
        }
        if (response.error){
            if ((typeof response.message) == 'string') {
                alert(response.message);
            } else {
                if (window.billingRegionUpdater) {
                    billingRegionUpdater.update();
                }
                alert(response.message.join("/n"));
            }
            return false;
        }
        checkout.setStepResponse(response);
}
//而checkout.setStepResponse(response)为基类checkout的方法
  setStepResponse: function(response){
        if (response.update_section) {
        	//response.update_section.html
            $('checkout-'+response.update_section.name+'-load').update(response.update_section.html);
        }
//这里的response.update_section.html就是返回在服务器端返回的json,其格式如下{"update_section":{"html":"<div>...</div>"}}

其它模块类似。

本文转自 http://blog.csdn.net/liangpei2008/article/details/6084183

Comments on this entry are closed.

Previous post:

Next post: