Surcharge on card payment in Magento

I just searched for a solution to surcharge customers for a certain PSP in Magento. The only thing I could find a module which priced at USD 49. I also found a lot of argument about whether card payment surcharge is illegal or against PSP’s policy, to which I do not care. What I do care is a free and easy solution to do the job.

Looking at Promotions -> Shopping Cart Price Rules, we can give discount for some kinds of payment method. But the discount can not be minus, which makes it work as surcharge. However, Magento only validates discount must be positive when saving a shopping cart price rule to database. It does not validate again when applying this rule. Therefore, we can make up a rule, enter discount with a positive value, then change the value to minus in database. That’s all you need to do to surcharge customers.

By the way, I think Magento validation on discount limits its usability. Why not use the salesrule module for both promotions and surcharges? I really like to see the menu Promotions be replaced by Sales Rules. (The word salesrule is already being used as table name and in script.)

PayPal Spoof

PayPal Looks Like Phishing
An email from PayPal: looks like phishing

I had an email from PayPal a while ago. I believe it was sent by some careless staff of PayPal.

PayPal always remind people aware of phishing emails. At the bottom of the email, it says – How do I know this is not a spoof email? Spoof or ‘phishing’ emails tend to have generic greetings such as “Dear PayPal member”. Email from PayPal will always address you by your first and last name.

However, this particular email address me “Dear First Name Last Name”.

Cross-browser CSS

Today I did something CSS cross-browser testing. Here are some of my findings today.

  • Validate Xhtml / Html before styling. I put form element between table and tr element which make it an invalid xhtml document and cause CSS rendering in a strange way in IE. (IE is generally bad in W3C standards but this time it is good – it reminds me to validate xhtml.)
  • -webkit-border-fit:lines

    is for Sarifi and Chrome only, making elements “shrink”, even block elements.
    > selector can’t be understand by IE6 and under.

  • Few people are using IE5.5 or under, so I decide not to bother about layout in IE5.5 or under.
  • Block elements have overflow by default to show in IE6, So if I want to set the height of a block element, I need also set
  • Cleaning elements with

    to clear floating elements above better be placed inside the same parent element of floating elements, otherwise in IE6, the elements after cleaning elements will not align nicely. for example:

    <div class="parent-element">
        <div class="floating-element">...</div>
        <div class="floating-element">...</div>
        <div class="cleaning-element">&nbsp;</div>

Open Office惨不忍睹

虽然我是 open source 的拥护者,但有人说 Open office 惨不忍睹,我也不得不承认。

在 Open Office Writer for Linux 下,按下 Ctrl + C 企图拷贝“邮编”这两个字,程序就死了。我试了好几次,Open Office 每次都死。这种毛病也真稀奇。

How Google group conversation is a mystery

我用一个 Google 邮箱 pop 另一个 Google 邮箱的1139封会话。Pop 结束后,接收方显示只有 1125封会话。当时我以为是某些会话没有 Pop 成功。经过一番核对,发现老邮箱里独立的某些会话,在新邮箱里被合并成一个会话。

于是我对 Google 合并会话的条件算法产生了兴趣,又经过一番搜索,发现 Google 对此算法讳莫如深。其实这算法有很大缺陷,Feature request 讨论组里对手工分拆和合并会话的呼声就很高。我也很想要这个功能。

Half constructed Magento objects

Magento 对象有个半构造状态。称之为半构造或许不恰当,但我一时找不到更合适的词来表达。

先说一个我以前碰到的问题:为什么在产品列表里的产品取不到自定义属性的值?因为此时产品处于半构造状态,半构造状态默认不加载自定义属性。只有在某产品所在的那一产品页,该产品才处于全构造状态。Magento 对象半构造主要是照顾速度。

再说另一个问题:甲产品是一个 bundled product,bundled items 里只有一个 option,该 option 里只有一个 selection,该 selection 是 20 件乙产品。我不明白 Magento 创造这么多名词干嘛,又是 option,又是 selection,暂且不管它,就按 Magento 层层 wrapper 来办。在甲产品的产品页上,要取得捆绑数量(20),可以这么办——

$_product = $this->getProduct(); //$_product is 甲产品
$_option = current($_product->getOptions());  //because only one option
$_selection = current($_option->getSelections()); //because only one selection
$_qty = $_selection->getSelectionQty(); 


$_product = Mage::getModel('catalog/product')->loadByAttribute('sku',$sku); //$_product is 甲产品
$_productType = $_product->getTypeInstance();
$_optionCollection = $_productType->getOptionsCollection();
$_selectionCollection = $_productType->getSelectionsCollection($_productType->getOptionsIds());
$_option = current($_optionCollection->appendSelections($_selectionCollection));
$_selection = current($_option->getSelections());

以上代码微妙之处就在$_option = current($_optionCollection->appendSelections($_selectionCollection));,它把半构造状态的甲产品进一步prepare,于是就有了selections。


If server_name is something like “*”, $server_name is exactly “*”. If $server_name is passed on to fastcgi_param as SERVER_NAME, in the program, for example, php $_SERVER[‘SERVER_NAME’] will be exactly “*”. However, _SERVER[“HTTP_HOST”] shows the value most of us would expect, i.e. the host name in the address bar.

In Nginx, I have set up a mechanism to install some popular scripts once, and use in multiple websites. I do not want people to find these websites are run under one roof. But if I write multiple websites in one line:


$_SERVER[‘SERVER_NAME’] is always assigned no matter the host is or

To avoid that, I have to break three websites into three server block in nginx.

$_SERVER[‘HTTP_HOST’] is always the host. But I can not control how people write the script. Breaking hosts into separate server blocks is recommended.

Nautilus mount

Nautilus is quite good, easy to use in regards to its mount feature. It can automatically “mount” Windows Share via smb:// protocol. However, some software, e.g. FileZilla (now can not read from or write to smb:// protocol. A genuine Linux mount is more helpful than Nautilus mount.