-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDiscoverCard.php
More file actions
155 lines (147 loc) · 4.26 KB
/
DiscoverCard.php
File metadata and controls
155 lines (147 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
<?php
declare(strict_types=1);
namespace GatePay\CreditCard\Brands;
use GatePay\CreditCard\Abstracts\AbstractCreditCardBrand;
use GatePay\CreditCard\Algorithms\Luhn;
use Throwable;
use function strlen;
use function substr;
/**
* Discover is a credit card brand issued primarily in the United States.
* It was introduced by Sears in 1985 and is currently issued by Capital One
*
* @see https://en.wikipedia.org/wiki/Discover_Card
* @see https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_(IIN)
*/
final class DiscoverCard extends AbstractCreditCardBrand
{
/**
* The unique identifier for the Discover Card.
* @var non-empty-lowercase-string
*/
public const ID = 'discover';
/**
* The unique identifier for the credit card brand.
* This is typically a lowercase string that represents the brand (e.g., "visa", "mastercard").
*
* @var non-empty-lowercase-string $id
*/
protected string $id = self::ID;
/**
* The human-readable name of the credit card brand.
* This is typically a capitalized string that represents the brand (e.g., "Visa", "MasterCard").
*
* @var non-empty-string $name
*/
protected string $name = 'Discover Card';
/**
* An array of valid Issuer Identification Number (IIN/BIN) ranges for this credit card brand.
* Each range can be represented as a string of digits (e.g., "4" for Visa, "51-55" for MasterCard)
* or as a positive integer (e.g., 4 for Visa, 51 for MasterCard).
*
* @var non-empty-list<positive-int> $iinList
* @see https://www.iso.org/standard/70484.html
* @see @see https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_(IIN)
*/
protected array $iinList = [
// 622126–622925 (China UnionPay co-branded)
622126,
622127,
622128,
622129,
622130,
622131,
622132,
622133,
622134,
622135,
622136,
622137,
622138,
622139,
622140,
622141,
622142,
622143,
622144,
622145,
622146,
622147,
622148,
622149,
622150,
622151,
622152,
622153,
622154,
622155,
622156,
622157,
622158,
622159,
622160,
622161,
622162,
622163,
622164,
622165,
622166,
622167,
622168,
622169,
// default IIN ranges for Discover cards
6011,
644,
645,
646,
647,
648,
649,
65,
];
/**
* An array of valid Primary Account Number (PAN) lengths for this credit card brand.
* The PAN is the full card number, which includes the IIN/BIN and the individual account identifier.
* Valid PAN lengths should be between 8 and 19 digits, inclusive.
*
* @var non-empty-list<int<8,19>> $panLengths
* @see https://www.iso.org/standard/70484.html
*/
protected array $panLengths = [16, 17, 18, 19];
/**
* @inheritdoc
*/
public function isValid(string $pan): bool
{
$length = strlen($pan);
// ranges 16-19 are valid for Discover cards,
// but some sources suggest that 16 is the most common length
if ($length > 19 || $length < 16) {
return false;
}
if ($pan[0] !== '6') {
return false;
}
try {
// assert that the PAN is valid according to the Luhn algorithm,
// which is commonly used for validating credit card numbers
Luhn::assert($pan);
} catch (Throwable) {
return false;
}
// take 6 digits for IIN range 622126–622925, otherwise take 4 digits for other IIN ranges
$digit = (int) substr($pan, 0, 6);
if ($digit >= 622126 && $digit <= 622925) {
return true;
}
// 6011, 644-649, 65 are valid IINs for Discover cards
if (str_starts_with($pan, '6011')) {
return true;
}
$digit = (int) substr($pan, 0, 3);
if ($digit >= 644 && $digit <= 649) {
return true;
}
return "$pan[0]$pan[1]" === '65';
}
}