#!/usr/bin/env python # -*- coding: utf-8 -*- from calendar import monthrange from datetime import date from django import forms from django.utils.translation import ugettext as _ from six.moves import range from paypal.pro.creditcard import verify_credit_card class CreditCardField(forms.CharField): """Form field for checking out a credit card.""" def __init__(self, *args, **kwargs): kwargs.setdefault('max_length', 20) super(CreditCardField, self).__init__(*args, **kwargs) def clean(self, value): """Raises a ValidationError if the card is not valid and stashes card type.""" if value: value = value.replace('-', '').replace(' ', '') self.card_type = verify_credit_card(value) if self.card_type is None: raise forms.ValidationError("Invalid credit card number.") return value # Credit Card Expiry Fields from: # http://www.djangosnippets.org/snippets/907/ class CreditCardExpiryWidget(forms.MultiWidget): """MultiWidget for representing credit card expiry date.""" def decompress(self, value): if isinstance(value, date): return [value.month, value.year] elif isinstance(value, basestring): return [value[0:2], value[2:]] else: return [None, None] def format_output(self, rendered_widgets): html = u' / '.join(rendered_widgets) return u'%s' % html class CreditCardExpiryField(forms.MultiValueField): EXP_MONTH = [(x, x) for x in range(1, 13)] EXP_YEAR = [(x, x) for x in range(date.today().year, date.today().year + 15)] default_error_messages = { 'invalid_month': u'Enter a valid month.', 'invalid_year': u'Enter a valid year.', } def __init__(self, *args, **kwargs): errors = self.default_error_messages.copy() if 'error_messages' in kwargs: errors.update(kwargs['error_messages']) fields = ( forms.ChoiceField(choices=self.EXP_MONTH, error_messages={'invalid': errors['invalid_month']}), forms.ChoiceField(choices=self.EXP_YEAR, error_messages={'invalid': errors['invalid_year']}), ) super(CreditCardExpiryField, self).__init__(fields, *args, **kwargs) self.widget = CreditCardExpiryWidget(widgets=[fields[0].widget, fields[1].widget]) def clean(self, value): exp = super(CreditCardExpiryField, self).clean(value) if date.today() > exp: raise forms.ValidationError("The expiration date you entered is in the past.") return exp def compress(self, data_list): if data_list: if data_list[1] in forms.fields.EMPTY_VALUES: error = self.error_messages['invalid_year'] raise forms.ValidationError(error) if data_list[0] in forms.fields.EMPTY_VALUES: error = self.error_messages['invalid_month'] raise forms.ValidationError(error) year = int(data_list[1]) month = int(data_list[0]) # find last day of the month day = monthrange(year, month)[1] return date(year, month, day) return None class CreditCardCVV2Field(forms.CharField): def __init__(self, *args, **kwargs): kwargs.setdefault('max_length', 4) super(CreditCardCVV2Field, self).__init__(*args, **kwargs) # Country Field from: # http://www.djangosnippets.org/snippets/494/ # http://xml.coverpages.org/country3166.html COUNTRIES = ( ('US', _('United States of America')), ('CA', _('Canada')), ('AF', _('Afghanistan')), ('AL', _('Albania')), ('DZ', _('Algeria')), ('AS', _('American Samoa')), ('AD', _('Andorra')), ('AO', _('Angola')), ('AI', _('Anguilla')), ('AQ', _('Antarctica')), ('AG', _('Antigua & Barbuda')), ('AR', _('Argentina')), ('AM', _('Armenia')), ('AW', _('Aruba')), ('AU', _('Australia')), ('AT', _('Austria')), ('AZ', _('Azerbaijan')), ('BS', _('Bahama')), ('BH', _('Bahrain')), ('BD', _('Bangladesh')), ('BB', _('Barbados')), ('BY', _('Belarus')), ('BE', _('Belgium')), ('BZ', _('Belize')), ('BJ', _('Benin')), ('BM', _('Bermuda')), ('BT', _('Bhutan')), ('BO', _('Bolivia')), ('BA', _('Bosnia and Herzegovina')), ('BW', _('Botswana')), ('BV', _('Bouvet Island')), ('BR', _('Brazil')), ('IO', _('British Indian Ocean Territory')), ('VG', _('British Virgin Islands')), ('BN', _('Brunei Darussalam')), ('BG', _('Bulgaria')), ('BF', _('Burkina Faso')), ('BI', _('Burundi')), ('KH', _('Cambodia')), ('CM', _('Cameroon')), ('CV', _('Cape Verde')), ('KY', _('Cayman Islands')), ('CF', _('Central African Republic')), ('TD', _('Chad')), ('CL', _('Chile')), ('CN', _('China')), ('CX', _('Christmas Island')), ('CC', _('Cocos (Keeling) Islands')), ('CO', _('Colombia')), ('KM', _('Comoros')), ('CG', _('Congo')), ('CK', _('Cook Iislands')), ('CR', _('Costa Rica')), ('HR', _('Croatia')), ('CU', _('Cuba')), ('CY', _('Cyprus')), ('CZ', _('Czech Republic')), ('DK', _('Denmark')), ('DJ', _('Djibouti')), ('DM', _('Dominica')), ('DO', _('Dominican Republic')), ('TP', _('East Timor')), ('EC', _('Ecuador')), ('EG', _('Egypt')), ('SV', _('El Salvador')), ('GQ', _('Equatorial Guinea')), ('ER', _('Eritrea')), ('EE', _('Estonia')), ('ET', _('Ethiopia')), ('FK', _('Falkland Islands (Malvinas)')), ('FO', _('Faroe Islands')), ('FJ', _('Fiji')), ('FI', _('Finland')), ('FR', _('France')), ('FX', _('France, Metropolitan')), ('GF', _('French Guiana')), ('PF', _('French Polynesia')), ('TF', _('French Southern Territories')), ('GA', _('Gabon')), ('GM', _('Gambia')), ('GE', _('Georgia')), ('DE', _('Germany')), ('GH', _('Ghana')), ('GI', _('Gibraltar')), ('GR', _('Greece')), ('GL', _('Greenland')), ('GD', _('Grenada')), ('GP', _('Guadeloupe')), ('GU', _('Guam')), ('GT', _('Guatemala')), ('GN', _('Guinea')), ('GW', _('Guinea-Bissau')), ('GY', _('Guyana')), ('HT', _('Haiti')), ('HM', _('Heard & McDonald Islands')), ('HN', _('Honduras')), ('HK', _('Hong Kong')), ('HU', _('Hungary')), ('IS', _('Iceland')), ('IN', _('India')), ('ID', _('Indonesia')), ('IQ', _('Iraq')), ('IE', _('Ireland')), ('IR', _('Islamic Republic of Iran')), ('IL', _('Israel')), ('IT', _('Italy')), ('CI', _('Ivory Coast')), ('JM', _('Jamaica')), ('JP', _('Japan')), ('JO', _('Jordan')), ('KZ', _('Kazakhstan')), ('KE', _('Kenya')), ('KI', _('Kiribati')), ('KP', _('Korea, Democratic People\'s Republic of')), ('KR', _('Korea, Republic of')), ('KW', _('Kuwait')), ('KG', _('Kyrgyzstan')), ('LA', _('Lao People\'s Democratic Republic')), ('LV', _('Latvia')), ('LB', _('Lebanon')), ('LS', _('Lesotho')), ('LR', _('Liberia')), ('LY', _('Libyan Arab Jamahiriya')), ('LI', _('Liechtenstein')), ('LT', _('Lithuania')), ('LU', _('Luxembourg')), ('MO', _('Macau')), ('MG', _('Madagascar')), ('MW', _('Malawi')), ('MY', _('Malaysia')), ('MV', _('Maldives')), ('ML', _('Mali')), ('MT', _('Malta')), ('MH', _('Marshall Islands')), ('MQ', _('Martinique')), ('MR', _('Mauritania')), ('MU', _('Mauritius')), ('YT', _('Mayotte')), ('MX', _('Mexico')), ('FM', _('Micronesia')), ('MD', _('Moldova, Republic of')), ('MC', _('Monaco')), ('MN', _('Mongolia')), ('MS', _('Monserrat')), ('MA', _('Morocco')), ('MZ', _('Mozambique')), ('MM', _('Myanmar')), ('NA', _('Namibia')), ('NR', _('Nauru')), ('NP', _('Nepal')), ('NL', _('Netherlands')), ('AN', _('Netherlands Antilles')), ('NC', _('New Caledonia')), ('NZ', _('New Zealand')), ('NI', _('Nicaragua')), ('NE', _('Niger')), ('NG', _('Nigeria')), ('NU', _('Niue')), ('NF', _('Norfolk Island')), ('MP', _('Northern Mariana Islands')), ('NO', _('Norway')), ('OM', _('Oman')), ('PK', _('Pakistan')), ('PW', _('Palau')), ('PA', _('Panama')), ('PG', _('Papua New Guinea')), ('PY', _('Paraguay')), ('PE', _('Peru')), ('PH', _('Philippines')), ('PN', _('Pitcairn')), ('PL', _('Poland')), ('PT', _('Portugal')), ('PR', _('Puerto Rico')), ('QA', _('Qatar')), ('RE', _('Reunion')), ('RO', _('Romania')), ('RU', _('Russian Federation')), ('RW', _('Rwanda')), ('LC', _('Saint Lucia')), ('WS', _('Samoa')), ('SM', _('San Marino')), ('ST', _('Sao Tome & Principe')), ('SA', _('Saudi Arabia')), ('SN', _('Senegal')), ('SC', _('Seychelles')), ('SL', _('Sierra Leone')), ('SG', _('Singapore')), ('SK', _('Slovakia')), ('SI', _('Slovenia')), ('SB', _('Solomon Islands')), ('SO', _('Somalia')), ('ZA', _('South Africa')), ('GS', _('South Georgia and the South Sandwich Islands')), ('ES', _('Spain')), ('LK', _('Sri Lanka')), ('SH', _('St. Helena')), ('KN', _('St. Kitts and Nevis')), ('PM', _('St. Pierre & Miquelon')), ('VC', _('St. Vincent & the Grenadines')), ('SD', _('Sudan')), ('SR', _('Suriname')), ('SJ', _('Svalbard & Jan Mayen Islands')), ('SZ', _('Swaziland')), ('SE', _('Sweden')), ('CH', _('Switzerland')), ('SY', _('Syrian Arab Republic')), ('TW', _('Taiwan, Province of China')), ('TJ', _('Tajikistan')), ('TZ', _('Tanzania, United Republic of')), ('TH', _('Thailand')), ('TG', _('Togo')), ('TK', _('Tokelau')), ('TO', _('Tonga')), ('TT', _('Trinidad & Tobago')), ('TN', _('Tunisia')), ('TR', _('Turkey')), ('TM', _('Turkmenistan')), ('TC', _('Turks & Caicos Islands')), ('TV', _('Tuvalu')), ('UG', _('Uganda')), ('UA', _('Ukraine')), ('AE', _('United Arab Emirates')), ('GB', _('United Kingdom (Great Britain)')), ('UM', _('United States Minor Outlying Islands')), ('VI', _('United States Virgin Islands')), ('ZZ', _('Unknown or unspecified country')), ('UY', _('Uruguay')), ('UZ', _('Uzbekistan')), ('VU', _('Vanuatu')), ('VA', _('Vatican City State (Holy See)')), ('VE', _('Venezuela')), ('VN', _('Viet Nam')), ('WF', _('Wallis & Futuna Islands')), ('EH', _('Western Sahara')), ('YE', _('Yemen')), ('YU', _('Yugoslavia')), ('ZR', _('Zaire')), ('ZM', _('Zambia')), ('ZW', _('Zimbabwe')), ) class CountryField(forms.ChoiceField): def __init__(self, *args, **kwargs): kwargs.setdefault('choices', COUNTRIES) super(CountryField, self).__init__(*args, **kwargs)