Skip to content

Commit

Permalink
Added support for 13/19 digits VISA credit cards in PaymentCardNumber…
Browse files Browse the repository at this point in the history
… type (pydantic#2286)

* Added support for 13/19 digits VISA credit cards

* Added changes md-file

* Fixed tests VALID_VISA_19 length, changed constants order

* tiny tweaks

Co-authored-by: Alexander Plaxin <a.plaxin@qiwi.com>
Co-authored-by: Samuel Colvin <samcolvin@gmail.com>
  • Loading branch information
3 people committed Feb 23, 2021
1 parent 3f849a3 commit c8883e3
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 7 deletions.
1 change: 1 addition & 0 deletions changes/1416-AlexanderSov.md
@@ -0,0 +1 @@
Added support for 13/19 digits VISA credit cards in `PaymentCardNumber` type
7 changes: 5 additions & 2 deletions pydantic/types.py
Expand Up @@ -903,10 +903,13 @@ def validate_length_for_brand(cls, card_number: 'PaymentCardNumber') -> 'Payment
Validate length based on BIN for major brands:
https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_(IIN)
"""
required_length: Optional[int] = None
if card_number.brand in {PaymentCardBrand.visa, PaymentCardBrand.mastercard}:
required_length: Union[None, int, str] = None
if card_number.brand in PaymentCardBrand.mastercard:
required_length = 16
valid = len(card_number) == required_length
elif card_number.brand == PaymentCardBrand.visa:
required_length = '13, 16 or 19'
valid = len(card_number) in {13, 16, 19}
elif card_number.brand == PaymentCardBrand.amex:
required_length = 15
valid = len(card_number) == required_length
Expand Down
14 changes: 9 additions & 5 deletions tests/test_types_payment_card_number.py
Expand Up @@ -9,7 +9,9 @@

VALID_AMEX = '370000000000002'
VALID_MC = '5100000000000003'
VALID_VISA = '4050000000000001'
VALID_VISA_13 = '4050000000001'
VALID_VISA_16 = '4050000000000001'
VALID_VISA_19 = '4050000000000000001'
VALID_OTHER = '2000000000000000008'
LUHN_INVALID = '4000000000000000'
LEN_INVALID = '40000000000000006'
Expand Down Expand Up @@ -73,7 +75,9 @@ def test_validate_luhn_check_digit(card_number: str, valid: bool):
@pytest.mark.parametrize(
'card_number, brand, valid',
[
(VALID_VISA, PaymentCardBrand.visa, True),
(VALID_VISA_13, PaymentCardBrand.visa, True),
(VALID_VISA_16, PaymentCardBrand.visa, True),
(VALID_VISA_19, PaymentCardBrand.visa, True),
(VALID_MC, PaymentCardBrand.mastercard, True),
(VALID_AMEX, PaymentCardBrand.amex, True),
(VALID_OTHER, PaymentCardBrand.other, True),
Expand All @@ -95,7 +99,7 @@ def test_length_for_brand(card_number: str, brand: PaymentCardBrand, valid: bool
[
(VALID_AMEX, PaymentCardBrand.amex),
(VALID_MC, PaymentCardBrand.mastercard),
(VALID_VISA, PaymentCardBrand.visa),
(VALID_VISA_16, PaymentCardBrand.visa),
(VALID_OTHER, PaymentCardBrand.other),
],
)
Expand All @@ -104,8 +108,8 @@ def test_get_brand(card_number: str, brand: PaymentCardBrand):


def test_valid():
card = PaymentCard(card_number=VALID_VISA)
assert str(card.card_number) == VALID_VISA
card = PaymentCard(card_number=VALID_VISA_16)
assert str(card.card_number) == VALID_VISA_16
assert card.card_number.masked == '405000******0001'


Expand Down

0 comments on commit c8883e3

Please sign in to comment.