magento 多货币paypal支付扩展

magento电商网站支持多种货币或语言,但是paypal支付的时候,都是基于店铺的baseCurrency进行付款,所以选择 paypal时,paypal不支持多货币的支付。
例如:网站的基准货币是GBP(英镑),客户现在只能使用USD(美元)付款;而magento集成的paypa在支付的时候,是以网站的基准货币GBP(英镑)进行付款,这时候客户就不能使用美元付款了,从而降低了网站的购买率。
现在,对paypal这一模块进行下扩展,让paypal支持多货币支付。
1、app/etc/modules/Silk_Paypal.xml

<?xml version='1.0'?>
<config>
    <modules>
        <Silk_Paypal>
            <active>true</active>
            <codePool>local</codePool>
        </Silk_Paypal>
    </modules>
</config>

2、app/code/local/Silk/Paypal

    ---etc
        --config.xml
    ---Model
        --Api
          --Nvp.php
        --Express
          --Checkout.php
        --Cart.php
        --Express.php

3、config.xml中:

<?xml version='1.0'?>
<config>
    <modules>
        <Silk_Paypal>
            <version>0.1.0</version>
        </Silk_Paypal>
    </modules>  
    <global>
        <models>
            <paypal>
                <rewrite>
                    <express>Silk_Paypal_Model_Express</express>
                    <express_checkout>Silk_Paypal_Model_Express_Checkout</express_checkout>
                    <api_nvp>Silk_Paypal_Model_Api_Nvp</api_nvp>
                    <cart>Silk_Paypal_Model_Cart</cart>
                </rewrite>
            </paypal>
        </models>
    </global>
</config>

4、点击paypal快捷支付后,magento就会向paypal官方发送数据进行支付:
Mage_Paypal_Model_Express_Checkout中的start方法用于SetExpressCheckout的订单号、支付金额、货币符号、返回url、cancelUrl、paymentAction的设定,我们在这个方法中重新设置支付金额和货币符号即可。就要重写这个start方法,将默认的start方法拷贝到第2步中的Checkout.php中去。
然后找到下面的代码:

    // prepare API
        $this->_getApi();
        $solutionType = $this->_config->getMerchantCountry() == 'DE'
            ? Mage_Paypal_Model_Config::EC_SOLUTION_TYPE_MARK : $this->_config->solutionType;
        $this->_api->setAmount($this->_quote->getBaseGrandTotal())/*默认使用的基准货币的总价格*/
            ->setCurrencyCode($this->_quote->getBaseCurrencyCode())/*默认设置的是店铺的基准货币*/
            ->setInvNum($this->_quote->getReservedOrderId())
            ->setReturnUrl($returnUrl)
            ->setCancelUrl($cancelUrl)
            ->setSolutionType($solutionType)
            ->setPaymentAction($this->_config->paymentAction);   

替换为

// prepare API
        $this->_getApi();
        $solutionType = $this->_config->getMerchantCountry() == 'DE'
            ? Mage_Paypal_Model_Config::EC_SOLUTION_TYPE_MARK : $this->_config->solutionType;

        /*得到店铺的当前货币*/
        $currentCurrencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();

        $this->_api->setAmount($this->_quote->getGrandTotal())/*当前货币的总价格,grandTotal表示实际应付总金额*/
        ->setCurrencyCode($currentCurrencyCode)/*设置货币为当前货币*/
        ->setInvNum($this->_quote->getReservedOrderId())
        ->setReturnUrl($returnUrl)
            ->setCancelUrl($cancelUrl)
            ->setSolutionType($solutionType)
            ->setPaymentAction($this->_config->paymentAction);

5、更改paypal购物车的信息,复制paypal/cart.php中的addItem方法到第2步的cart.php中去,更改如下:

public function addItem($name, $qty, $amount, $identifier = null)
    {
        $this->_shouldRender = true;
        if($name == 'Discount'){
            /*得到购物车中的discount*/
            $quoteEntity = $this->getSalesEntity();
            $grandTotal = $quoteEntity->getGrandTotal();
            $subtotal = $quoteEntity->getSubtotal();
            $shppingAmount = $quoteEntity->getShippingAmount();/*运输费*/
            $discount = -1 *($subtotal+$shippingAmount - $grandTotal) ;
          
            $item = new Varien_Object(array(
                'name'   => $name,
                'qty'    => $qty,
                'amount' => (float)$discount,
            ));
        }else {
            $item = new Varien_Object(array(
                'name' => $name,
                'qty' => $qty,
                'amount' => (float)$this->CurrencyConverter($amount),/*CurrencyConverter货币转换,转换为当前货币*/
            ));
        }
        if ($identifier) {
            $item->setData('id', $identifier);
        }
        $this->_items[] = $item;
        return $item;
    }

然后再在这个cart.php中新增一个上面addItem方法中所提到的方法CurrencyConverter

