Ecommerce

Currency exchange for UPS carrier


Reading Time: 4 minutes

UPS shows the carrier price according to its origin country. If the product is sent is from Sweden to the USA, the carrier price is shown in SEK instead of USD and this becomes a real problem. For that reason, it is necessary to convert that currency before we show to the user.

Hello, everyone. In this blog post I’ll explain you a problem I faced some days ago in a project with Solidus when I was trying to show the shipping rates for UPS. To give you a little context, I’ll give you a quick explanation:

EasyPost currency convertion with UPS

Currently, I’m working on an eCommerce project in which we have different sellers from around the world (Germany, Australia, India, New Zealand, Sweden, Spain, among others). In this project, I’m using the Solidus gem to build our eCommerce and the solidus_easypost gem that handler all the carries. In this case, the carriers that we use are USPS, DHL, FedEx, and UPS.

When I made some tests about shipments from India to the USA, I realized that the cost for this package was too expensive. This behavior only happened with this carrier (I thought that something was wrong with the EasyPost implementation), so I made a lot of tests with sellers from around the world and realized that this was happening only with shippings from Sweden or India to the USA.

After I made tests directly in the UPS website, I noticed that this was because they were showing the currency from the country of origin. So that 1874.00 that they showed as the shipping cost weren’t USD, but actually INR. In the image below, the EasyPost gem showed us six different carries for this package. (In FedEx options, the cost varies 17ish dollars; but in the next options, we can see that the costs for the same package are too high — even 10 times more than the cost of the product).

Concurrency gem info

To handle the currency conversion, I added the concurrency gem.

“Concurrency is a lightweight gem that can be deployed for foreign exchange and currency conversion operation complying with the latest rates provided by The Free Currency Converter API.”

“Concurrency is a lightweight gem that can be deployed for foreign exchange and currency conversion operation complying with the latest rates provided by The Free Currency Converter API. It should be noted that the rates provided by the parent API are refreshed every 30 minutes and are not in real-time.” — @naman2202

This gem can implement the currency conversion operation for the following national currencies:

  • AUD – Australian Dollar
  • BGN – Bulgarian Lev
  • BRL – Brazilian Real
  • CAD – Canadian Dollar
  • CHF – Swiss Franc
  • CNY – Chinese Yuan
  • CZK – Czech Koruna
  • DKK – Danish Krone
  • GBP – British Pound
  • HKD – Hong Kong Dollar
  • HRK – Croatian Kuna
  • HUF – Hungarian Forint
  • IDR – Indonesian Rupiah
  • ILS – Israeli New Shekel
  • INR – Indian Rupee
  • JPY – Japanese Yen
  • KRW – South Korean Won
  • MXN – Mexican Peso
  • MYR – Malaysian Ringgit
  • NOK – Norwegian Krone
  • NZD – New Zealand Dollar
  • PHP – Philippine Peso
  • PLN – Polish Zloty
  • RON – Romanian Leu
  • RUB – Russian Ruble
  • SEK – Swedish Krona
  • SGD – Singapore Dollar
  • THB – Thai Baht
  • TRY – Turkish Lira
  • USD – United States Dollar
  • ZAR – South African Rand

Concurrency configuration

So, I needed to add the gem into the project:

gem ‘concurrency’

Then, put:

bundle install

Getting your ENV VARS

Once I had the gem added into the project, I needed to create a new file called config/initializers/concurrency.rb. In this file, I created the configuration that the concurrency gem needs to work properly.

Concurrency.configure do |config|
  config.api_key = ENV['CONCURRENCY_APIKEY']
  config.url = ENV['CONCURRENCY_URL']
end

The config.url is the endpoint which we are making reference if we create a free API, you need to put the https://free.currencyconverterapi.com/api/v6/convert. Otherwise, you need to put https://api.currconv.com/api/v7/convert.

Once we add the config file, we need to decorate the estimator.rb model from the solidus_easypost (this file is responsible to get all the rates). For this validation, we have to compare the currency from the origin country of the product vs the destination country. If this condition is true, the concurrency gem did its job!

We have to compare the currency from the origin country of the product vs the destination country. If this condition is true, the concurrency gem did its job!

app/models/solidus_easypost/estimator_decorator.rb

Here we create a new method which is responsible to do the currency conversion:

def currency_convertion(package, rate)
  return if package.currency == rate.currency
  converted_rate = Concurrency.convert(rate.rate.to_f, rate.currency, 'USD')
  cost = converted_rate if converted_rate.present? && converted_rate.is_a?(Float)
  cost
end

On line 3, ‘Concurrency.convert(rate.rate.to_f, rate.currency, ‘USD’)’, the first argument that we pass is the rate that we want to convert (in our case it would be 1874.00). The second argument would be current currency (in this case is INR), and the USD is the currency that we want to convert our value: Concurrency.convert(amount_to_be_converted, convert_from_currency, convert_to_currency).

EasyPost Model decorator

There is a method called shipping_rates in the estimator.rb model, in this part, EasyPost builds the object to retrieve the rates. Here, we’ll call our method created above.

if rates.any?
  rates.each do |rate|
    spree_rate = ::Spree::ShippingRate.new(
      name: "#{rate.carrier} #{rate.service}",
      cost: currency_convertion(package, rate) || rate.rate,
      easy_post_shipment_id: rate.shipment_id,
      easy_post_rate_id: rate.id,
      shipping_method: find_or_create_shipping_method(rate)
     )
     shipping_rates << spree_rate if spree_rate.shipping_method.available_to_users?
end

We only call the currency_conversion(package, rate) method with the parameters that they need.

With this single method, we make the currency conversion after the gem does that: we show the cost of the package to the user in USD.

With this single method, we make the currency conversion after the gem does that: we show the cost of the package to the user in USD.

There you go! If you face a similar situation in the future you can follow this approach. I hope I’ll give you a general idea of how to deal with it!

BTW, if it is your first time working with solidus EasyPost, I recommend an amazing blog post which will explain how to get started with this gem → Setting Up EasyPost on Solidus.

Thanks for reading!

@SamanthaBello, Software Engineer at MagmaLabs.

Ecommerce
Raising the Bar for Ecommerce: The Omni-Channel Approach to Customer Experience
Ecommerce
IRCE recap: Experimental retail, ecommerce UX and personas creation
Ecommerce
Setting Up EasyPost on Solidus
Copy link
Powered by Social Snap