Auto-check paypal status.
[wolnelektury.git] / src / club / payu / views.py
1 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
3 #
4 from hashlib import md5, sha256
5 from django.conf import settings
6 from django import http
7 from django.shortcuts import get_object_or_404
8 from django.utils.decorators import method_decorator
9 from django.utils.translation import get_language
10 from django.views.decorators.csrf import csrf_exempt
11 from django.views.generic import FormView, TemplateView, View
12
13
14 class Payment(TemplateView):
15     pass
16
17
18 class RecPayment(FormView):
19     """ Set form_class to a CardTokenForm. """
20     template_name = 'payu/rec_payment.html'
21
22     def get_context_data(self, *args, **kwargs):
23         ctx = super().get_context_data(*args, **kwargs)
24
25         schedule = self.get_schedule()
26         pos = self.get_pos()
27
28         widget_args = {
29             'merchant-pos-id': pos.pos_id,
30             'shop-name': "SHOW NAME",
31             'total-amount': str(int(schedule.amount * 100)),
32             'currency-code': pos.currency_code,
33             'customer-language': get_language(), # filter to pos.languages
34             'customer-email': schedule.email,
35             'store-card': 'true',
36             'recurring-payment': 'true',
37         }
38         widget_sig = sha256(
39             (
40                 "".join(v for (k, v) in sorted(widget_args.items())) +
41                 pos.secondary_key
42             ).encode('utf-8')
43         ).hexdigest()
44
45         ctx['widget_args'] = widget_args
46         ctx['widget_sig'] = widget_sig
47         ctx['schedule'] = schedule
48         ctx['pos'] = pos
49         return ctx
50
51     def form_valid(self, form):
52         form.save(self)
53         return super().form_valid(form)
54
55
56
57 @method_decorator(csrf_exempt, name='dispatch')
58 class NotifyView(View):
59     """ Set `order_model` in subclass. """
60     def post(self, request, pk):
61         order = get_object_or_404(self.order_model, pk=pk)
62
63         try:
64             openpayu = request.META['HTTP_OPENPAYU_SIGNATURE']
65             openpayu = dict(term.split('=') for term in openpayu.split(';'))
66             assert openpayu['algorithm'] == 'MD5'
67             assert openpayu['content'] == 'DOCUMENT'
68             assert openpayu['sender'] == 'checkout'
69             sig = openpayu['signature']
70         except (KeyError, ValueError, AssertionError):
71             return http.HttpResponseBadRequest('bad')
72
73         document = request.body + order.get_pos().secondary_key.encode('latin1')
74         if md5(document).hexdigest() != sig:
75             return http.HttpResponseBadRequest('wrong')
76
77         notification = order.notification_set.create(
78             body=request.body.decode('utf-8')
79         )
80         notification.apply()
81
82         return http.HttpResponse('ok')