diff options
author | Patryk Zawadzki <patrys@pld-linux.org> | 2010-09-30 16:39:03 +0200 |
---|---|---|
committer | Patryk Zawadzki <patrys@pld-linux.org> | 2010-09-30 16:46:46 +0200 |
commit | 0b5a90cb3a194eb8c7331d81872da443ed93effa (patch) | |
tree | 2e6a8fb11dbac2d2cefe89730c6655ef497efd10 /payments/dotpay | |
download | django-payments-taler-0b5a90cb3a194eb8c7331d81872da443ed93effa.tar.gz django-payments-taler-0b5a90cb3a194eb8c7331d81872da443ed93effa.tar.bz2 django-payments-taler-0b5a90cb3a194eb8c7331d81872da443ed93effa.zip |
Initial release
Diffstat (limited to 'payments/dotpay')
-rw-r--r-- | payments/dotpay/__init__.py | 93 | ||||
-rw-r--r-- | payments/dotpay/forms.py | 80 |
2 files changed, 173 insertions, 0 deletions
diff --git a/payments/dotpay/__init__.py b/payments/dotpay/__init__.py new file mode 100644 index 0000000..caaca92 --- /dev/null +++ b/payments/dotpay/__init__.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +import urlparse + +from django.contrib.sites.models import Site +from django.core.urlresolvers import reverse +from django.utils.http import urlquote +from django.http import HttpResponse, HttpResponseForbidden + +from .. import BasicProvider +from ..models import Payment + +from .forms import ProcessPaymentForm + +class DotpayProvider(BasicProvider): + ''' + dotpay.pl payment provider + + seller_id: + seller ID, assigned by dotpay + url: + return URL, user will be bounced to this address after payment is + processed + pin: + PIN + channel: + default payment channel (consult dotpay.pl reference guide) + lang: + UI language + lock: + whether to disable channels other than the default selected above + ''' + _method = 'post' + _action = 'https://ssl.dotpay.pl/' + + def __init__(self, seller_id, url, domain=None, pin=None, channel=0, lang='pl', lock=False, **kwargs): + self._seller_id = seller_id + self._url = url + self._domain = domain \ + or urlparse.urlunparse(( + 'https', + Site.objects.get_current().domain, + '/', + None, + None, + None)) + self._pin = pin + self._channel = channel + self._lang = lang + self._lock = lock + return super(DotpayProvider, self).__init__(**kwargs) + + def get_hidden_fields(self, payment): + get_label = lambda x: x.name if x.quantity == 1 else u'%s × %d' % (x.name, x.quantity) + items = map(get_label, payment.items.all()) + + domain = urlparse.urlparse(self._domain) + path = reverse('process_payment', args=[self._variant]) + urlc = urlparse.urlunparse((domain.scheme, domain.netloc, path, None, None, None)) + url_parts = urlparse.urlparse(self._url) + if url_parts.scheme: + url = self._url + else: + url = urlparse.urlunparse((domain.scheme, domain.netloc, url_parts.path, None, None, None)) + + data = { + 'id': self._seller_id, + 'amount': str(payment.total), + 'control': str(payment.id), + 'currency': payment.currency, + 'description': ', '.join(items), + 'lang': self._lang, + 'channel': str(self._channel), + 'ch_lock': '1' if self._lock else '0', + 'URL': url, + 'URLC': urlc, + 'type': '2', + 'control': payment.id, + } + return data + + def process_data(self, request, variant): + from django.core.mail import mail_admins + mail_admins('Payment', unicode(request.POST) + '\n' + unicode(request.GET)) + failed = HttpResponseForbidden("FAILED") + if request.method != "POST": + return failed + + form = ProcessPaymentForm(pin=self._pin, data=request.POST) + if not form.is_valid(): + return failed + + form.save() + return HttpResponse("OK") diff --git a/payments/dotpay/forms.py b/payments/dotpay/forms.py new file mode 100644 index 0000000..54040f4 --- /dev/null +++ b/payments/dotpay/forms.py @@ -0,0 +1,80 @@ +# -*- coding:utf-8 -*- +from django import forms +from django.utils.translation import ugettext as _ +from django.db.models import Q + +import md5 + +from ..models import Payment + +NO_MORE_CONFIRMATION=0 +NEW=1 +ACCEPTED=2 +REJECTED=3 +CANCELED=4 + +STATUS_CHOICES = map(lambda c: (c,c), ( + NO_MORE_CONFIRMATION, + NEW, + ACCEPTED, + REJECTED, + CANCELED +)) + +class ProcessPaymentForm(forms.Form): + status = forms.ChoiceField(choices=(("OK","OK"),("FAIL","FAIL"))) + id = forms.IntegerField() + #this should be Payments modelchoicefield + control = forms.IntegerField() + #control = forms.TypedChoiceField( + # choices = [ (id,id) for id in Payment.objects.exclude( + # Q(status='rejected') + # ).values_list("id", flat=True) + # ], + # coerce=int, + #) + t_id = forms.CharField() + amount = forms.DecimalField() + email = forms.EmailField(required=False) + t_status = forms.TypedChoiceField(coerce=int, choices=STATUS_CHOICES) + description = forms.CharField(required=False) + md5 = forms.CharField() + + def __init__(self, pin, **kwargs): + super(ProcessPaymentForm, self).__init__(**kwargs) + self.pin = pin + + def clean(self): + vars = { + "pin": self.pin, + "id": self.cleaned_data['id'], + "control": self.cleaned_data["control"], + "t_id": self.cleaned_data["t_id"], + "amount": self.cleaned_data["amount"], + "email": self.cleaned_data.get("email", ""), + "service": "", + "code": "", + "username": "", + "password": "", + "t_status": self.cleaned_data["t_status"] + } + + key = "%(pin)s:%(id)s:%(control)s:%(t_id)s:%(amount)s:%(email)s:%(service)s:%(code)s:%(username)s:%(password)s:%(t_status)s" % vars + hash = md5.new(key).hexdigest() + if hash != self.cleaned_data["md5"]: + raise forms.ValidationError() + return self.cleaned_data + + def save(self, *args, **kwargs): + payment_id = self.cleaned_data['control'] + status = self.cleaned_data['t_status'] + + payment = Payment.objects.get(id=payment_id) + payment.transaction_id = self.cleaned_data['t_id'] + payment.save() + + if status == ACCEPTED: + payment.change_status('confirmed') + elif (status == NO_MORE_CONFIRMATION and payment.status == 'waiting') \ + or status == REJECTED or status == CANCELED: + payment.change_status('rejected') |