views.py 8.41 KB
Newer Older
Skia's avatar
Skia committed
1
2
from collections import OrderedDict
from datetime import datetime
Skia's avatar
Skia committed
3
import pytz
Skia's avatar
Skia committed
4
5
6
import hmac
import base64
from OpenSSL import crypto
7

Skia's avatar
Skia committed
8
from django.shortcuts import render
9
10
11
12
13
14
from django.core.urlresolvers import reverse_lazy
from django.views.generic import TemplateView, View
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.db import transaction, DataError
from django.utils.translation import ugettext as _
Skia's avatar
Skia committed
15
from django.conf import settings
16

Skia's avatar
Skia committed
17
18
from counter.models import Product, Customer, Counter
from eboutic.models import Basket, Invoice, BasketItem, InvoiceItem
19
20
21
22
23

# Create your views here.
class EbouticMain(TemplateView):
    template_name = 'eboutic/eboutic_main.jinja'

Skia's avatar
Skia committed
24
25
26
27
28
29
30
31
32
33
34
    def make_basket(self, request):
        if 'basket_id' not in request.session.keys(): # Init the basket session entry
            self.basket = Basket(user=request.user)
            self.basket.save()
        else:
            self.basket = Basket.objects.filter(id=request.session['basket_id']).first()
            if self.basket is None:
                self.basket = Basket(user=request.user)
                self.basket.save()
        request.session['basket_id'] = self.basket.id
        request.session.modified = True
35
36

    def get(self, request, *args, **kwargs):
Skia's avatar
Skia committed
37
38
39
        if not request.user.is_authenticated():
            return HttpResponseRedirect(reverse_lazy('core:login', args=self.args, kwargs=kwargs))
        self.make_basket(request)
40
41
42
        return super(EbouticMain, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
Skia's avatar
Skia committed
43
44
45
        if not request.user.is_authenticated():
            return HttpResponseRedirect(reverse_lazy('core:login', args=self.args, kwargs=kwargs))
        self.make_basket(request)
46
47
48
49
50
51
52
        if 'add_product' in request.POST['action']:
            self.add_product(request)
        elif 'del_product' in request.POST['action']:
            self.del_product(request)
        return self.render_to_response(self.get_context_data(**kwargs))


Skia's avatar
Skia committed
53
    def add_product(self, request):
54
        """ Add a product to the basket """
Skia's avatar
Skia committed
55
56
57
58
59
        try:
            p = Product.objects.filter(id=int(request.POST['product_id'])).first()
            self.basket.add_product(p)
        except:
            pass
60
61
62

    def del_product(self, request):
        """ Delete a product from the basket """
Skia's avatar
Skia committed
63
64
65
66
67
        try:
            p = Product.objects.filter(id=int(request.POST['product_id'])).first()
            self.basket.del_product(p)
        except:
            pass
68
69
70

    def get_context_data(self, **kwargs):
        kwargs = super(EbouticMain, self).get_context_data(**kwargs)
Skia's avatar
Skia committed
71
        kwargs['basket'] = self.basket
Skia's avatar
Skia committed
72
        kwargs['eboutic'] = Counter.objects.filter(type="EBOUTIC").first()
73
74
75
76
77
        return kwargs

class EbouticCommand(TemplateView):
    template_name = 'eboutic/eboutic_makecommand.jinja'

Skia's avatar
Skia committed
78
    def get(self, request, *args, **kwargs):
Skia's avatar
Skia committed
79
80
        if not request.user.is_authenticated():
            return HttpResponseRedirect(reverse_lazy('core:login', args=self.args, kwargs=kwargs))
Skia's avatar
Skia committed
81
82
        return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))

83
    def post(self, request, *args, **kwargs):
Skia's avatar
Skia committed
84
85
        if not request.user.is_authenticated():
            return HttpResponseRedirect(reverse_lazy('core:login', args=self.args, kwargs=kwargs))
Skia's avatar
Skia committed
86
87
88
89
        if 'basket_id' not in request.session.keys():
            return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))
        self.basket = Basket.objects.filter(id=request.session['basket_id']).first()
        if self.basket is None:
90
            return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))
Skia's avatar
Skia committed
91
        else:
Skia's avatar
Skia committed
92
            kwargs['basket'] = self.basket
93
94
        return self.render_to_response(self.get_context_data(**kwargs))

Skia's avatar
Skia committed
95
96
97
98
99
100
101
102
    def get_context_data(self, **kwargs):
        kwargs = super(EbouticCommand, self).get_context_data(**kwargs)
        kwargs['et_request'] = OrderedDict()
        kwargs['et_request']['PBX_SITE'] = settings.SITH_EBOUTIC_PBX_SITE
        kwargs['et_request']['PBX_RANG'] = settings.SITH_EBOUTIC_PBX_RANG
        kwargs['et_request']['PBX_IDENTIFIANT'] = settings.SITH_EBOUTIC_PBX_IDENTIFIANT
        kwargs['et_request']['PBX_TOTAL'] = int(self.basket.get_total()*100)
        kwargs['et_request']['PBX_DEVISE'] = 978 # This is Euro. ET support only this value anyway
