01273 264503 info@mootpoint.org

I recently was tasked with integrating a currency convertor on a client’s WordPress website. The available plugins, while powerful, tended to have over-complicated UI’s with no ability to style the forms to match the site design. Would it not be possible to create a simple currency convertor form that we could style at will? Also, exchange rates change all the time, where can we get up to date rates?

Open Exchange Rates offers an API with free tier for a limited number of API queries. If we retrieve the rates daily with a scheduled task, and store them locally in the database, we only have to make one API request a day and won’t run into problems with rate limiting. Obviously, if you require more frequently updated rates, you may wish to sign up for a paid plan.

Firstly we need to sign up for an account at https://openexchangerates.org/signup and generate an app_id.

We’ll need a function in our theme’s functions.php file to download the latest rates and store them in the options table:

// Daily task which retrieves currency exchange rates and stores them in options
add_action ( 'update_currency_data_event', 'mp_update_currency_data' );

function mp_update_currency_data()  {
	// get the Open Exchange Rates app_id from an ACF custom field (or you could hard-code it)
	$app_id = get_field('open_exchange_rates_app_id', 'option');
	if ( $app_id ) {
		$api_url = 'https://openexchangerates.org/api/';
		$rates = false;
		$currencies = false;

		// get the latest rates
		$response = wp_remote_get( $api_url . 'latest.json?app_id=' . $app_id );
		if ( !is_wp_error( $response ) ) {
			if ( wp_remote_retrieve_response_code( $response ) == 200 ) {
				$body = json_decode( wp_remote_retrieve_body( $response ), true );
				$rates = $body['rates'];
			}
		}

		// get the list of currencies
		$response = wp_remote_get( $api_url . 'currencies.json?show_alternative=false&show_inactive=false&app_id=' . $app_id );
		if ( !is_wp_error( $response ) ) {
			if ( wp_remote_retrieve_response_code( $response ) == 200 ) {
				$body = json_decode( wp_remote_retrieve_body( $response ), true );
				$currencies = $body;
			}
		}

		// store the rates and names in options
		$data = array();
		if ( $rates && $currencies ) {
			foreach ( $rates as $currency_code => $rate ) {
				if ( isset( $currencies[$currency_code] ) ) {
					$data[$currency_code] = array(
						'name' => $currencies[$currency_code],
						'rate' => $rate
					);
				}
			}
			// sort the list by currency name
			uasort($data, function($a, $b) {
			    return $a['name'] <=> $b['name'];
			});

			update_option( 'mp_currency_data', $data, false );
		}
	}
} 

Of course, we’ll need to schedule this process daily:

// Schedule the update currency event
if ( !wp_next_scheduled('update_currency_data_event') ) {
	wp_schedule_event( time(), 'daily', 'update_currency_data_event' );
}

Then, we’ll need a function respond to a conversion request via the WC_Ajax API:

// Ajax function to convert currency
add_action( 'wp_ajax_nopriv_convert_currency', 'mp_convert_currency' );
add_action( 'wp_ajax_convert_currency', 'mp_convert_currency' );

function mp_convert_currency() {

	$amount = $_POST['amount'];
	$from_currency = $_POST['from_currency'];
	$to_currency = $_POST['to_currency'];

	$currency_data = get_option( 'mp_currency_data' );

	if ( isset( $currency_data[$from_currency] ) && isset( $currency_data[$to_currency] ) ) {
		$converted_amount = round( ( $amount / $currency_data[$from_currency]['rate'] ) * $currency_data[$to_currency]['rate'], 2);
		wp_send_json_success( $to_currency . ' ' . $converted_amount );
	} else {
		wp_send_json_error( 'Unable to convert.' );
	}
    
}

Now, we need to output the currency conversion form in a template:

<?php $currency_data = get_option( 'mp_currency_data' ); ?>
<form id="currency_converter_form" action="convert_currency" method="post">
    <input type="hidden" name="action" value="convert_currency">
    <div class="form-control">
        <label for="amount">Amount:</label>
        <input type="text" name="amount" id="amount" value="">
    </div>
    
    <div class="form-control">
        <label for="from_currency">From Currency:</label>
        <select name="from_currency" id="from_currency">
            <option value="">Currency</option>
            <?php if ( $currency_data ) : ?>
            <?php foreach ( $currency_data as $currency_code => $currency ) : ?>
            <option value="<?php echo $currency_code; ?>"><?php echo $currency['name']; ?></option>
            <?php endforeach; ?>
            <?php endif; ?>
        </select>
    </div> 
    <div class="form-control">
        <label for="to_currency">To Currency:</label>
        <select name="to_currency" id="to_currency">
            <option value="">Currency</option>
            <?php if ( $currency_data ) : ?>
            <?php foreach ($currency_data as $currency_code => $currency) : ?>
            <option value="<?php echo $currency_code; ?>"><?php echo $currency['name']; ?></option>
            <?php endforeach; ?>
            <?php endif; ?>
        </select>
    </div>   
    <div class="form-control">
        <button class="btn btn-primary" type="submit">Convert</button>
    </div>
</form>

In the same template, we’ll include a div which will be populated with the converted currency via Ajax:

<div id="converted_amount"></div>

And lastly, the same template will need some Javascript to make the Ajax call when the currency convertor form is submitted:

<script type="text/javascript">
    jQuery('#currency_converter_form').submit(ajaxSubmit);

    function ajaxSubmit() {
        var formData = jQuery(this).serialize();

        jQuery.ajax({
            type: "POST",
            url: "/wp-admin/admin-ajax.php",
            data: formData,
            success: function(response){
                jQuery("#converted_amount").html(response.data);
            }
        });

        return false;
    }
</script>

Now the converted amount should be output in the #converted_amount div when the submit button is clicked, without having to reload the page.