Sunday, November 17, 2013

Currency exchange for non-supported Paypal currencies in Drupal Ubercart Payments module

Problem

Paypal payments for Drupal Ubercart do not support just any currency. The list of supported currencies is pretty static: AUD, BRL, CAD, CHF, CZK, DKK, EUR, GBP, HKD, HUF, ILS, JPY, MXN, MYR, NOK, NZD, PHP, PLN, SEK, SGD, THB, TWD, USD.
Webshop is using LTL as its default currency and as you can see its not supported by Paypal. When cart is submitted - it submits full amount, just in EUR (Paypals default currency in websites settings). If default website setting is not set - it will be USD. Keep this in mind, so you could adjust your case accordingly.

Installation details

- Drupal 7
- Ubercart 7.x-3.5
- Paypal Website Payments Standard (WPS)
- Currency LTL

Research

There are a couple of suggestions online for INR, ZAR and RUB, but none of them suited my case. Research on suggested behavior gave no results, most of the answers led to 6.x solutions, one time patches on different D7 versions or bold suggestions to try Currency modules in Drupal. Thing is - all currency modules i've tested are outdated or have no connection to WPS, Cart or at least Language.

m0rg0t suggests to adjust main Store module and add a language filter. This would work if you wish to change all the prices when user changes current site language. This option is very user friendly, but in my case I needed all users to see same default store currency: LTL.

Another suggestion by Rahul suggests intercepting the WPS and putting currency converter in between. This solution makes some sense, but I was not able to find out how the from/to variables are populated. Also this suggestion is limited to order total amount and WPS. After some testing it resulted in convert(order_total)+tax+handling. As you can see it omits the handling fees and taxes. Suggestion is not complete, but it definitely gives you an idea.

After some investigation on uc_paypal module I found references to Paypal payment options. File ubercart/payment/uc_paypal/uc_paypal.module:
- DirectPayment ( 'METHOD' => 'DoDirectPayment')
- ExpressCheckout ('METHOD' => 'DoExpressCheckoutPayment')
- Website payment standard (function uc_paypal_wps_form($form, &$form_state, $order) {)

Implementation option 1

Change all amounts based on current site language. Edit file ubercart/uc_store/uc_store.module, locate the procedure uc_currency_format and adjust the following:

  // If the value is significantly less than the minimum precision, zero it.
  if ($prec > 0 && round(abs($value), $prec + 1) < pow(10, -$prec)) {
    $value = 0;
  }

  define('LTL',0.4528);
  $curr =  variable_get('uc_paypal_wps_currency', 'USD');
  if ($curr=='EUR') 
    {//$sign = 'lt'; 
     //$thou = ','; 
     //$dec = '.';    
     $value = $value / LTL; // conversion happens here
     //$sign_after = TRUE;
    };

  // Force the price to a positive value and add a negative sign if necessary.
  if ($value < 0) {
    $value = abs($value);
    $output .= '-';
  }

Change is done just before the modulus calculation. You may also uncomment the few commented lines, I only had use of just 1 of them.

Implementation option 2 (my choice)

Change only the amount passed to WPS, in this case site displays same currency independent of language selected. In order to adjust the amount for all payment methods just search for uc_currency_format and replace all the occurrences. In this case just edit the file ubercart/payment/uc_paypal/uc_paypal.module. Locate the function uc_paypal_wps_form and adjust the following:

define('LTL',3.4528);   // add this line somewhere at the top of the function
'handling_cart' => uc_currency_format($shipping / LTL, FALSE, FALSE, '.'),
'tax_cart' => uc_currency_format($tax / LTL, FALSE, FALSE, '.'),
$data['amount_' . $i] = uc_currency_format($item->price / LTL, FALSE, FALSE, '.');
$data['amount_1'] = uc_currency_format($order->order_total - $shipping - $tax / LTL, FALSE, FALSE, '.');

References

Geekport, "Converting INR to USD in during paypal checkout". http://www.geekport.in/samples/Drupal7-currency-convertor.php
Drupalize.me, "uc_currency_format". http://api.drupalize.me/api/drupal/function/uc_currency_format/7
m0rg0t suggestion on stackoverflow: http://stackoverflow.com/questions/7688662/mulitcurrency-for-ubercart-3-drupal-7
Rahul Nahar, "Drupal 7 Ubercart currency convert (ZAR to USD)". http://rahulnahar001.blogspot.com/2012/09/drupal-7-ubercart-currency-convert-zar.html