Source code for web_payments.django.models
from decimal import Decimal
from urllib.parse import urlencode, urljoin
from django.db import models
from django.conf import settings
try:
from django.urls import reverse
except ImportError:
from django.core.urlresolvers import reverse
from .. import FraudStatus, PaymentStatus, ProviderVariant
from ..logic import BasicPayment
from ..utils import getter_prefixed_address
from .signals import status_changed
from . import get_base_url
__all__ = ["BasePayment", "BasePaymentWithAddress"]
[docs]class BasePayment(models.Model, BasicPayment):
'''
Represents a single transaction. Each instance has one or more PaymentItem.
'''
# overwrite variant to remove field
#: select payment provider
variant = models.CharField(max_length=255)
#: Transaction status
status = models.CharField(
max_length=10, choices=PaymentStatus.CHOICES,
default=PaymentStatus.WAITING)
#: Transaction status message
message = models.TextField(blank=True, default='')
#: fraud status
fraud_status = models.CharField(
max_length=10, choices=FraudStatus.CHOICES,
default=FraudStatus.UNKNOWN)
#: fraud message
fraud_message = models.TextField(blank=True, default='')
#: for attrs pseudo dict
extra_data = models.TextField(blank=True, default='')
#: secret token (for get_process_url)
token = models.CharField(max_length=36, blank=True, default='')
#: Transaction ID (if applicable)
transaction_id = models.CharField(max_length=255, blank=True)
#: Currency code (may be provider-specific)
currency = models.CharField(max_length=10)
#: Total amount (gross)
total = models.DecimalField(max_digits=20, decimal_places=8, default=Decimal('0.0'))
#: captured = current captured amount
captured_amount = models.DecimalField(
max_digits=20, decimal_places=8, default=Decimal('0.0'))
#: recommended for audit:
#created = models.DateTimeField(auto_now_add=True)
#modified = models.DateTimeField(auto_now=True)
[docs] def signal_status_change(self):
status_changed.send(sender=type(self), instance=self)
[docs] def get_process_url(self, extra_data=None):
url = reverse('process_payment', kwargs={'token': self.token})
url = urljoin(get_base_url(self.provider), url)
if extra_data:
qs = urlencode(extra_data)
return url + '?' + qs
return url
[docs] @classmethod
def list_providers(cls, **kwargs):
""" returns an iterable with ProviderVariants """
def _helper(item):
t = {"name": item[0]}
t.update(item[1][2])
return ProviderVariant(item[1][0], item[1][1], t)
if "name" in kwargs:
if kwargs["name"] in settings.PAYMENT_VARIANTS_API:
return [_helper((kwargs["name"], settings.PAYMENT_VARIANTS_API[kwargs["name"]]))]
else:
return []
else:
return map(_helper, settings.PAYMENT_VARIANTS_API.items())
[docs] def get_provider_variant(self):
t = settings.PAYMENT_VARIANTS_API[self.variant]
variant = ProviderVariant(t[0], t[1], {"name": self.variant})
variant.extra.update(t[2])
return variant
[docs] @classmethod
def check_token_exists(cls, token):
return cls._default_manager.filter(token=token).exists()
[docs] def save(self, **kwargs):
self.create_token()
return models.Model.save(self, **kwargs)
[docs]class BasePaymentWithAddress(BasePayment):
""" Has real billing address + shippingaddress alias on billing address """
get_billing_address = getter_prefixed_address("billing")
get_shipping_address = get_billing_address
billing_first_name = models.CharField(max_length=256, blank=True)
billing_last_name = models.CharField(max_length=256, blank=True)
billing_address_1 = models.CharField(max_length=256, blank=True)
billing_address_2 = models.CharField(max_length=256, blank=True)
billing_email = models.EmailField(blank=True)
billing_city = models.CharField(max_length=256, blank=True)
billing_postcode = models.CharField(max_length=20, blank=True)
billing_country_code = models.CharField(max_length=2, blank=True)
billing_country_area = models.CharField(max_length=256, blank=True)