HomeContactLinks

Using updated currency rates

By Flib

2009-05-04

Category: PHP

The problem

You have an e-commerce site that for the convenience of our users would like to give approximate exchange rates for items even though we will actually bill them in our native currency.

Where can we get up to date exchange rate information and how do we use it?

The solution

The problem is actually two-fold. The first step is to get the currency data into a form you can use on your site. The second is the actually be able to use it.

I will cover the second stage first since it is the most rarely documented on the net out of the two.

Using exchange rates.

For the following examples I will use today's data from the European Central bank (2009-04-30).

These are all spot rates relative to the Euro, so whatever calculation we want to do we need to convert to the Euro first then convert to the destination currency. We can do a quick ballpark sanity check when developing by comparing on another online converter such as the one at xe.com.

GBP / 0.8933 = 1.1193 Euros Euros * 1.3275 = 1.4859 USD

Xe.com puts the GBP -> USD rate at approx 1.49, so this would suggest our calculation is correct.

This is all very well but its only the 'spot' rate. What we actually want is the rate that the user will be charged on conversion during checkout.

This is normally a couple of percent either side of the base rate to allow the company making the exchange to make a profit on the deal. If we add 2% to the final figure we will probably be pretty close.

We can do this by multiplying by 1.02 (102% to people without a maths background)

Retreiving exchange rate data.

There are many places to source exchange rate data from, some down to the 15 minute mark. This level of granularity is unnecessary for basic e-commerce use as its aimed for people buying and selling currency itself.

We will be amply served by the free rate feeds provided by many of the banks and financial institutions around the world.

A couple of links for these are as follows:

http://www.bsi.si/_data/tecajnice/dtecbs.xml
http://www.imf.org/external/np/fin/data/rms_rep.aspx
http://www.ecb.int/stats/exchange/eurofxref/html/index.en.html

For this article though, I will be using the feed from the European Central Bank.

The actual feed itself is available at http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml in XML format and looks similar to the following

<gesmes:Envelope> <gesmes:subject>Reference rates</gesmes:subject> <gesmes:Sender> <gesmes:name>European Central Bank</gesmes:name> </gesmes:Sender> <Cube> <Cube time="2009-04-30"> <Cube currency="USD" rate="1.3275"/> <Cube currency="JPY" rate="130.34"/> <Cube currency="BGN" rate="1.9558"/> . . <Cube currency="ZAR" rate="11.2426"/> </Cube> </Cube> </gesmes:Envelope>

There is also example code relying on the regex functions of PHP at http://www.ecb.int/stats/exchange/eurofxref/html/index.en.html#dev while it works, its not very elegant.

So lets see if we can improve on this...

<?php $feed=<<<EOL <gesmes:Envelope> <gesmes:subject>Reference rates</gesmes:subject> <gesmes:Sender> <gesmes:name>European Central Bank</gesmes:name> </gesmes:Sender> <Cube> <Cube time="2009-04-30"> <Cube currency="USD" rate="1.3275"/> <Cube currency="JPY" rate="130.34"/> <Cube currency="BGN" rate="1.9558"/> <Cube currency="CZK" rate="26.701"/> <Cube currency="DKK" rate="7.4484"/> <Cube currency="EEK" rate="15.6466"/> <Cube currency="GBP" rate="0.89335"/> <Cube currency="HUF" rate="289.73"/> <Cube currency="LTL" rate="3.4528"/> <Cube currency="LVL" rate="0.7093"/> <Cube currency="PLN" rate="4.3993"/> <Cube currency="RON" rate="4.1892"/> <Cube currency="SEK" rate="10.6915"/> <Cube currency="CHF" rate="1.5066"/> <Cube currency="NOK" rate="8.7245"/> <Cube currency="HRK" rate="7.4101"/> <Cube currency="RUB" rate="43.8630"/> <Cube currency="TRY" rate="2.1145"/> <Cube currency="AUD" rate="1.8146"/> <Cube currency="BRL" rate="2.8850"/> <Cube currency="CAD" rate="1.5786"/> <Cube currency="CNY" rate="9.0575"/> <Cube currency="HKD" rate="10.2881"/> <Cube currency="IDR" rate="14071.50"/> <Cube currency="INR" rate="66.2620"/> <Cube currency="KRW" rate="1696.88"/> <Cube currency="MXN" rate="18.2950"/> <Cube currency="MYR" rate="4.7259"/> <Cube currency="NZD" rate="2.3378"/> <Cube currency="PHP" rate="63.924"/> <Cube currency="SGD" rate="1.9620"/> <Cube currency="THB" rate="46.808"/> <Cube currency="ZAR" rate="11.2426"/> </Cube> </Cube> </gesmes:Envelope> EOL; header('Content-type: text/plain'); $xml = @simplexml_load_string($feed); // the ecb feed uses namespaces without referencing them, //we get many warnings if we don't supress them with @. $time=$xml->Cube->Cube->attributes()->time; echo $time."\n"; foreach ($xml->Cube->Cube->Cube as $value) { $currency[(string)$value['currency']]=(float)$value['rate']; } print_r($currency); ?>

Its not perfect, we have little error checking at present, but it works. You will notice the typecasting for the objects returned in the foreach loop, this is necessary to use them in a sensible way, otherwise we still have a simpleXML object which isn't usable as input to most other functions.

The feed is updated daily at approx 1415 local time for the ECB, so checking it any more frequently than this is pointless and is likely to just get you blacklisted on their servers.

Once we have the data in the variable it is trivial to do something like...

$rate=1/$currency['GBP']*$currency['USD'];

to get from one currency to another.

The 1/currency is needed since all the rates are from Euro *to* another rate and we need to go the opposite direction for the first step.

1/x is known as the reciprical of the number and is useful when you want to turn x/y into y/x.

©2009 AskFlib.com

Powered by TMI-CMS and Technomonk Industries