Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion pydantic_extra_types/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class PaymentCardBrand(str, Enum):
troy = 'Troy'
unionpay = 'UnionPay'
jcb = 'JCB'
diners_club = 'Diners Club'
other = 'other'

def __str__(self) -> str:
Expand Down Expand Up @@ -146,7 +147,7 @@ def validate_brand(card_number: str) -> PaymentCardBrand:
if card_number[0] == '4':
brand = PaymentCardBrand.visa
required_length = [13, 16, 19]
elif 51 <= int(card_number[:2]) <= 55:
elif (51 <= int(card_number[:2]) <= 55) or (2221 <= int(card_number[:4]) <= 2720):
brand = PaymentCardBrand.mastercard
required_length = [16]
elif card_number[:2] in {'34', '37'}:
Expand Down Expand Up @@ -185,6 +186,12 @@ def validate_brand(card_number: str) -> PaymentCardBrand:
elif 3528 <= int(card_number[:4]) <= 3589:
brand = PaymentCardBrand.jcb
required_length = [16, 19]
elif card_number[:2] in {'30', '36', '38', '39'}:
brand = PaymentCardBrand.diners_club
required_length = list(range(14, 20))
elif card_number.startswith('55'):
brand = PaymentCardBrand.diners_club
required_length = [16]

valid = len(card_number) in required_length if brand != PaymentCardBrand.other else True

Expand Down
11 changes: 11 additions & 0 deletions tests/test_types_payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
VALID_MAESTRO = '6759649826438453'
VALID_TROY = '9792000000000001'
VALID_OTHER = '2000000000000000008'
VALID_DINERS_CLUB_14 = '30500000000000'
VALID_DINERS_CLUB_16 = '3050000000000009'
VALID_DINERS_CLUB_17 = '30500000000000009'
VALID_DINERS_CLUB_19 = '3050000000000000009'
LUHN_INVALID = '4000000000000000'
LEN_INVALID = '40000000000000006'

Expand Down Expand Up @@ -117,6 +121,9 @@ def test_validate_luhn_check_digit(card_number: str, valid: bool):
(LEN_INVALID, PaymentCardBrand.visa, False),
(VALID_MAESTRO, PaymentCardBrand.maestro, True),
(VALID_TROY, PaymentCardBrand.troy, True),
(VALID_DINERS_CLUB_14, PaymentCardBrand.diners_club, True),
(VALID_DINERS_CLUB_16, PaymentCardBrand.diners_club, True),
(VALID_DINERS_CLUB_19, PaymentCardBrand.diners_club, True),
(VALID_OTHER, PaymentCardBrand.other, True),
],
)
Expand Down Expand Up @@ -144,6 +151,10 @@ def test_length_for_brand(card_number: str, brand: PaymentCardBrand, valid: bool
(VALID_JCB_16, PaymentCardBrand.jcb),
(VALID_OTHER, PaymentCardBrand.other),
(VALID_MAESTRO, PaymentCardBrand.maestro),
(VALID_DINERS_CLUB_14, PaymentCardBrand.diners_club),
(VALID_DINERS_CLUB_16, PaymentCardBrand.diners_club),
(VALID_DINERS_CLUB_17, PaymentCardBrand.diners_club),
(VALID_DINERS_CLUB_19, PaymentCardBrand.diners_club),
(VALID_TROY, PaymentCardBrand.troy),
],
)
Expand Down
Loading