123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- # coding=utf-8
- from __future__ import unicode_literals
- from collections import OrderedDict
- from .. import BaseProvider
- class CreditCard(object):
- def __init__(
- self,
- name,
- prefixes,
- length=16,
- security_code='CVC',
- security_code_length=3):
- self.name = name
- self.prefixes = prefixes
- self.length = length
- self.security_code = security_code
- self.security_code_length = security_code_length
- class Provider(BaseProvider):
- # Prefixes from:
- # * https://en.wikipedia.org/wiki/Payment_card_number#Issuer_identification_number_.28IIN.29
- # * https://www.regular-expressions.info/creditcard.html
- # * https://creditcardjs.com/credit-card-type-detection
- prefix_maestro = ['5018', '5020', '5038', '56##', '57##', '58##',
- '6304', '6759', '6761', '6762', '6763', '0604', '6390']
- prefix_mastercard = ['51', '52', '53', '54', '55', '222%']
- prefix_visa = ['4']
- prefix_amex = ['34', '37']
- prefix_discover = ['6011', '65']
- prefix_diners = ['300', '301', '302', '303', '304', '305', '36', '38']
- prefix_jcb16 = ['35']
- prefix_jcb15 = ['2131', '1800']
- credit_card_types = OrderedDict((
- ('maestro', CreditCard('Maestro',
- prefix_maestro, 12, security_code='CVV')),
- ('mastercard', CreditCard('Mastercard',
- prefix_mastercard, 16, security_code='CVV')),
- ('visa16', CreditCard('VISA 16 digit', prefix_visa)),
- ('visa13', CreditCard('VISA 13 digit', prefix_visa, 13)),
- ('visa19', CreditCard('VISA 19 digit', prefix_visa, 19)),
- ('amex', CreditCard('American Express', prefix_amex,
- 15, security_code='CID', security_code_length=4)),
- ('discover', CreditCard('Discover', prefix_discover)),
- ('diners', CreditCard('Diners Club / Carte Blanche', prefix_diners, 14)),
- ('jcb15', CreditCard('JCB 15 digit', prefix_jcb15, 15)),
- ('jcb16', CreditCard('JCB 16 digit', prefix_jcb16)),
- ))
- credit_card_types['visa'] = credit_card_types['visa16']
- credit_card_types['jcb'] = credit_card_types['jcb16']
- luhn_lookup = {'0': 0, '1': 2, '2': 4, '3': 6, '4': 8,
- '5': 1, '6': 3, '7': 5, '8': 7, '9': 9}
- def credit_card_provider(self, card_type=None):
- """ Returns the provider's name of the credit card. """
- if card_type is None:
- card_type = self.random_element(self.credit_card_types.keys())
- return self._credit_card_type(card_type).name
- def credit_card_number(self, card_type=None):
- """ Returns a valid credit card number. """
- card = self._credit_card_type(card_type)
- prefix = self.random_element(card.prefixes)
- number = self._generate_number(self.numerify(prefix), card.length)
- return number
- def credit_card_expire(self, start='now', end='+10y', date_format='%m/%y'):
- expire_date = self.generator.date_time_between(start, end)
- return expire_date.strftime(date_format)
- def credit_card_full(self, card_type=None):
- card = self._credit_card_type(card_type)
- tpl = ('{provider}\n'
- '{owner}\n'
- '{number} {expire_date}\n'
- '{security}: {security_nb}\n')
- tpl = tpl.format(provider=card.name,
- owner=self.generator.parse(
- "{{first_name}} {{last_name}}"),
- number=self.credit_card_number(card),
- expire_date=self.credit_card_expire(),
- security=card.security_code,
- security_nb=self.credit_card_security_code(card))
- return self.generator.parse(tpl)
- def credit_card_security_code(self, card_type=None):
- """ Returns a security code string. """
- sec_len = self._credit_card_type(card_type).security_code_length
- return self.numerify('#' * sec_len)
- def _credit_card_type(self, card_type=None):
- """ Returns a random credit card type instance. """
- if card_type is None:
- card_type = self.random_element(self.credit_card_types.keys())
- elif isinstance(card_type, CreditCard):
- return card_type
- return self.credit_card_types[card_type]
- def _generate_number(self, prefix, length):
- """
- 'prefix' is the start of the CC number as a string, any number of digits.
- 'length' is the length of the CC number to generate. Typically 13 or 16
- """
- number = prefix
- # Generate random char digits
- number += '#' * (length - len(prefix) - 1)
- number = self.numerify(number)
- reverse = number[::-1]
- # Calculate sum
- tot = 0
- pos = 0
- while pos < length - 1:
- tot += Provider.luhn_lookup[reverse[pos]]
- if pos != (length - 2):
- tot += int(reverse[pos + 1])
- pos += 2
- # Calculate check digit
- check_digit = (10 - (tot % 10)) % 10
- number += str(check_digit)
- return number
|