Asbestos Supply

2012-09-25 Crimes Against Internationalization

What's wrong with this snippet from Authorize.net's .NET SDK?

public CardPresentPriorAuthCapture(string transactionID, Decimal amount)
{
  this.SetApiAction(RequestAction.PriorAuthCapture);
  this.Queue("x_ref_trans_id", transactionID);
  this.Queue("x_amount", amount.ToString());
  ...

Did you get it yet? Think about that last line, amount.ToString() -- what's that going to do?

Let's see -- what's the meaning of $25.99? Well that's twenty-five dollars and ninety-nine cents. What's the meaning of €25.99? That's not as clear -- Europeans use "." where Americans use "," to denote thousands. Maybe it should be read €25.990; almost twenty six thousand Euros! Or perhaps it's a typo and that decimal point shouldn't be there at all, it's meaningless in the position it's in anyway, so perhaps the meaning is twenty-five-hundred and ninety-nine Euros.

Well sure enough, Authorize.net's API assumes that "." denotes decimals and "," denotes thousands. If the thread that calls into their SDK is in a European culture that .ToString() call will output 25,99. But when Authorize.net's API sees that request they parse it as twenty-five-hundred and ninety-nine dollars.

And that is a crime against internationalization. If you're writing an SDK please do not use .ToString() without a format provided. In this case, if Authorize.net has just added a couple more characters -- .ToString("0.0") -- the format would stay constant across cultures.