diff --git a/.gitignore b/.gitignore index 3a6fe9c..558daab 100755 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ composer.lock /build /vendor + +/.idea/ \ No newline at end of file diff --git a/README.md b/README.md index 190753e..0ebebe2 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Require the package in `composer.json` ```json "require": { - "inacho/php-credit-card-validator": "1.*" + "habil/php-credit-card-validator": "1.*" }, ``` @@ -24,7 +24,7 @@ If you are using Laravel, add an alias in `config/app.php` ... 'View' => 'Illuminate\Support\Facades\View', - 'CreditCard' => 'Inacho\CreditCard', + 'CreditCard' => 'Sivax\CreditCard', ), ``` @@ -98,3 +98,6 @@ bool(false) Execute the following command to run the unit tests: vendor/bin/phpunit + +### Disclaimer +Many thanks to [inacho](https://github.com/inacho "inacho"). This repository based on it's [PHP Credit Card Validator](https://github.com/inacho/php-credit-card-validator "PHP Credit Card Validator") repository. \ No newline at end of file diff --git a/composer.json b/composer.json index dec0e6b..6eb2200 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "inacho/php-credit-card-validator", + "name": "habil/php-credit-card-validator", "type": "library", "description": "Validates popular debit and credit cards numbers against regular expressions and Luhn algorithm. Also validates the CVC and the expiration date", "keywords": ["creditcard", "creditcards", "debit", "credit", "card", "cards", "validator", "cvc", "laravel"], @@ -11,15 +11,16 @@ } ], "require": { - "php": ">=5.3.0", - "lib-pcre": ">=7.3" + "php": ">=5.6.0", + "lib-pcre": ">=7.3", + "ext-ctype": "*" }, "require-dev": { "phpunit/phpunit": "4.7.*" }, "autoload": { "psr-4": { - "Inacho\\": "src/" + "Sivax\\": "src/" } } } diff --git a/src/CreditCard.php b/src/CreditCard.php index ce8f5d6..c18c6f7 100644 --- a/src/CreditCard.php +++ b/src/CreditCard.php @@ -8,13 +8,19 @@ * @copyright 2014 Ignacio de Tomás (http://inacho.es) */ -namespace Inacho; +namespace Sivax; +/** + * Class CreditCard + * @package Sivax + */ class CreditCard { + /** + * Debit cards must come first, since they have more specific patterns than their credit-card equivalents. + * @var array + */ protected static $cards = array( - // Debit cards must come first, since they have more specific patterns than their credit-card equivalents. - 'visaelectron' => array( 'type' => 'visaelectron', 'pattern' => '/^4(026|17500|405|508|844|91[37])/', @@ -43,6 +49,13 @@ class CreditCard 'cvcLength' => array(3), 'luhn' => true, ), + 'mir' => array( + 'type' => 'mir', + 'pattern' => '/^220[0-4]/', + 'length' => array(16), + 'cvcLength' => array(3), + 'luhn' => true, + ), // Credit cards 'visa' => array( 'type' => 'visa', @@ -82,7 +95,7 @@ class CreditCard ), 'unionpay' => array( 'type' => 'unionpay', - 'pattern' => '/^(62|88)/', + 'pattern' => '/^(62|81)/', 'length' => array(16, 17, 18, 19), 'cvcLength' => array(3), 'luhn' => false, @@ -94,8 +107,28 @@ class CreditCard 'cvcLength' => array(3), 'luhn' => true, ), + 'uatp' => array( + 'type' => 'uatp', + 'pattern' => '/^1/', + 'length' => array(15), + 'cvcLength' => array(3), + 'luhn' => true, + ), + 'rupay' => array( + 'type' => 'rupay', + 'pattern' => '/^(60|6521|6522)/', + 'length' => array(16), + 'cvcLength' => array(3), + 'luhn' => true, + ), ); + /** + * @param string $number + * @param null $type + * + * @return array + */ public static function validCreditCard($number, $type = null) { $ret = array( @@ -119,23 +152,41 @@ public static function validCreditCard($number, $type = null) ); } + $ret['validation'] = array( + 'pattern' => !empty($type) && self::validPattern($number, $type), + 'length' => !empty($type) && self::validLength($number, $type), + 'luhn' => !empty($type) && self::validLuhn($number, $type), + ); + return $ret; } + /** + * @param string $cvc + * @param string $type + * + * @return bool + */ public static function validCvc($cvc, $type) { return (ctype_digit($cvc) && array_key_exists($type, self::$cards) && self::validCvcLength($cvc, $type)); } + /** + * @param int $year + * @param int $month + * + * @return bool + */ public static function validDate($year, $month) { $month = str_pad($month, 2, '0', STR_PAD_LEFT); - if (! preg_match('/^20\d\d$/', $year)) { + if (!preg_match('/^20\d\d$/', $year)) { return false; } - if (! preg_match('/^(0[1-9]|1[0-2])$/', $month)) { + if (!preg_match('/^(0[1-9]|1[0-2])$/', $month)) { return false; } @@ -147,9 +198,11 @@ public static function validDate($year, $month) return true; } - // PROTECTED - // --------------------------------------------------------- - + /** + * @param string $number + * + * @return string + */ protected static function creditCardType($number) { foreach (self::$cards as $type => $card) { @@ -161,16 +214,47 @@ protected static function creditCardType($number) return ''; } + /** + * @param string $bin + * + * @return string|null + */ + public static function determineCreditCardType($bin) + { + $type = self::creditCardType($bin); + + return !empty($type) ? $type : null; + } + + /** + * @param string $number + * @param string $type + * + * @return bool + */ protected static function validCard($number, $type) { - return (self::validPattern($number, $type) && self::validLength($number, $type) && self::validLuhn($number, $type)); + return (self::validPattern($number, $type) && self::validLength($number, $type) && self::validLuhn($number, + $type)); } + /** + * @param string $number + * @param string $type + * + * @return false|int + */ protected static function validPattern($number, $type) { return preg_match(self::$cards[$type]['pattern'], $number); } + /** + * @param string $number + * @param string $type + * + * @return bool + */ protected static function validLength($number, $type) { foreach (self::$cards[$type]['length'] as $length) { @@ -182,6 +266,12 @@ protected static function validLength($number, $type) return false; } + /** + * @param string $cvc + * @param string $type + * + * @return bool + */ protected static function validCvcLength($cvc, $type) { foreach (self::$cards[$type]['cvcLength'] as $length) { @@ -193,29 +283,40 @@ protected static function validCvcLength($cvc, $type) return false; } + /** + * @param string $number + * @param string $type + * + * @return bool + */ protected static function validLuhn($number, $type) { - if (! self::$cards[$type]['luhn']) { + if (!self::$cards[$type]['luhn']) { return true; } else { return self::luhnCheck($number); } } + /** + * @param string $number + * + * @return bool + */ protected static function luhnCheck($number) { $checksum = 0; - for ($i=(2-(strlen($number) % 2)); $i<=strlen($number); $i+=2) { - $checksum += (int) ($number{$i-1}); + for ($i = (2 - (strlen($number) % 2)); $i <= strlen($number); $i += 2) { + $checksum += (int) ($number{$i - 1}); } // Analyze odd digits in even length strings or even digits in odd length strings. - for ($i=(strlen($number)% 2) + 1; $i array( '5019717010103742', ), + 'mir' => array( + '2200524572467853', + '2201338708835472', + '2202410737880339', + '2203027541752030', + '2204500360586886', + ), // Credit cards 'visa' => array(