Skip to content
This repository was archived by the owner on Oct 20, 2021. It is now read-only.

Commit 37437ba

Browse files
feat(rules): Added CreditCard rule
1 parent 79d4246 commit 37437ba

6 files changed

Lines changed: 146 additions & 3 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ The library can be loaded either as a standalone script, or through an [AMD](htt
9494
- [Consonant](docs/consonant.md)
9595
- [Contains](docs/contains.md)
9696
- [Cpf](docs/cpf.md)
97+
- [CreditCard](docs/credit-card.md)
9798
- [CurrencyCode](docs/currency-code.md)
9899
- [DateTime](docs/date-time.md)
99100
- [Digit](docs/digit.md)

awesome-validator.min.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/credit-card.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# CreditCard
2+
3+
Validates a credit card number.
4+
5+
Valid values:
6+
7+
```js
8+
validator.creditCard().validate('5376 7473 9720 8720');
9+
validator.creditCard('American Express').validate('340316193809364');
10+
validator.creditCard('Diners Club').validate('30351042633884');
11+
validator.creditCard('Discover').validate('6011000990139424');
12+
validator.creditCard('JCB').validate('3566002020360505');
13+
validator.creditCard('MasterCard').validate('5376747397208720');
14+
validator.creditCard('Visa').validate('4024007153361885');
15+
```
16+
17+
Invalid values:
18+
19+
```js
20+
validator.creditCard().validate('');
21+
validator.creditCard().validate('foo');
22+
validator.creditCard().validate(null);
23+
validator.creditCard().validate('1234 1234 1234 1234');
24+
validator.creditCard('Visa').validate(3530111333300000); // JCB
25+
```
26+
27+
The current supported brands are:
28+
29+
- American Express
30+
- Diners Club
31+
- Discover
32+
- JCB
33+
- MasterCard
34+
- Visa

src/rules/credit-card.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { Luhn } from './luhn';
2+
import { Regex } from './regex';
3+
4+
export class CreditCard extends Luhn {
5+
6+
/**
7+
* Services.
8+
*/
9+
protected services: Map<string, RegExp> = new Map([
10+
['American Express', /^3[47]\d{13}$/],
11+
['Diners Club', /^3(?:0[0-5]|[68]\d)\d{11}$/],
12+
['Discover', /^6(?:011|5\d{2})\d{12}$/],
13+
['JCB', /^(?:2131|1800|35\d{3})\d{11}$/],
14+
['MasterCard', /(5[1-5]|2[2-7])\d{14}$/],
15+
['Visa', /^4\d{12}(?:\d{3})?$/]
16+
]);
17+
18+
/**
19+
* CreditCard.
20+
*/
21+
public constructor(public readonly serviceKey?: string) {
22+
super();
23+
}
24+
25+
/**
26+
* Validate.
27+
*/
28+
public validate(input: any): boolean {
29+
if (!super.validate(input)) {
30+
return false;
31+
}
32+
33+
const stringInput: string = String(input).replace(/[^\d]/g, '');
34+
const serviceValue: RegExp | undefined = this.serviceKey ? this.services.get(this.serviceKey) : undefined;
35+
36+
if (serviceValue !== undefined) {
37+
return new Regex(serviceValue).validate(stringInput);
38+
}
39+
40+
for (const service of Array.from(this.services.values())) {
41+
if (new Regex(service).validate(stringInput)) {
42+
return true;
43+
}
44+
}
45+
46+
return false;
47+
}
48+
}

src/rules/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export * from './cntrl';
1515
export * from './consonant';
1616
export * from './contains';
1717
export * from './cpf';
18+
export * from './credit-card';
1819
export * from './currency-code';
1920
export * from './date-time';
2021
export * from './digit';

test/rules/credit-card.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { assert } from 'chai';
2+
3+
import { AbstractRule } from '../../src/rules/abstract-rule';
4+
import { CreditCard } from '../../src/rules/credit-card';
5+
6+
describe('CreditCard', () => {
7+
8+
it('is rule', () => {
9+
assert.instanceOf(new CreditCard(), AbstractRule);
10+
});
11+
12+
it('values is valid', () => {
13+
assert.isTrue(new CreditCard().validate('5376 7473 9720 8720')); // MasterCard 5 BIN Range
14+
assert.isTrue(new CreditCard().validate('2223000048400011')); // MasterCard 2 BIN Range
15+
assert.isTrue(new CreditCard().validate('4024.0071.5336.1885')); // Visa 16
16+
assert.isTrue(new CreditCard().validate('4024 007 193 879')); // Visa 13
17+
assert.isTrue(new CreditCard().validate('340-3161-9380-9364')); // American Express
18+
assert.isTrue(new CreditCard().validate('30351042633884')); // Diners Club
19+
assert.isTrue(new CreditCard().validate('6011000990139424')); // Discover
20+
assert.isTrue(new CreditCard().validate('3566002020360505')); // JBC
21+
assert.isTrue(new CreditCard('MasterCard').validate('5376 7473 9720 8720'));
22+
assert.isTrue(new CreditCard('MasterCard').validate('2222 4000 4124 0011'));
23+
assert.isTrue(new CreditCard('Visa').validate('4024.0071.5336.1885'));
24+
assert.isTrue(new CreditCard('Visa').validate('4024 007 193 879'));
25+
assert.isTrue(new CreditCard('American Express').validate('340-3161-9380-9364'));
26+
assert.isTrue(new CreditCard('Diners Club').validate('30351042633884'));
27+
assert.isTrue(new CreditCard('Discover').validate('6011000990139424'));
28+
assert.isTrue(new CreditCard('JCB').validate('3566002020360505'));
29+
});
30+
31+
it('values is not valid', () => {
32+
assert.isFalse(new CreditCard('MasterCard').validate('6011111111111117')); // Discover
33+
assert.isFalse(new CreditCard('Visa').validate('3530111333300000')); // JCB
34+
assert.isFalse(new CreditCard('American Express').validate('5555555555554444')); // MasterCard
35+
assert.isFalse(new CreditCard('Diners Club').validate('4012888888881881')); // Visa
36+
assert.isFalse(new CreditCard('Discover').validate('371449635398431')); // American Express
37+
assert.isFalse(new CreditCard('JCB').validate('38520000023237')); // Diners Club
38+
assert.isFalse(new CreditCard().validate(''));
39+
assert.isFalse(new CreditCard().validate('foo'));
40+
assert.isFalse(new CreditCard().validate('1234 1234 1234 1234'));
41+
assert.isFalse(new CreditCard().validate('1234.1234.1234.1234'));
42+
assert.isFalse(new CreditCard().validate('it isnt my credit card number'));
43+
assert.isFalse(new CreditCard().validate('&stR@ng3|) (|-|@r$'));
44+
assert.isFalse(new CreditCard().validate(1.0));
45+
assert.isFalse(new CreditCard().validate('wrongtld'));
46+
assert.isFalse(new CreditCard().validate(null));
47+
assert.isFalse(new CreditCard().validate(undefined));
48+
assert.isFalse(new CreditCard().validate(true));
49+
assert.isFalse(new CreditCard().validate(false));
50+
assert.isFalse(new CreditCard().validate([]));
51+
assert.isFalse(new CreditCard().validate({}));
52+
assert.isFalse(new CreditCard().validate(new Array('foo')));
53+
assert.isFalse(new CreditCard().validate(new Object({foo: 'bar'})));
54+
55+
class Foo {}
56+
assert.isFalse(new CreditCard().validate(new Foo()));
57+
});
58+
59+
});

0 commit comments

Comments
 (0)