PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/satchmo/payment/models.py

https://github.com/roadhead/satchmo
Python | 106 lines | 84 code | 7 blank | 15 comment | 2 complexity | a98214b6f1710cc33821473b795f5a41 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. """
  2. Stores details about the available payment options.
  3. Also stores credit card info in an encrypted format.
  4. """
  5. from Crypto.Cipher import Blowfish
  6. from datetime import datetime
  7. from django.conf import settings
  8. from django.db import models
  9. from django.utils.translation import ugettext_lazy as _
  10. from satchmo import caching
  11. from satchmo.configuration import config_value, config_choice_values, SettingNotSet
  12. from satchmo.contact.models import Contact
  13. from satchmo.payment.fields import PaymentChoiceCharField, CreditChoiceCharField
  14. from satchmo.shop.models import OrderPayment
  15. import config
  16. import base64
  17. import logging
  18. try:
  19. from decimal import Decimal
  20. except:
  21. from django.utils._decimal import Decimal
  22. log = logging.getLogger('payment.models')
  23. class PaymentOption(models.Model):
  24. """
  25. If there are multiple options - CC, Cash, COD, etc this class allows
  26. configuration.
  27. """
  28. description = models.CharField(_("Description"), max_length=20)
  29. active = models.BooleanField(_("Active"),
  30. help_text=_("Should this be displayed as an option for the user?"))
  31. optionName = PaymentChoiceCharField(_("Option Name"), max_length=20,
  32. unique=True,
  33. help_text=_("The class name as defined in payment.py"))
  34. sortOrder = models.IntegerField(_("Sort Order"))
  35. class Meta:
  36. verbose_name = _("Payment Option")
  37. verbose_name_plural = _("Payment Options")
  38. class CreditCardDetail(models.Model):
  39. """
  40. Stores an encrypted CC number, its information, and its
  41. displayable number.
  42. """
  43. orderpayment = models.ForeignKey(OrderPayment, unique=True,
  44. related_name="creditcards")
  45. credit_type = CreditChoiceCharField(_("Credit Card Type"), max_length=16)
  46. display_cc = models.CharField(_("CC Number (Last 4 digits)"),
  47. max_length=4, )
  48. encrypted_cc = models.CharField(_("Encrypted Credit Card"),
  49. max_length=40, blank=True, null=True, editable=False)
  50. expire_month = models.IntegerField(_("Expiration Month"))
  51. expire_year = models.IntegerField(_("Expiration Year"))
  52. card_holder = models.CharField(_("card_holder Name"), max_length=60, blank=True)
  53. start_month = models.IntegerField(_("Start Month"), blank=True, null=True)
  54. start_year = models.IntegerField(_("Start Year"), blank=True, null=True)
  55. issue_num = models.CharField(blank=True, null=True, max_length=2)
  56. def storeCC(self, ccnum):
  57. """Take as input a valid cc, encrypt it and store the last 4 digits in a visible form"""
  58. # Must remember to save it after calling!
  59. secret_key = settings.SECRET_KEY
  60. encryption_object = Blowfish.new(secret_key)
  61. # block cipher length must be a multiple of 8
  62. padding = ''
  63. if (len(ccnum) % 8) <> 0:
  64. padding = 'X' * (8 - (len(ccnum) % 8))
  65. self.encrypted_cc = base64.b64encode(encryption_object.encrypt(ccnum + padding))
  66. self.display_cc = ccnum[-4:]
  67. def setCCV(self, ccv):
  68. """Put the CCV in the cache, don't save it for security/legal reasons."""
  69. if not self.encrypted_cc:
  70. raise ValueError('CreditCardDetail expecting a credit card number to be stored before storing CCV')
  71. caching.cache_set(self.encrypted_cc, skiplog=True, length=60*60, value=ccv)
  72. def getCCV(self):
  73. try:
  74. ccv = caching.cache_get(self.encrypted_cc)
  75. except caching.NotCachedError:
  76. ccv = ""
  77. return ccv
  78. ccv = property(fget=getCCV, fset=setCCV)
  79. def _decryptCC(self):
  80. secret_key = settings.SECRET_KEY
  81. encryption_object = Blowfish.new(secret_key)
  82. # strip padding from decrypted credit card number
  83. ccnum = encryption_object.decrypt(base64.b64decode(self.encrypted_cc)).rstrip('X')
  84. return (ccnum)
  85. decryptedCC = property(_decryptCC)
  86. def _expireDate(self):
  87. return(str(self.expire_month) + "/" + str(self.expire_year))
  88. expirationDate = property(_expireDate)
  89. class Meta:
  90. verbose_name = _("Credit Card")
  91. verbose_name_plural = _("Credit Cards")