/*货币转为当前货币*/
    protected function CurrencyConverter($amount)
    {
        $amount =  Mage::app()->getStore()->convertPrice($amount);
        return round($amount,2);
    }

值得一提的是discount折扣的货币转换,这里我没有对折扣进行货币转换,因为折扣是百分比的话,会出现换算的问题,所以采用比较保险的方法,用总的Subtotal(总价格)减去GrandTotal(结算价格)即为discount折扣的总价格,这样就避免了不必要的错误。
$this->getSalesEntity()这个调用说明:
(1)在start方法中你会看到这样的一段代码:

 $paypalCart = Mage::getModel('paypal/cart', array($this->_quote));
        $this->_api->setPaypalCart($paypalCart)
            ->setIsLineItemsEnabled($this->_config->lineItemsEnabled)
        ;

(2)在paypal/cart中的构造方法里面可以看到,下面2个方法:

 public function __construct($params = array())
    {
    
        $salesEntity = array_shift($params);
        if (is_object($salesEntity)
            && (($salesEntity instanceof Mage_Sales_Model_Order) || ($salesEntity instanceof Mage_Sales_Model_Quote))) {
            $this->_salesEntity = $salesEntity;
        } else {
            throw new Exception('Invalid sales entity provided.');
        }
    }
    /*得到queto对象*/
     public function getSalesEntity()
    {
        return $this->_salesEntity;
    }

所以在这里直接调用getSalesEntity方法,就可以取到SUbtotal和grandTotal了
6、更改callSetExpressCheckout和callDoExpressCheckoutPayment这2个方法,这2个方法的位置:Mage_Paypal_Model_Api_Nvp
在这个2个方法中添加:

$request['AMT'] = (float)$this->getPayTotal();
        $request['ITEMAMT'] = (float)$this->getPayTotal();

在Nvp.php中添加一个方法GetPaypalTotal

public function getPayTotal()
    {  
        $items = $this->_cart->getItems();
        $total = 0;  
        foreach($items as  $item){         
           $total += $_item['qty'] * $_item['amount'];        
        }
        $totals = $total 
        
        /*如果有交税的话,加税费即可*/
        $Subtotal = $this->_cart->getTotals();
        $tax = Mage::app()->getStore()->convertPrice($subtotal['tax']);
        
        return $totals + round($tax,2);
    }

在Mage/Paypal/Model/cart中可以看到一个_render()的方法和_addRegularItem();
这个2个方法就是将discount、shipping以及网站的购物车的Items添加到paypal购物车中去作为Items,所以,在getPayTotal方法中遍历出paypal购物车的所有Items,计算出每个item的总价格,在进行叠加即可得到结算时的总价格。如果有交税的话,加税费即可。
7、更改最后一个文件:Express.php(订单授权)
Mage_Paypal_Model_Express修改它里面的_placeOrder()方法,找到

$api = $this->_pro->getApi()
            ->setToken($token)
            ->setPayerId($payment->
                getAdditionalInformation(Mage_Paypal_Model_Express_Checkout::PAYMENT_INFO_TRANSPORT_PAYER_ID))
            ->setAmount($amount)
            ->setPaymentAction($this->_pro->getConfig()->paymentAction)
            ->setNotifyUrl(Mage::getUrl('paypal/ipn/'))
            ->setInvNum($order->getIncrementId())
            ->setCurrencyCode($order->getBaseCurrencyCode())
            ->setPaypalCart(Mage::getModel('paypal/cart', array($order)))//
            ->setIsLineItemsEnabled($this->_pro->getConfig()->lineItemsEnabled);

更改为

$currentCurrencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();
   
        $api = $this->_pro->getApi()
            ->setToken($token)
            ->setPayerId($payment->
            getAdditionalInformation(Mage_Paypal_Model_Express_Checkout::PAYMENT_INFO_TRANSPORT_PAYER_ID))
            ->setAmount($amount)/*总价格*/
            ->setPaymentAction($this->_pro->getConfig()->paymentAction)
            ->setNotifyUrl(Mage::getUrl('paypal/ipn/'))
            ->setInvNum($order->getIncrementId())/*订单号*/
            ->setCurrencyCode($currentCurrencyCode)/*设置下单的货币,paypal账号必须支持该货币*/
            ->setPaypalCart(Mage::getModel('paypal/cart', array($order)))//
            ->setIsLineItemsEnabled($this->_pro->getConfig()->lineItemsEnabled);

完成以上步骤,paypal多货币的支付就可以实现了。
再来看看前段页面的显示效果:
我测试网站主站是英国站,基准货币为GBP,我切换为美元的时候,购物车如图:

点击payapl支付后,paypal购物车的信息:

后台订单的信息:

来源: https://segmentfault.com/a/1190000005073085

相关文章

0 0 投票数
文章评分
订阅评论
提醒
0 评论
内联反馈
查看所有评论