SaaS CMS has officially launched! Learn more now.

Son Do
Dec 31, 2016
  3421
(1 votes)

EPiServer Commerce: updating currency exchange rates automatically

Simple exchange rates updater automatically.


Why we need update exchange rates automatically

Currency exchange rates are changed everyday or hourly. This is quite important, our commerce site also need to update them to correct product price, shipping cost, ... more often.

How can we do

- Currency exchange rates source: in this sample, I used source from http://fixer.io/ - it's free and simple. You can chose whatever source if you feel trust.

- We have EPiServer schedule job - this is called and run in the background at preset time intervals (for more information, you can go here). So we could write a schedule job to update our task.

Step by step

Step 1: In your project site, create a class, name it as ExchangeRatesUpdateJob.cs.

This class will inherit from ScheduleJobBase.


[ScheduledPlugIn(
    DisplayName = "Exchange Rates update job",
    Description = "This job update exchange rates.")]
public class ExchangeRatesUpdateJob : ScheduledJobBase
{
    public override string Execute()
    {
        return "Exchange Rate update Job was finished.";
    }
}

This class is same as document I mentioned above.

Step 2: using CurrencyManager to update Exchange rates.


[ScheduledPlugIn(
    DisplayName = "Exchange Rates update job",
    Description = "This job update exchange rates.")]
public class ExchangeRatesUpdateJob : ScheduledJobBase
{
    [NonSerialized]
    private static readonly ILogger _log = LogManager.GetLogger(typeof(ExchangeRatesUpdateJob));
        
    public override string Execute()
    {
        string message = string.Empty;
        int records = UpdateExchangeRate(out message);
        return $"{records.ToString()} currencies were updated. {message}. Exchange Rate update Job was finished.";
    }
        
    private static int UpdateExchangeRate(out string message)
    {
        message = string.Empty;
        _log.Information("Starting to update exchange rate job.");
        var processedCurrency = 0;
        var dto = CurrencyManager.GetCurrencyDto();
            
        var currencyCodeIdMapping = dto.Currency.ToDictionary(c => c.CurrencyCode, c => c.CurrencyId);

        try
        {
            foreach (var code in currencyCodeIdMapping.Keys)
            {
                int fromCurrencyId;
                currencyCodeIdMapping.TryGetValue(code, out fromCurrencyId);

                try
                {
                    var uri = $"http://api.fixer.io/latest?base={code}";
                    using (var client = new WebClient())
                    {
                        var json = client.DownloadString(uri);
                        dynamic d = JObject.Parse(json);

                        DateTime exchangeDate = d.date; 

                        foreach (var rate in d.rates)
                        {
                            string toCurrencyCode = rate.Name;
                            int toCurrencyId;
                            if (currencyCodeIdMapping.TryGetValue(toCurrencyCode, out toCurrencyId))
                            {

                                var currencyRate = dto.CurrencyRate.NewCurrencyRateRow();
                                currencyRate.FromCurrencyId = fromCurrencyId;
                                currencyRate.ToCurrencyId = toCurrencyId;

                                currencyRate.EndOfDayRate = currencyRate.AverageRate = rate.Value;
                                currencyRate.CurrencyRateDate = exchangeDate;
                                currencyRate.ModifiedDate = DateTime.Now;
                                dto.CurrencyRate.AddCurrencyRateRow(currencyRate);
                                currencyRate.AcceptChanges();
                            }
                        }

                        dto.CurrencyRate.AcceptChanges();
                    }
                }
                catch (Exception ex)
                {
                    message += "Cannot update currency {code}. ";
                    _log.Error("Cannot update currency {code}.", ex);
                    continue;
                }

                dto.AcceptChanges();
                processedCurrency++;
                _log.Information($"{code} rates were updated");
            }
        }
        catch (Exception ex)
        {
            _log.Error("The job could not be completed. ", ex);
        }
        return processedCurrency;
    }
}

Step 3: rebuild solution, reset your site to add our new Schedule job to system.

Navigate to CMS/Admin menu, we will see our schedule job in left panel.

Exchange rates schedule job

Click on Start Manually to get first exchange rates.

Step 4: Set Active = true, in this sample, we will set schedule run everyday in 12.00 am.

Setting Exchange rates schedule job

So our job was FINISHED and this job will update exchange rates everyday to our site :)

You could download this file from my github.

Hope this post help your works.

/Son Do

Dec 31, 2016

Comments

valdis
valdis Jan 1, 2017 07:45 PM

Hi,

Nice. I would add my 2 cents:

1) you can (from v 10.3) inject ILogger interface in job via constructor injection

2) I would refactor so that *actual* exchange rate logic in somewhere outside - in some service or whatever, and scheduled job acts only as shell, as triggering mechanism that will call that service. This could make it easier to create unit/integration tests.

Jeroen Stemerdink
Jeroen Stemerdink Jan 2, 2017 10:11 AM

Hi Son, I actually created a NuGet package for this about a year ago, with two services/providers, Fixer and CurrencyLayer.

You could also use a different service by creating a different provider, see my post from last year for instructions how to do that.

Son Do
Son Do Jan 3, 2017 01:30 AM

@Valdis: thanks, I will update sample code for this.

@Jeroen: great to see your post and your github repo (y). You wrote out what I plan to do, this makes me feel good with currency area. Thank you.

Please login to comment.
Latest blogs
Creating Custom Actors for Optimizely Forms

Optimizely Forms is a powerful tool for creating web forms for various purposes such as registrations, job applications, surveys, etc. By default,...

Nahid | Jul 16, 2024

Optimizely SaaS CMS Concepts and Terminologies

Whether you're a new user of Optimizely CMS or a veteran who have been through the evolution of it, the SaaS CMS is bringing some new concepts and...

Patrick Lam | Jul 15, 2024

How to have a link plugin with extra link id attribute in TinyMce

Introduce Optimizely CMS Editing is using TinyMce for editing rich-text content. We need to use this control a lot in CMS site for kind of WYSWYG...

Binh Nguyen Thi | Jul 13, 2024

Create your first demo site with Optimizely SaaS/Visual Builder

Hello everyone, We are very excited about the launch of our SaaS CMS and the new Visual Builder that comes with it. Since it is the first time you'...

Patrick Lam | Jul 11, 2024

Integrate a CMP workflow step with CMS

As you might know Optimizely has an integration where you can create and edit pages in the CMS directly from the CMP. One of the benefits of this i...

Marcus Hoffmann | Jul 10, 2024

GetNextSegment with empty Remaining causing fuzzes

Optimizely CMS offers you to create partial routers. This concept allows you display content differently depending on the routed content in the URL...

David Drouin-Prince | Jul 8, 2024 | Syndicated blog