Jump to content

Module: Currency Conversion Service


ryan
 Share

Recommended Posts

Currency Conversion for ProcessWire
 
This module is designed for performing currency conversions among ~165 world currencies. It uses OpenExchangeRates.org (or compatible) for data so that currency exchange rates are always up-to-date.
 
It provides various API functions that you can use to convert from one currency to another. This is especially handy for generating rate tables in multiple currencies or giving users of your site the option to see prices in their currency.
Requires ProcessWire 2.4.0 or newer. To use the quick-installer from your modules screen, paste in ServiceCurrencyConversion.
 
Basic Example
$cc = $modules->get('ServiceCurrencyConversion'); 
$dollars = 100; // amount of currency we want to convert
$euros = $cc->convert('USD', 'EUR', $dollars); 
echo "<p>$dollars US Dollars equals $euros Euros</p>";  

For a live example of a currency conversion tool built with this module see the included convert.php file and test it out here.

  • Like 18
Link to comment
Share on other sites

  • 3 months later...

Ryan, this module is working really well for me on everything but one currency; mexian peso MXN. When parsing it reports this error:

Error: Exception: Can't find target currency. (in /var/www/clients/client2/web37/web/site/modules/ServiceCurrencyConversion/ServiceCurrencyConversion.module line 295)

#0 /var/www/clients/client2/web37/web/site/modules/ServiceCurrencyConversion/ServiceCurrencyConversion.module(310): ServiceCurrencyConversion->convertAdvanced('GBP', 'MXN', 250, 0, -1)
#1 /var/www/clients/client2/web37/web/site/templates/currency.php(16): ServiceCurrencyConversion->convert('GBP', 'MXN', 250)
#2 /var/www/clients/client2/web37/web/wire/core/TemplateFile.php(140): require('/var/www/client...')
#3 [internal function]: TemplateFile->___render()
#4 /var/www/clients/client2/web37/web/wire/core/Wire.php(359): call_user_func_array(Array, Array)
#5 /var/www/clients/client2/web37/web/wire/core/Wire.php(317): Wire->runHooks('render', Array)
#6 /var/www/clients/client2/web37/web/wire/modules/PageRender.module(337): Wire->__call('render', Array)
#7 /var/www/clients/client2/web37/web/wire/modules/PageRender.module(337): TemplateFile->render()
#8 [in

I'm using this to  code:

$cc = $modules->get('ServiceCurrencyConversion');
$dollars  = 250;   // this is what we're going to convert   -- ignore dollar naming convention
$currency = $page->symbol;   // 
$symbol = $cc->getSymbol("$currency");
$euros = $cc->convert('GBP', "$currency", $dollars);  //again, please ignore dodgy naming convention
$simple = $cc->convert('GBP', "$currency", '1');

?>

<div class="container">
	<div class="row">
		<div class="col-md-6">
		<?php echo "<h2> £1 = $symbol$simple .</h2>"; ?>
		</div>

	        <div class="col-md-6">
                <?php echo "<h3>That means £$dollars is going to buy you {$symbol}{$euros} .</3>"; ?>
                </div>



	</div>
</div>

please ignore my dodgy variable names.

Any idea why it has a problem with MXN please?

Link to comment
Share on other sites

And in this:

http://openexchangerates.org/api/latest.json?app_id=xxxxx (with your API key).

What happens if you edit the module file:

https://github.com/ryancramerdesign/ServiceCurrencyConversion/blob/master/ServiceCurrencyConversion.module#L293

to include a log of $rates and $toCurrency

public function convertAdvanced($fromCurrency, $toCurrency, $amount, $markup = 0.0, $decimals = -1) {
    error_log(print_r($rates,true));
    error_log("ToCURR:".$toCurrency);
    $rates = $this->getConvertedRatesTable($fromCurrency, $amount, $markup, $decimals); 
    if(!isset($rates[$toCurrency])) throw new WireException("Can't find target currency."); 
    return $rates[$toCurrency]; 
}
Link to comment
Share on other sites

Unfortunately that didn't seem to make any difference. I commented out the original function and added your adapted one in like so:

/**	public function convertAdvanced($fromCurrency, $toCurrency, $amount, $markup = 0.0, $decimals = -1) {
*		$rates = $this->getConvertedRatesTable($fromCurrency, $amount, $markup, $decimals); 
*		if(!isset($rates[$toCurrency])) throw new WireException("Can't find target currency."); 
*		return $rates[$toCurrency]; 
*	}
*/	
	
	public function convertAdvanced($fromCurrency, $toCurrency, $amount, $markup = 0.0, $decimals = -1) {
    error_log(print_r($rates,true));
    error_log("ToCURR:".$toCurrency);
    $rates = $this->getConvertedRatesTable($fromCurrency, $amount, $markup, $decimals); 
    if(!isset($rates[$toCurrency])) throw new WireException("Can't find target currency."); 
    return $rates[$toCurrency]; 
}

