summaryrefslogtreecommitdiff
path: root/payments/dotpay
diff options
context:
space:
mode:
authorPatryk Zawadzki <patrys@pld-linux.org>2010-09-30 16:39:03 +0200
committerPatryk Zawadzki <patrys@pld-linux.org>2010-09-30 16:46:46 +0200
commit0b5a90cb3a194eb8c7331d81872da443ed93effa (patch)
tree2e6a8fb11dbac2d2cefe89730c6655ef497efd10 /payments/dotpay
downloaddjango-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__.py93
-rw-r--r--payments/dotpay/forms.py80
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')