Blog

printf and Octal Values (2009-08-13)

We came across a strange issue while using ActiveMerchant to connect Moneris’ eSelect Plus payment gateway in one of our projects. ActiveMerchant raised an exception every time an order had ‘08’ or ‘09’ as the credit card expiry month.

The culprit was the way ActiveMerchant uses sprintf to format the month value before sending it to the payment gateway. In the file lib/active_merchant/billing/gateways/moneris.rb (around line 80):

1 def expdate(creditcard)
2   sprintf("%.4i", creditcard.year)[-2..-1] + 
3                 sprintf("%.2i", creditcard.month)
4 end

Let’s test that in irb.


>> sprintf("%.2i", '06')
=> "06"	
	
>> sprintf("%.2i", '07')
=> "07"

>> sprintf("%.2i", '10')
=> "10"
	
>> sprintf("%.2i", '08')
ArgumentError: invalid value for Integer: "08"
	from (irb):1:in `sprintf'
	from (irb):1
	from :0

>> sprintf("%.2i", '09')
ArgumentError: invalid value for Integer: "09"
	from (irb):2:in `sprintf'
	from (irb):2
	from :0

Weird, isn’t it?

It seems like sprintf won’t accept values ‘08’ and ‘09’. This ruby-talk message explains why. The leading zero tell Ruby to interpret 8 and 9 as octal numbers. Anything above 7 is obviously not a valid octal number.

For example:


irb(main):005:0> 07
=> 7

irb(main):006:0> 08
SyntaxError: compile error
(irb):6: Illegal octal digit
	from (irb):6
	from :0

The solution is quite simple: just make sure you cast the expiry month as an integer (using to_i) before creating an ActiveMerchant credit card object.

» posted by Alexandre Grégoire on 2009-08-13 - permalink

« go back