決済

クレジットカード番号のチェック

投稿日:2022年2月15日 更新日:

クレジットカード番号は、各種ブランド(VISA/MASTERCARD/JCB/AMEXなど)によって異なる番号が付与されます。クレジットカード番号には、チェックデジットが含まれていて、正当性を確認することができます。

■ クレジットカード番号の体系

クレジットカード番号の体系は、国際標準規格(ISO/IEC 7812)で決められています。
最後の桁には、チャックデジットと呼ばれる数字が付与され、クレジットカード番号の正当性を確認できます。

・BIN(6桁)
  発行者識別番号であり、ブランド(VISA/MASTERCARD/JCB/AMEXなど)毎に決められている値

・口座番号(最大12桁)
  ブランド(VISA/MASTERCARD/JCB/AMEXなど)が付与する値

・チェックデジット(1桁)
 決められたアルゴリズム(Luhnアルゴリズム)でチェックが正常となるために付与される値


ちなみに、クレジットのICカードの規格であるEMVでは、TLVのTAG 0x5Aがクレジットカード番号(PAN)となっています。

https://emvlab.org/emvtags/?number=5A

NameDescriptionSourceFormatTemplateTagLengthP/C
Application Primary Account Number (PAN)Valid cardholder account numberICCcn var. up to 1970 or 775A0–10primitive

■ クレジットカード番号のチェックアルゴリズム

Luhnアルゴリズムを以下を参考にPythonでプログラミングしてみました。

https://ja.wikipedia.org/wiki/Luhn%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0

クレジットカード番号からブランド名を取得するようにしています。
以下のクレジットカード番号のBINを判定しています。

https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AC%E3%82%B8%E3%83%83%E3%83%88%E3%82%AB%E3%83%BC%E3%83%89%E3%81%AE%E7%95%AA%E5%8F%B7


テストのクレジットカード番号は、以下のPAYJPのものを使いました。
(ただし、一部、上記のBINの定義があとで追加されているようで、ブランド名が取得できないものもあります)

https://pay.jp/docs/testcard

# -*- coding: utf-8 -*-
import sys
import os

#
# ブランド名取得関数
#
def GetBrand(pan):

    name = ''

    # ブランド毎のBINは、以下を参考とした
    # https://ja.wikipedia.org/wiki/%E3%82%AF%E3%83%AC%E3%82%B8%E3%83%83%E3%83%88%E3%82%AB%E3%83%BC%E3%83%89%E3%81%AE%E7%95%AA%E5%8F%B7
    brand_list = [['VISA',[[4]]],\
                    ['JCB',[[3528,3589]]],\
                    ['MASTERCARD',[[510000,559999],[222100,272099]]],\
                    ['DISCOVER',[[60110],[60112,60114],[601174,601179],[601186,601199],[644,649],[65]]],\
                    ['DINARS',[[300,303574],[3095],[36],[38,39]]],\
                    ['AMEX',[[34],[37]]]]

    for brand in brand_list:
        name=brand[0]
        id_list = brand[1]
        for id in id_list:
            if len(id) > 1:
                lower = id[0]
                upper = id[1]

                size = max(len(str(lower)),len(str(upper)))
                pan_head=pan[:size]

                lower_str=str(lower).ljust(size, '0')
                upper_str=str(upper).ljust(size, '0')

                if int(pan_head) >= int(lower_str) and int(pan_head) <= int(upper_str):
                    return name 
            else:
                lower = id[0]
                size = len(str(lower))
                pan_head=pan[:size]
                if int(pan_head) == lower:
                    return name 
    return ''

#
# クレジットカード番号チェック関数
# ⇒ 判定結果とブランド名を返す
#
def CheckPan(pan):
    sum = 0
    name = ''

    # PAN文字列が数字で、19桁以下かをチェック
    if not pan.isdecimal() or len(pan) > 19:
        return False

    # PAN文字列を逆にして1桁づつ取得
    i = 1
    for degit in reversed(pan):

        degit = int(degit)

        # 桁が偶数番かをチェック
        if i%2 == 0: 

            # 偶数番のとき2倍する
            degit *= 2

            # 10以上(桁あふれ)した場合
            if degit > 9:

                # 各桁を足し合わせる
                sum_tmp = 0
                for part in str(degit):
                    part = int(part)
                    sum_tmp += part
                degit = sum_tmp

        # 加算            
        sum += degit
        i+=1

    # 10割った余りが0なら正常
    if (sum % 10) == 0:

        # ブランド名を取得
        name=GetBrand(pan)

        return True,name
    else:
        return False,name



if __name__ == '__main__':

    # テストカード番号
    # PAYJPのテストカード番号を使う
    #   https://pay.jp/docs/testcard

    print(CheckPan('4242424242424242'))
    print(CheckPan('4012888888881881'))
    print(CheckPan('5555555555554444'))
    print(CheckPan('5105105105105100'))
    print(CheckPan('3530111333300000'))
    print(CheckPan('3566002020360505'))
    print(CheckPan('378282246310005'))
    print(CheckPan('371449635398431'))
    print(CheckPan('38520000023237'))

     # ブランド名(Dinars)が判定できない(BINが追加されている思われる)
    print(CheckPan('30569309025904'))    

    # ブランド名(Discover)が判定できない(BINが追加されている思われる)
    print(CheckPan('6011111111111117'))   

    print(CheckPan('6011000990139424'))

■ まとめ 

チェックデジットがあるからといって、クレジットカード番号を安易にチェックすると、逆に、弊害となる場合もあり得ます。

100%、クレジットカード番号の最後に下位1桁をチェックデジットとして扱っているとは言えないからです。
確実に、チェックデジットを付与していると特定できるブランドだけで実施できるのであればよいですが、そうではない場合、チェックデジットを使ったクレジットカード番号のチェックは行わないのが無難です。

実際には、カード発行者側のシステムにおいて決済を実行する際に、 チェックデジットを使ったクレジットカード番号のチェック が実施されているものと考えられます。



-決済

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

オーソリ

ネットワークを介したクレジットカードや銀行口座引き落としによる決済とは、「オーソリ」と呼ばれる一つの電文によって行われます。 ■ オーソリ オーソリとは、「承認」(Authorization)の略語で …

カード決済

フィンテック(FinTech)とは、消費者がモノを買うという作業=決済を、ITを使って自動化することを言います。その中で、カードを使うカード決済は、ずっと昔からある決済手段であり、フィンテックの基本で …

デジタル通貨

デジタル通貨について、解説します。以下について、知ることができます。  ・通貨とは ・通貨がデジタル化されるということ ・何が変わるのか ■通貨とは 貨幣(Money)とは、個人間、企業間、個人と企業 …