Skia's avatar
Skia committed
103
        kwargs['et_request']['PBX_CMD'] = self.basket.id
Skia's avatar
Skia committed
104
105
106
        kwargs['et_request']['PBX_PORTEUR'] = self.basket.user.email
        kwargs['et_request']['PBX_RETOUR'] = "Amount:M;BasketID:R;Auto:A;Error:E;Sig:K"
        kwargs['et_request']['PBX_HASH'] = "SHA512"
Skia's avatar
Skia committed
107
108
        kwargs['et_request']['PBX_TYPEPAIEMENT'] = "CARTE"
        kwargs['et_request']['PBX_TYPECARTE'] = "CB"
Skia's avatar
Skia committed
109
110
111
112
113
114
        kwargs['et_request']['PBX_TIME'] = str(datetime.now().replace(microsecond=0).isoformat('T'))
        kwargs['et_request']['PBX_HMAC'] = hmac.new(settings.SITH_EBOUTIC_HMAC_KEY,
                bytes("&".join(["%s=%s"%(k,v) for k,v in kwargs['et_request'].items()]), 'utf-8'),
                "sha512").hexdigest().upper()
        return kwargs

115
116
117
118
119
120
121
122
123
class EbouticPayWithSith(TemplateView):
    template_name = 'eboutic/eboutic_payment_result.jinja'

    def post(self, request, *args, **kwargs):
        try:
            with transaction.atomic():
                if 'basket_id' not in request.session.keys() or not request.user.is_authenticated():
                    return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))
                b = Basket.objects.filter(id=request.session['basket_id']).first()
Skia's avatar
Skia committed
124
                if b is None or b.items.filter(type="REFILLING").exists():
Skia's avatar
Skia committed
125
126
127
                    return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))
                c = Customer.objects.filter(user__id=b.user.id).first()
                if c is None:
128
129
130
                    return HttpResponseRedirect(reverse_lazy('eboutic:main', args=self.args, kwargs=kwargs))
                kwargs['not_enough'] = True
                if c.amount < b.get_total():
Skia's avatar
Skia committed
131
                    raise DataError(_("You do not have enough money to buy the basket"))
132
133
134
135
136
137
                else:
                    i = Invoice()
                    i.user = b.user
                    i.payment_method = "SITH_ACCOUNT"
                    i.save()
                    for it in b.items.all():
Skia's avatar
Skia committed
138
                        InvoiceItem(invoice=i, product_id=it.product_id, product_name=it.product_name, type=it.type,
139
140
                                product_unit_price=it.product_unit_price, quantity=it.quantity).save()
                    i.validate()
Skia's avatar
Skia committed
141
                    b.delete()
142
143
144
145
146
147
148
                    kwargs['not_enough'] = False
                    request.session.pop('basket_id', None)
        except DataError as e:
                kwargs['not_enough'] = True
        return self.render_to_response(self.get_context_data(**kwargs))

class EtransactionAutoAnswer(View):
Skia's avatar
Skia committed
149
150
151
152
153
154
    def get(self, request, *args, **kwargs):
        if (not 'Amount' in request.GET.keys() or
            not 'BasketID' in request.GET.keys() or
            not 'Auto' in request.GET.keys() or
            not 'Error' in request.GET.keys() or
            not 'Sig' in request.GET.keys()):
Skia's avatar
Skia committed
155
            return HttpResponse("Bad arguments", status=400)
Skia's avatar
Skia committed
156
157
158
159
160
161
162
        key = crypto.load_publickey(crypto.FILETYPE_PEM, settings.SITH_EBOUTIC_PUB_KEY)
        cert = crypto.X509()
        cert.set_pubkey(key)
        sig = base64.b64decode(request.GET['Sig'])
        try:
            crypto.verify(cert, sig, '&'.join(request.META['QUERY_STRING'].split('&')[:-1]), "sha1")
        except:
Skia's avatar
Skia committed
163
            return HttpResponse("Bad signature", status=400)
Skia's avatar
Skia committed
164
        if request.GET['Error'] == "00000":
Skia's avatar
Skia committed
165
166
167
168
169
170
171
172
173
            with transaction.atomic():
                b = Basket.objects.filter(id=request.GET['BasketID']).first()
                if b is None:
                    return HttpResponse("Basket does not exists", status=400)
                i = Invoice()
                i.user = b.user
                i.payment_method = "CREDIT_CARD"
                i.save()
                for it in b.items.all():
Skia's avatar
Skia committed
174
175
                    InvoiceItem(invoice=i, product_id=it.product_id, product_name=it.product_name, type=it.type,
                        product_unit_price=it.product_unit_price, quantity=it.quantity).save()
Skia's avatar
Skia committed
176
                i.validate()
Skia's avatar
Skia committed
177
                b.delete()
Skia's avatar
Skia committed
178
            return HttpResponse()
Skia's avatar
Skia committed
179
        else:
Skia's avatar
Skia committed
180
            return HttpResponse("Payment failed with error: "+request.GET['Error'])
Skia's avatar
Skia committed
181