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购物车的信息:
后台订单的信息: