
CakePHPなどでクレジットカード番号をチェックする方法
2018/10/09
クレジットカードの番号、VisaとかMasterカードですと16桁の数字ですが、乱数で構成されていると思われがちですが、実はあれ「Luhn algorithm(ルーン・アルゴリズム)」という法則によって導き出されているのはご存知だったでしょうか?
ルーン・アルゴリズムについて
「ルーン・アルゴリズム」の法則
「ルーン・アルゴリズム」の法則は以下の通り。
- カード番号の奇数桁目を2倍にし、値が10以上になったら9を引く
- それぞれの数字を足す
- 2の結果が10の倍数になったら正しい番号。10の倍数で無ければ不正な番号
図にするとこんな感じ。
3566-0020-2036-0505 がカード番号だとします。
1 2 3 |
3 5 6 6 0 0 2 0 2 0 3 6 0 5 0 5 ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ 6+5+3+6+0+0+4+0+4+0+6+6+0+5+0+5 = 50 |
1) 奇数番目の数字を2倍(10以上だと-9する)、偶数番目はそのままとする
2) 全てを足す
3) 結果が10の倍数である「50」なので、3566-0020-2036-0505 は正しい番号である、とわかる
クレジットカード番号の意味
ちなみにそれぞれの桁の数字にも意味があります。
1ケタ目
最初の1桁:主要産業識別子 (MII:Major industry identifier)。カード発行者の業界を表します。
0:予備
1、2:航空
3:旅行・娯楽
4、5:銀行・金融
6:商品輸送・銀行
7:石油
8:通信
9:国ごとの割り当て分
2ケタ目
MIIを含む最初6桁:発行者識別番号(IIN:Issuer Identifier Number)。カード発行者の身元を表します。
主要クレジットカードのIIN
Visa | 4xxxxx |
---|---|
Mastercard | 51xxxx - 55xxxx |
Discover | 6011xx, 644xxx, 65xxxx |
Amex | 34xxxx, 37xxxx |
7ケタ目以降
7ケタ目~最後1ケタの前の数まで:カード口座番号。
最後の1ケタ
最後の1ケタ:チェックディジット。
と、いうような法則があるので、チェック用プログラムも書けます。
意外と単純。
プレーンPHP
[php]
function checkCard()
{
// 変数の初期化
$card = "";
$check = "";
// ポストデータをエスケープ
$_POST = array_map('htmlspecialchars', $_POST);
// データを一つにまとめる
for ($i=1; $i <= 4; $i++) {
$card .= $_POST['card_'.$i];
}
// 数値以外はエラーを返す。
if (!is_numeric($card)) {
return '半角数字で入力してください';
}
// 文字列を配列に分解
$card = str_split($card);
// 数字の数だけループする
for ($i=0; $i<16; $i++) {
// 奇数の場合のみ2倍する
if ($i % 2 == 0){
$card[$i] = $card[$i] * 2;
}
// 2桁の場合は分割して足す
if (mb_strlen( $card[$i] ) != 1){
$split = str_split($card[$i]);
$card[$i] = $split[0] + $split[1];
}
$check += $card[$i];
}
if ($check % 10 == 0) {
return '正しいクレジットカード番号です';
} else {
return 'クレジットカード番号が不正です';
}
}
[/php]
CakePHP
CakePHPでは、バリデーションルールにクレジットカード用に cc があります。
ruleのパラメータは「type」「deep」「regex」で、type を all とすると、全てのクレジットカード番号のタイプでチェックします。
deep にはTRUE もしくは FALSE をセットし、TRUEだと前述した「ルーン・アルゴリズム」によるチェックをを行います。
regrex は独自に正規表現を設定できます。
使い方は以下のように。こちらも単純ですね。
[php]
class Payment extends AppModel
{
var $validate = array(
'cc_number' => array(
array(
'rule' => 'numeric',
'message' => '『クレジットカード番号』は半角数字で入力してください',
'required' => true,
'allowEmpty' => false
),
array(
'rule' => array('cc', 'all', true, null),
'message' => '『クレジットカード番号』が不正です',
'required' => true,
'allowEmpty' => false
),
array(
'rule' => 'notEmpty',
'message' => '『クレジットカード番号』を入力してください',
'required' => true,
'allowEmpty' => false
),
),
);
}
[/php]
ZendFramework
さらに、ZendFrameworkではこんな感じで、バリデーションが可能です。
[php]
require_once 'Zend/Validate/Ccnum.php';
// インスタンス化
$validator = new Zend_Validate_Ccnum();
if ($validator->isValid($card_number) == TRUE) {
return '正しいクレジットカード番号です';
} else {
return 'クレジットカード番号が不正です';
}
[/php]
私は初めて知ったのですが、クレジットカードの判定が必要な際は参考にしてみてください。
[tgAmazonItemLookup asin="B00B66ZWMS" related="1"]