Skip to content

Commit 365ea79

Browse files
committed
Fixes #17 Card number should be numeric. Do strip non numeric characters from card number, allow only spaces
1 parent ed9a3b8 commit 365ea79

File tree

6 files changed

+112
-25
lines changed

6 files changed

+112
-25
lines changed

src/Cards/Card.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use LVR\CreditCard\Exceptions\CreditCardLengthException;
1010
use LVR\CreditCard\Exceptions\CreditCardPatternException;
1111
use LVR\CreditCard\Exceptions\CreditCardChecksumException;
12+
use LVR\CreditCard\Exceptions\CreditCardCharactersException;
1213

1314
abstract class Card
1415
{
@@ -90,9 +91,9 @@ public function __construct(string $card_number = '')
9091
*/
9192
public function setCardNumber(string $card_number)
9293
{
93-
$card_number = preg_replace('/[^0-9]/', '', $card_number);
94+
$this->card_number = preg_replace('/\s+/', '', $card_number);
9495

95-
$this->card_number = $card_number;
96+
$this->isValidCardNumber();
9697

9798
if (! $this->validPattern()) {
9899
throw new CreditCardPatternException(
@@ -106,6 +107,7 @@ public function setCardNumber(string $card_number)
106107
/**
107108
* @return bool
108109
* @throws \LVR\CreditCard\Exceptions\CreditCardChecksumException
110+
* @throws \LVR\CreditCard\Exceptions\CreditCardCharactersException
109111
* @throws \LVR\CreditCard\Exceptions\CreditCardException
110112
* @throws \LVR\CreditCard\Exceptions\CreditCardLengthException
111113
*/
@@ -115,6 +117,12 @@ public function isValidCardNumber()
115117
throw new CreditCardException('Card number is not set');
116118
}
117119

120+
if (! is_numeric(preg_replace('/\s+/', '', $this->card_number))) {
121+
throw new CreditCardCharactersException(
122+
sprintf('Card number "%s" contains invalid characters', $this->card_number)
123+
);
124+
}
125+
118126
if (! $this->validLength()) {
119127
throw new CreditCardLengthException(
120128
sprintf('Incorrect "%s" card length', $this->card_number)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace LVR\CreditCard\Exceptions;
4+
5+
class CreditCardCharactersException extends CreditCardException
6+
{
7+
}

src/ExpirationDateValidator.php

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,6 @@ public function __construct(string $year, string $month)
2828
$this->month = trim($month);
2929
}
3030

31-
/**
32-
* @param $year
33-
*
34-
* @return $this
35-
*/
36-
protected function setYear($year)
37-
{
38-
$year = trim($year);
39-
40-
if (strlen($year) == 2) {
41-
$year = substr(date('Y'), 0, 2).$year;
42-
}
43-
44-
$this->year = $year;
45-
46-
return $this;
47-
}
48-
4931
/**
5032
* @param string $year
5133
* @param string $month
@@ -67,6 +49,24 @@ public function isValid()
6749
&& $this->isFeatureDate();
6850
}
6951

52+
/**
53+
* @param $year
54+
*
55+
* @return $this
56+
*/
57+
protected function setYear($year)
58+
{
59+
$year = trim($year);
60+
61+
if (strlen($year) == 2) {
62+
$year = substr(date('Y'), 0, 2).$year;
63+
}
64+
65+
$this->year = $year;
66+
67+
return $this;
68+
}
69+
7070
/**
7171
* @return string
7272
*/

tests/Unit/CardExpirationTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ protected function yearValidator(string $year)
164164
*/
165165
protected function monthValidator(string $month, ?int $year = null)
166166
{
167-
$year = $year ?? Carbon::now()->addYear()->year;
167+
$year = $year ? $year : Carbon::now()->addYear()->year;
168168

169169
return Validator::make(
170170
[

tests/Unit/CardTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace LVR\CreditCard\Tests\Unit;
4+
5+
use LVR\CreditCard\Factory;
6+
use LVR\CreditCard\Cards\Card;
7+
use LVR\CreditCard\Tests\TestCase;
8+
use LVR\CreditCard\Exceptions\CreditCardException;
9+
use LVR\CreditCard\Exceptions\CreditCardCharactersException;
10+
11+
class CardTest extends TestCase
12+
{
13+
/** @test **/
14+
public function it_expects_card_number()
15+
{
16+
$this->expectException(CreditCardException::class);
17+
18+
Factory::makeFromNumber('');
19+
}
20+
21+
/** @test **/
22+
public function it_allows_spaces_in_card_numbers()
23+
{
24+
$this->assertInstanceOf(Card::class, Factory::makeFromNumber('4111 1111 1111 1111'));
25+
}
26+
27+
/** @test **/
28+
public function it_checks_if_all_card_number_characters_are_numeric()
29+
{
30+
$this->expectException(CreditCardCharactersException::class);
31+
32+
Factory::makeFromNumber('4111111x111111sss111');
33+
}
34+
35+
/** @test **/
36+
public function it_returns_card_name()
37+
{
38+
$card = Factory::makeFromNumber('4111 1111 1111 1111');
39+
40+
$this->assertEquals('visa', $card->name());
41+
}
42+
43+
/** @test **/
44+
public function it_returns_card_brand()
45+
{
46+
$card = Factory::makeFromNumber('4111 1111 1111 1111');
47+
48+
$this->assertEquals('Visa', $card->brand());
49+
}
50+
}

tests/Unit/Cards/BaseCardTests.php

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
use Illuminate\Support\Facades\Validator;
99
use LVR\CreditCard\Exceptions\CreditCardException;
1010
use Illuminate\Foundation\Http\Middleware\TrimStrings;
11+
use LVR\CreditCard\Exceptions\CreditCardLengthException;
12+
use LVR\CreditCard\Exceptions\CreditCardPatternException;
13+
use LVR\CreditCard\Exceptions\CreditCardChecksumException;
14+
use LVR\CreditCard\Exceptions\CreditCardCharactersException;
1115
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
1216

1317
abstract class BaseCardTests extends TestCase
@@ -76,7 +80,7 @@ public function it_recognises_valid_card_numbers()
7680
['card_number' => $number],
7781
['card_number' => new CardNumber]
7882
)->passes(),
79-
sprintf('The number: "%s" is recognised as invalid but should be valid', $number)
83+
sprintf('The number: "%s" is recognized as invalid but should be valid', $number)
8084
);
8185
});
8286
}
@@ -95,7 +99,7 @@ public function it_recognises_invalid_card_numbers()
9599
['card_number' => $number],
96100
['card_number' => [new CardNumber]]
97101
)->fails(),
98-
sprintf('The number: "%s" is recognised as valid but should be invalid', $number)
102+
sprintf('The number: "%s" is recognized as valid but should be invalid', $number)
99103
);
100104
});
101105
}
@@ -114,7 +118,7 @@ public function it_checks_number_length()
114118
$this->assertEquals(
115119
CardNumber::MSG_CARD_LENGTH_INVALID,
116120
$validator->messages()->first(),
117-
sprintf('The number: "%s" is not recognised as invalid length', $number)
121+
sprintf('The number: "%s" is not recognized as invalid length', $number)
118122
);
119123
});
120124
}
@@ -157,8 +161,26 @@ public function it_should_not_match_other_cards()
157161
false,
158162
sprintf('%s cards ("%s") pattern matches %s card.', $card, $number, $this->instance)
159163
);
164+
} catch (CreditCardPatternException $ex) {
165+
$this->assertTrue(
166+
$ex->getMessage() === sprintf('Wrong "%s" card pattern', $number)
167+
);
168+
} catch (CreditCardLengthException $ex) {
169+
$this->assertTrue(
170+
$ex->getMessage() === sprintf('Incorrect "%s" card length', $number)
171+
);
172+
} catch (CreditCardChecksumException $ex) {
173+
$this->assertTrue(
174+
$ex->getMessage() === sprintf('Invalid card number: "%s". Checksum is wrong', $number)
175+
);
176+
} catch (CreditCardCharactersException $ex) {
177+
$this->assertTrue(
178+
$ex->getMessage() === sprintf('Card number "%s" contains invalid characters', $number)
179+
);
160180
} catch (CreditCardException $ex) {
161-
$this->assertTrue($ex->getMessage() === sprintf('Wrong "%s" card pattern', $number));
181+
$this->assertTrue(
182+
$ex->getMessage() === 'Card number is not set'
183+
);
162184
}
163185
}
164186
});

0 commit comments

Comments
 (0)