Packages
ex_money
2.0.2
6.1.1
6.1.0
6.0.0
6.0.0-rc.0
5.24.2
5.24.1
5.24.0
retired
5.23.0
5.22.0
5.21.0
5.20.0
5.19.2
5.19.1
5.19.0
5.18.0
5.17.2
5.17.1
5.17.0
5.16.1
5.16.0
5.15.4
5.15.3
5.15.2
5.15.1
5.15.0
5.14.1
5.13.0
5.12.4
5.12.3
5.12.2
5.12.1
5.12.0
5.11.0
5.10.0
5.9.0
5.8.0
5.7.4
5.7.3
5.7.2
5.7.1
5.7.0
5.6.0
5.5.5
5.5.4
5.5.3
5.5.2
5.5.1
5.5.0
5.4.1
5.4.0
5.4.0-rc.0
5.3.2
5.3.1
5.3.0
5.2.1
5.2.0
5.1.0
5.0.2
5.0.1
5.0.0
retired
4.4.3
4.4.2
retired
4.4.1
4.4.0
4.3.0
4.2.2
4.2.1
4.2.0
4.1.0
4.0.0
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.1
3.3.0
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.0
3.0.0
2.12.2
2.12.1
retired
2.12.0
retired
2.11.0
2.10.0
2.9.1
2.9.0
2.8.0
2.7.3
2.7.2
2.7.1
2.7.0
2.6.1
2.6.0
2.5.0
2.4.0
2.3.0
2.2.2
2.2.1
2.2.0
2.1.0
2.1.0-rc.1
retired
2.1.0-rc.0
retired
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.1.3
1.1.2
1.1.1
retired
1.1.0
1.0.0
1.0.0-rc.0
retired
0.9.0
retired
0.8.5
retired
0.8.4
retired
0.8.3
retired
0.8.2
retired
0.8.1
retired
0.8.0
retired
0.7.0
retired
0.6.2
retired
0.6.1
retired
0.6.0
retired
0.5.3
retired
0.5.2
retired
0.5.1
retired
0.5.0
retired
0.4.3
retired
0.4.2
retired
0.4.1
retired
0.4.0
retired
0.3.0
retired
0.2.0
retired
0.1.7
retired
0.1.6
retired
0.1.5
retired
0.1.4
retired
0.1.3
retired
0.1.2
retired
0.1.1
retired
0.1.0
retired
0.0.16
retired
0.0.15
retired
0.0.14
retired
0.0.13
retired
0.0.12
retired
0.0.11
retired
0.0.10
retired
0.0.9
retired
0.0.7
retired
0.0.6
retired
0.0.5
retired
0.0.4
retired
0.0.3
retired
0.0.2
retired
Money functions for operations on and localization of a money data type with support for ISO 4217 currencies and ISO 24165 digial tokens (crypto currencies).
Current section
Files
Jump to
Current section
Files
lib/money/exchange_rates/open_exchange_rates.ex
defmodule Money.ExchangeRates.OpenExchangeRates do @moduledoc """ Implements the `Money.ExchangeRates` for the Open Exchange Rates service. ## Required configuration: The configuration key `:open_exchange_rates_app_id` should be set to your `app_id`. for example: config :ex_money, open_exchange_rates_app_id: "your_app_id" or configure it via environment variable: config :ex_money, open_exchange_rates_app_id: {:system, "OPEN_EXCHANGE_RATES_APP_ID"} It is also possible to configure an alternative base url for this service in case it changes in the future. For example: config :ex_money, open_exchange_rates_app_id: "your_app_id" open_exchange_rates_url: "https://openexchangerates.org/alternative_api" """ @behaviour Money.ExchangeRates @open_exchange_rate_url "https://openexchangerates.org/api" @doc """ Update the retriever configuration to include the requirements for Open Exchange Rates. This function is invoked when the exchange rate service starts up, just after the ets table :exchange_rates is created. * `default_config` is the configuration returned by `Money.ExchangeRates.default_config/0` Returns the configuration either unchanged or updated with additional configuration specific to this exchange rates retrieval module. """ def init(default_config) do url = Money.get_env(:open_exchange_rates_url, @open_exchange_rate_url) app_id = Money.get_env(:open_exchange_rates_app_id, nil) Map.put(default_config, :retriever_options, %{url: url, app_id: app_id}) end @doc """ Retrieves the latest exchange rates from Open Exchange Rates site. * `config` is the retrieval configuration. When invoked from the exchange rates services this will be the config returned from `Money.ExchangeRates.OpenExchangeRates.config/1` Returns: * `{:ok, rates}` if the rates can be retrieved * `{:error, reason}` if rates cannot be retrieved Typically this function is called by the exchange rates retrieval service although it can be called outside that context as required. """ @spec get_latest_rates(Money.ExchangeRates.Config.t()) :: {:ok, Map.t()} | {:error, String.t()} def get_latest_rates(config) do url = config.retriever_options.url app_id = config.retriever_options.app_id retrieve_latest_rates(url, app_id) end defp retrieve_latest_rates(_url, nil) do {:error, app_id_not_configured()} end @latest_rates "/latest.json" defp retrieve_latest_rates(url, app_id) do retrieve_rates(url <> @latest_rates <> "?app_id=" <> app_id) end @doc """ Retrieves the historic exchange rates from Open Exchange Rates site. * `date` is a date returned by `Date.new/3` or any struct with the elements `:year`, `:month` and `:day`. * `config` is the retrieval configuration. When invoked from the exchange rates services this will be the config returned from `Money.ExchangeRates.OpenExchangeRates.config/1` Returns: * `{:ok, rates}` if the rates can be retrieved * `{:error, reason}` if rates cannot be retrieved Typically this function is called by the exchange rates retrieval service although it can be called outside that context as required. """ def get_historic_rates(date, config) do url = config.retriever_options.url app_id = config.retriever_options.app_id retrieve_historic_rates(date, url, app_id) end defp retrieve_historic_rates(_date, _url, nil) do {:error, app_id_not_configured()} end @historic_rates "/historical/" defp retrieve_historic_rates(%Date{calendar: Calendar.ISO} = date, url, app_id) do date_string = Date.to_string(date) retrieve_rates(url <> @historic_rates <> "#{date_string}.json" <> "?app_id=" <> app_id) end defp retrieve_historic_rates(%{year: year, month: month, day: day}, url, app_id) do case Date.new(year, month, day) do {:ok, date} -> retrieve_historic_rates(date, url, app_id) error -> error end end defp retrieve_rates(url) do case :httpc.request(String.to_charlist(url)) do {:ok, {{_version, 200, 'OK'}, _headers, body}} -> %{"base" => _base, "rates" => rates} = Poison.decode!(body) decimal_rates = rates |> Cldr.Map.atomize_keys() |> Enum.map(fn {k, v} -> {k, Decimal.new(v)} end) |> Enum.into(%{}) {:ok, decimal_rates} {_, {{_version, code, message}, _headers, _body}} -> {:error, "#{code} #{message}"} {:error, {:failed_connect, [{_, {_host, _port}}, {_, _, sys_message}]}} -> {:error, sys_message} end end defp app_id_not_configured do "Open Exchange Rates app_id is not configured. Rates are not retrieved." endend