but still received the following for MXN:

Error: Exception: Can't find target currency. (in /var/www/clients/client2/web37/web/site/modules/ServiceCurrencyConversion/ServiceCurrencyConversion.module line 304)

#0 /var/www/clients/client2/web37/web/site/modules/ServiceCurrencyConversion/ServiceCurrencyConversion.module(319): ServiceCurrencyConversion->convertAdvanced('GBP', 'MXN', 250, 0, -1)
#1 /var/www/clients/client2/web37/web/site/templates/currency.php(16): ServiceCurrencyConversion->convert('GBP', 'MXN', 250)
#2 /var/www/clients/client2/web37/web/wire/core/TemplateFile.php(140): require('/var/www/client...')
#3 [internal function]: TemplateFile->___render()
#4 /var/www/clients/client2/web37/web/wire/core/Wire.php(359): call_user_func_array(Array, Array)
#5 /var/www/clients/client2/web37/web/wire/core/Wire.php(317): Wire->runHooks('render', Array)
#6 /var/www/clients/client2/web37/web/wire/modules/PageRender.module(337): Wire->__call('render', Array)
#7 /var/www/clients/client2/web37/web/wire/modules/PageRender.module(337): TemplateFile->render()
#8 [in
Link to comment
Share on other sites

Sorry I put that error log call before $rates was defined. Try moving those new lines after:

$rates = $this->getConvertedRatesTable($fromCurrency, $amount, $markup, $decimals); 

I'll also try installing the module here and see if I can replicate the error.

Link to comment
Share on other sites

OK, I have a quick fix for you. Replace the attached file. It was a problem with the parsing of currencies with two codes.

The Mexican Peso was:

MXN MXV Mexican Peso Mexican Unidad de Inversion (UDI) $

But if you change it to:

MXN Mexican Peso Mexican Unidad de Inversion (UDI) $

everything works fine. The reason I attached a replacement is that you need to make sure there are tabs in the correct places within that line.

Seems like there needs to be a change to the parsing logic here to account for currencies with more than one code, because right now, the code that is being sent to the Open Exchange Rates service is "MXN MXV". There are actually several currencies with the same problem.

if(substr_count($line, "\t") < 2) {
   list($code, $name) = explode("\t", $line); 
   $symbol = '';
} else {
   list($code, $name, $symbol) = explode("\t", $line); 
}

I am not sure what the extra code is about anyway, so maybe Ryan will Chime in. He will either need to remove the extra code from the txt file, or parse it out before sending to the service.

Github issue submitted: https://github.com/ryancramerdesign/ServiceCurrencyConversion/issues/1

currencies.txt

  • Like 4
Link to comment
Share on other sites

OK, I have a quick fix for you. Replace the attached file. It was a problem with the parsing of currencies with two codes.

The Mexican Peso was:

MXN MXV Mexican Peso Mexican Unidad de Inversion (UDI) $

But if you change it to:

MXN Mexican Peso Mexican Unidad de Inversion (UDI) $

everything works fine. The reason I attached a replacement is that you need to make sure there are tabs in the correct places within that line.

Seems like there needs to be a change to the parsing logic here to account for currencies with more than one code, because right now, the code that is being sent to the Open Exchange Rates service is "MXN MXV". There are actually several currencies with the same problem.

if(substr_count($line, "\t") < 2) {
   list($code, $name) = explode("\t", $line); 
   $symbol = '';
} else {
   list($code, $name, $symbol) = explode("\t", $line); 
}

I am not sure what the extra code is about anyway, so maybe Ryan will Chime in. He will either need to remove the extra code from the txt file, or parse it out before sending to the service.

Github issue submitted: https://github.com/ryancramerdesign/ServiceCurrencyConversion/issues/1

Adrian - superb!

I guess the problem with having a separate currency symbol on a different line could cause problems when you use the module round the other way and rather than asking for a conversion with symbols you can pass it country names to return symbols I think.. meaning it may bring back two.

but for me.. solver it perfectly.

Cheers

  • Like 1
Link to comment
Share on other sites

  • 9 months later...

