[JavaScript] クレジットカード番号から国際ブランドを特定する

前回に引き続きクレジットカードがテーマです。今回は決済画面などで入力されたクレジットカード番号がどの国際ブランであるかを調べるコードです。

ブランドを検出するロジックは前回と同じですので、ここではユーザーの入力と検出部分のつなぎ込みがメインテーマとなります。

クレジットカード番号の仕様

開始番号と桁数

前回と同じ表です。カード番号の冒頭数桁でカード会社を判定できるようになっています。例えば「4」でカード番号が始まっていればVISAであることがわかります。

国際ブランド 開始番号 桁数 セキュリティコード
VISA 4 13, 16 CVV(3桁)
MASTER Card 510000〜559999, 222100〜272099 16 CVC(3桁)
JCB 3528〜3589 16 CVV(3桁)
American Express 34, 37 15 CID(4桁)
Diners Club 300〜303574, 3095, 36, 38〜39 14 CVV(3桁)
  • この情報は主にWikipediaを参考にしています。誤りや古くなっている箇所などあればご指摘ください。

ブランドの検出方法

では前述のロジックを利用してブランドを検出してみます。単純にカード番号の先頭を取り出して比較するだけですね。

ちょっとだけ厄介なのは「aからbの間」の判定です。正規表現を利用しても良いのですが少し複雑になるのでここではbetween()という関数を用意しました。

const n = '4111111111111111'
const between = (value, min, max) => ((min <= Number(value)) && (Number(value) <= max))

if( n.substr(0,1) === '4' ){
  console.log('Visa')
}
else if( n.match(/^5[1-5]/) || between(n.substr(0,6), 222100, 272099) ){
  console.log('Master')
}
else if( between(n.substr(0,4), 3528, 3589) ){
  console.log('JCB')
}
else if( n.match(/^3[47]/) ){
  console.log('AMEX')
}
else if( between(n.substr(0,6), 300000, 303574) || n.substr(0,4) === '3095' || n.match(/^3[689]/) ){
  console.log('Diners Club')
}

ライブラリを利用して判定

手前味噌ですが先ほどのロジックをそのまま利用したライブラリ「creditcard-checkerjs」を使うともっとシンプルに記述できます。

Webブラウザ上で動かしたい場合はcreditcard-checker.min.jsをダウンロードして保存しておきます。あとは先ほどのライブラリをscriptタグで読み込んでおきcreditcard.cardtype()で判定するだけです。

<script src="creditcard-checker.min.js"></script>
<script>
  const number = '4111111111111111'
  switch( creditcard.cardtype(number) ){
    case creditcard.type.VISA:
      console.log('Visa')
      break
    case creditcard.type.MASTER:
      console.log('Master Card')
      break
    case creditcard.type.JCB:
      console.log('JCB')
      break
    case creditcard.type.AMEX:
      console.log('American Express')
      break
    case creditcard.type.DINERS:
      console.log('Diners Club')
      break

    case creditcard.type.UNKNOWN:
    default:
      console.log('?????')
      break
  }
</script>

サンプル「ほぼリアルタイムに国際ブランドを判定する」

動作サンプル

最初の表を参考にしながらカード番号を入力してみてください。特定できた時点でテキストボックスの右側にアイコンが表示されます。

コード

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>creditcard-checker.js example</title>
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <style>
    #brand{ font-size: 20pt; }
    #number{ width:200px; padding:5px; }
  </style>
</html>
<body>

<form>
  <span id="brand"></span>
  <input type="text" id="number" placeholder="XXXX-XXXX-XXXX-XXXX">
</form>

<script src="creditcard-checker.min.js"></script>
<script>
//---------------------------------------
// ブランドを特定する
//---------------------------------------
document.querySelector('#number').addEventListener('keyup', (e)=>{
  const number = document.querySelector('#number').value
  const brand  = document.querySelector('#brand')

  switch( creditcard.cardtype(number) ){
    case creditcard.type.VISA:
      brand.innerHTML = '<i class="fab fa-cc-visa"></i>'
      break
    case creditcard.type.MASTER:
      brand.innerHTML = '<i class="fab fa-cc-mastercard"></i>'
      break
    case creditcard.type.JCB:
      brand.innerHTML = '<i class="fab fa-cc-jcb"></i>'
      break
    case creditcard.type.AMEX:
      brand.innerHTML = '<i class="fab fa-cc-amex"></i>'
      break
    case creditcard.type.DINERS:
      brand.innerHTML = '<i class="fab fa-cc-diners-club"></i>'
      break

    case creditcard.type.UNKNOWN:
    default:
      brand.innerHTML = ''
      break
  }
})

//---------------------------------------
// submitイベントをキャンセル
//---------------------------------------
document.querySelector('form').addEventListener('submit', (e)=>{
  e.preventDefault()
})
</script>
</body>
</html>

参考ページ