activemerchant / active_merchant

Active Merchant is a simple payment abstraction library extracted from Shopify. The aim of the project is to feel natural to Ruby users and to abstract as many parts as possible away from the user to offer a consistent interface across all supported gateways.
http://activemerchant.org
MIT License
4.54k stars 2.5k forks source link

Active merchant says Invalid card for a valid card #1452

Closed pamio closed 9 years ago

pamio commented 9 years ago

Hi, I have been facing this issue for sometime now and I have raised an SO question also, the link to which is http://stackoverflow.com/questions/26713398/activemerchant-says-invalid-credit-card-for-a-valid-card. First I thought that this is a problem with JCB cards but this also happens with master cards. So I'm not sure if there's a configuration problem or something else.

here is what I did

2.1.1 :056 > cc = CreditCard.new(:first_name => 'Steve',:last_name => 'Smith', :month => '9',:year => '2015',:number => '3088023605344101', :verification_value => '123') => #<ActiveMerchant::Billing::CreditCard:0x0000010a0d91d8 @first_name="Steve", @last_name="Smith", @month="9", @year="2015", @number="3088023605344101", @verification_value="123"> 2.1.1 :057 > cc.valid? => false 2.1.1 :058 > cc.errors => {"brand"=>["is required"], "number"=>[]}

Then i fed brand

2.1.1 :059 > cc = CreditCard.new(:first_name => 'Steve',:last_name => 'Smith', :month => '9',:year => '2015',:number => '3088023605344101', :verification_value => '123', :brand => 'jcb') => #<ActiveMerchant::Billing::CreditCard:0x00000109d886c8 @first_name="Steve", @last_name="Smith", @month="9", @year="2015", @number="3088023605344101", @verification_value="123", @brand="jcb"> 2.1.1 :060 > cc.valid? => false 2.1.1 :061 > cc.errors => {"number"=>[], "brand"=>["does not match the card number"]}

why should this happen ? I have already verified card numbers.

girasquid commented 9 years ago

The regular expression being used to check if the number is a jcb card is /^35(28|29|[3-8]\d)\d{12}$/ - the number you're supplying doesn't start with 35, so I'd guess that's why you're getting that error.

According to the page at http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29, the IIN range for JCB cards is 3528-3589.

I wonder if JCB has updated their IINs since that wikipedia page was updated - the PDF I found on that wikipedia page is five years old.

j-mutter commented 9 years ago

One of the sites you linked to in your Stack Overflow article has some conflicting information…

It has three numbers listed as JCB test cards:

But then farther down it says:

Credit Card Issuer | Starts With ( IIN Range ) | Length ( Number of digits )
...
JCB                  3528 to 3589                16

Maybe the 30 numbers are just test numbers? Where are you getting the number you're trying to use?

The other site shows that JCB has some 30 range numbers, (and that they also have 15 digit numbers) but doesn't have any sources to where they got this information. I can't find anything from JCB that confirms this either way :disappointed:

ntalbott commented 9 years ago

@pamio any follow up on the source of the 30 numbers? Or other sources we can use to correct the brand identification code?

pamio commented 9 years ago

I had these 30 series numbers given by my client and I'm not sure where he got the numbers from. For now Im using the following regex as a temporary solution to verify the cards

  def type
    if @card =~ /^5[1-5][0-9]{14}$/
      return SUPPORTED_CARD_BRANDS[:MASTERCARD]
    elsif @card.match(/^4[0-9]{12}([0-9]{3})?$/)
      return SUPPORTED_CARD_BRANDS[:VISA]
    elsif @card.match(/^3[47][0-9]{13}$/)
      return SUPPORTED_CARD_BRANDS[:AMEX]
    elsif @card =~ /^3(0[0-5]|[68][0-9])[0-9]{11}$/
      return SUPPORTED_CARD_BRANDS[:DINNERS]
    elsif @card =~ /^6011[0-9]{12}$/
      return SUPPORTED_CARD_BRANDS[:DISCOVER]
    elsif @card =~ /^(3[0-9]{4}|2131|1800)[0-9]{11}$/
      return SUPPORTED_CARD_BRANDS[:JCB]
    elsif @card =~ /^(5[06-8]|6)[0-9]{10,17}$/
      return SUPPORTED_CARD_BRANDS[:MAESTRO]
    else
      return nil
   end
end

I'll have the information on where I got that series from. Sorry for the delayed reply.

pamio commented 9 years ago

@j-mutter @ntalbott I got these from Authorise.net as test card numbers. Here are the other card numbers which Authorize.net sent in an email

  • American Express Test Card: 370000000000002

  • Discover Test Card: 6011000000000012

  • Visa Test Card: 4007000000027

  • Second Visa Test Card: 4012888818888

  • JCB: 3088000000000017

  • Diners Club/ Carte Blanche: 38000000000006

The irony is that when I validate these numbers, they are just validated fine. Of course the regex mentioned above handles it but the question now is if the IIN's are changed ? Authorize.net is a really valid source but not sure how to take this forward.

ntalbott commented 9 years ago

@pamio I guess I'd be really dubious about changing the regex based on a test card; I've seen some bizarre things used as test numbers :confounded:

Unless we can get confirmation via something halfway official, I think we'll leave the regex as-is in ActiveMerchant.

pamio commented 9 years ago

@ntalbott I do agree on that. But what I can't understand is that, how can a test card number have a different IIN than to that of a real credit card number. I mean, test cards are also some relevant card numbers but used just for testing, hence they follow the same patterns as any real card number. The numbers above are provided by Authorize.net which is a payment Gateway and I do not expect them to provide a test card number just like that without keeping standards in mind. However, due to the benefit of doubt, it would be better to verify before changing the regex. Let me see if I can help on this anyway. Thanks for you help guys.

ntalbott commented 9 years ago

@pamio what you say is totally logical in terms of test cards needing to reflect reality... but my experience at Spreedly with 70+ gateways and their test environments says that logic doesn't really enter into it unfortunately. Oh the stories I can tell, but to get the good ones we have to meet in person (can't put this stuff in writing!) and you have to buy me a :beer: or two :grin:

pamio commented 9 years ago

@ntalbott I would be more than happy to buy you a drink :) Will catch up sometime :)

ntalbott commented 9 years ago

Closing this for now; feel free to re-open if new evidence comes to light.

pamio commented 9 years ago

Sure @ntalbott