If somebody needs this too. I wrote a Module Fieldtype InputfieldSelect suitable to ServiceCurrencyConversion.
It stores the 3-letter code and returns a multiple array value of all corresponding exchange rates.

    	array(
    	'code' => EUR // selected value
    	'name' => 'Euros', 
	'symbol' => '€', 
	'x' => [USD exhcange rate], 
	'updated' => 2015-01-14-14:45, 
	'AED' => array(
		'name' => 'UAE Dirham', 
		'symbol' => '', 
		'x' => [EUR exchange rate], // source = selected value
		'amount' => [your amount in UAE Dirham]
		), 
	'[currency code]' => array(
		...and so on...
		),
		.. and so on...
	);

There is a small issue in the currencies.txt file. Module cannot handle double entries like:

UYU UYI    Peso Uruguayo Uruguay Peso en Unidades Indexadas    $U

this should be changed to

UYU    Peso Uruguayo    $U
UYI    Uruguay Peso en Unidades Indexadas    

Other solution is to make the module able to handle this.

Here comes the FieldtypeSelectCurrency. Have fun :)


FieldtypeSelectCurrency.module

Link to comment
Share on other sites

@adrian
sorry I didn't read all posts of the topic. I fixed the issue in a german translation.

There is also a currency missing.
ZMK    Zambian Kwacha is not in use anymore. It was replaced by ZMW in 2013 (1000:1).
Possible to keep ZMK but ZMW should be added.
 

Link to comment
Share on other sites

  • 2 years later...

I want to use this lovely little converter to search a given textarea field for all mentions of currency amounts, convert each of those to another currency, and then show both. In other words, taking:

Quote

"...the rate is €40 for 40 minutes, €70 for 80 minutes..."

and turning that into:

Quote

"...the rate is €40 ($48) for 40 minutes, €70 ($83) for 80 minutes..." 

(The usd amount, obviously, would be filled in by the converter.)

After dozens of code variations and attempted angles of attack, I feel like I am close with this—but it is not quite working.

$cc = $modules->get('ServiceCurrencyConversion');
$text = $page->body;
$regex='/\x{20AC}\d+(\.\d{2})?/u';
$text = preg_replace($regex, '$0 ($' . $cc->convert("EUR", "USD", str_replace('€;', '', $regex)) . ')', $text);
echo $text;

It does no actual converting. I end up with just the euro amount repeating itself in parentheses:

Quote

"...the rate is €40 (€40) for 40 minutes, €70 (€70) for 80 minutes..." 

I figured the cc_convert only works on numerical amounts, so I need to strip the currency symbol before I can perform the conversion, but am having a devil of a time doing so. (And, yes, I have tried all sorts of Unicode, UTF, and HTM Entity encodings in place of that '€' to no avail.) 

For the record, I am, shall we say, not very handy with regex (it took my a day and half to arrive at that working $regex variable).

(As a cherry in top, I'd also like to round output amount, which I haven't yet even tried to work into the code.)

Any advice?

Link to comment
Share on other sites

11 hours ago, Reid Bramblett said:

For the record, I am, shall we say, not very handy with regex

My regex is rather weak also, but I think this will work...

$cc = $modules->get('ServiceCurrencyConversion');
$text = $page->body;
$regex = '/\x{20AC}([0-9]+\.?[0-9]+)/u';
$text = preg_replace_callback(
    $regex,
    function($matches) use ($cc) {
        $dollars = number_format($cc->convert('EUR', 'USD', $matches[1]), 0);
        return "{$matches[0]} (\${$dollars})";
    },
    $text
);
echo $text;

Would makes sense to put this into a simple Textformatter module and use it that way. See TextformatterNewlineBR for a basic example to start from.

  • Like 1
Link to comment
Share on other sites

Thanks, Robin. Works a treat.

I had tried fiddling with the number_format as well, but didn't really understand it.

I did, however, go back and tweak the regex statement so that it would catch single-digit amounts, too, as well as amounts with or without a two-place decimal amount (the "cents"). 

Link to comment
Share on other sites

  • 1 year later...

I'm using this piece of code from the convert.php demo page  

  $cc = $modules->get('ServiceCurrencyConversion'); 
    $names = $cc->getNames(); // names of currencies, indexed by 3-digit codes
    $amount = '';
    $options = '';
    foreach($names as $code => $name) {
        $options .= "<option value='$code'>$code: $name</option>";
    }
    $optionsTo = $options; 



    echo "<select name='to' onchange='this.form.submit()'>";
        echo "<option>Select currency</option>";
        echo $optionsTo;
    echo "</select><input type='submit' name='submit' value='Convert' /></p>";

I'm getting all possible currencies as a dropdown.
How do I limit the choices of the options to my selection of relevant currencies (e.g. EUR, USD, GBP)?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...