source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/etranzact/studentsbrowser.py @ 15730

Last change on this file since 15730 was 15702, checked in by Henrik Bettermann, 5 years ago

Add first Payoutlet components. Not yet tested.
Rename eTranzact.

File size: 7.6 KB
Line 
1## $Id: studentsbrowser.py 15599 2019-09-20 13:24:59Z henrik $
2##
3## Copyright (C) 2017 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import grok
19import hashlib
20from datetime import datetime, timedelta
21from zope.component import getUtility
22from zope.security import checkPermission
23from waeup.kofa.interfaces import IKofaUtils
24from waeup.kofa.utils.helpers import to_timezone
25from waeup.kofa.browser.layout import UtilityView, KofaPage
26from waeup.kofa.browser.viewlets import ManageActionButton
27from kofacustom.nigeria.etranzact.helpers import (
28    write_payments_log, process_response, query_history)
29from kofacustom.nigeria.students.browser import NigeriaOnlinePaymentDisplayFormPage as NOPDPStudent
30from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
31from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment
32from kofacustom.nigeria.interfaces import MessageFactory as _
33
34from kofacustom.nigeria.etranzact.tests import (
35    TERMINAL_ID, HOST, HTTPS, SECRET_KEY, LOGO_URL)
36
37grok.templatedir('browser_templates')
38
39def module_activated(session):
40    try:
41        return getattr(grok.getSite()['configuration'][str(session)],
42            'etranzact_webconnect_enabled', False)
43    except KeyError:
44        return False
45
46class EtranzactActionButtonStudent(ManageActionButton):
47    grok.order(1)
48    grok.context(INigeriaOnlinePayment)
49    grok.view(NOPDPStudent)
50    grok.require('waeup.payStudent')
51    icon = 'actionicon_pay.png'
52    text = _('Pay via Etranzact')
53    target = 'goto_etranzact'
54
55    @property
56    def target_url(self):
57        if not module_activated(self.context.student.current_session):
58            return ''
59        if self.context.p_state != 'unpaid':
60            return ''
61        return self.view.url(self.view.context, self.target)
62
63class EtranzactRequeryActionButtonStudent(ManageActionButton):
64    grok.order(2)
65    grok.context(INigeriaOnlinePayment)
66    grok.view(NOPDPStudent)
67    grok.require('waeup.payStudent')
68    icon = 'actionicon_call.png'
69    text = _('Requery Etranzact History')
70    target = 'requery_history'
71
72    @property
73    def target_url(self):
74        if not module_activated(self.context.student.current_session):
75            return ''
76        if self.context.p_state in ('paid', 'waived'):
77            return ''
78        return self.view.url(self.view.context, self.target)
79
80class EtranzactPageStudent(KofaPage):
81    """ View which sends a POST request to the Etranzact payment gateway.
82    """
83    grok.context(INigeriaStudentOnlinePayment)
84    grok.name('goto_etranzact')
85    grok.template('goto_etranzact')
86    grok.require('waeup.payStudent')
87    label = _('Pay via Etranzact')
88    submit_button = _('Pay now')
89
90    host = HOST
91    https = HTTPS
92    secret_key = SECRET_KEY
93    terminal_id = TERMINAL_ID
94    logo_url = LOGO_URL
95
96    @property
97    def action(self):
98        if self.https:
99            return 'https://' + self.host + '/webconnect/v3/caller.jsp'
100        return 'http://' + self.host + '/webconnect/v3/caller.jsp'
101
102    def init_update(self):
103        if self.context.p_state == 'paid':
104            return _("Payment ticket can't be re-sent to Etranzact.")
105        now = datetime.utcnow()
106        if self.context.creation_date.tzinfo is not None:
107            # That's bad. Please store timezone-naive datetimes only!
108            now = self.context.creation_date.tzinfo.localize(now)
109        time_delta = now - self.context.creation_date
110        if time_delta.days > 7:
111            return _("This payment ticket is too old. Please create a new ticket.")
112        # In contrast to the procedure in the Remita and Interswitch modules,
113        # we do not call requery_history but receive and evaluate
114        # the response form from Etranzact directly. This is possible
115        # because Etranzact provides the FINAL_CHECKSUM hash value
116        # which authenticates the response.
117        self.responseurl = self.url(self.context, 'receive_etranzact')
118        # Already now it becomes a Etranzact payment
119        self.context.r_company = u'etranzact'
120        hashargs =      self.amount + self.terminal_id+self.transaction_id \
121            + self.responseurl + self.secret_key
122        self.hashvalue = hashlib.md5(hashargs).hexdigest()
123        self.customer = self.context.student
124        return
125
126    def update(self):
127        if not module_activated(self.context.student.current_session):
128            return
129        self.transaction_id = self.context.p_id
130        self.amount = "%.1f" % self.context.amount_auth
131        error = self.init_update()
132        if error:
133            self.flash(error, type='danger')
134            self.redirect(self.url(self.context, '@@index'))
135            return
136        return
137
138class EtranzactReceiveResponseStudent(NOPDPStudent):
139    """ View that receives the response from eTrantact payment gateway.
140    """
141    grok.name('receive_etranzact')
142
143    secret_key = SECRET_KEY
144    terminal_id = TERMINAL_ID
145
146    def update(self):
147        super(EtranzactReceiveResponseStudent, self).update()
148        if not module_activated(self.context.student.current_session):
149            return
150        student = self.context.student
151        form = self.request.form
152        verify = False
153        if self.context.p_state == 'paid':
154            verify = True
155        success, msg, log = process_response(self.context, form, self, verify)
156        student.writeLogMessage(self, log)
157        if not success:
158            self.flash(msg, type='danger')
159            return
160        write_payments_log(student.student_id, self.context)
161        flashtype, msg, log = self.context.doAfterStudentPayment()
162        if log is not None:
163            student.writeLogMessage(self, log)
164        self.flash(msg, type=flashtype)
165        return
166
167class EtranzactRequestPaymentStatusPageStudent(UtilityView, grok.View):
168    """ Request webservice view for the Etranzact gateway.
169    """
170    grok.context(INigeriaStudentOnlinePayment)
171    grok.name('requery_history')
172    grok.require('waeup.payStudent')
173
174    host = HOST
175    https = HTTPS
176    secret_key = SECRET_KEY
177    terminal_id = TERMINAL_ID
178    logo_url = LOGO_URL
179
180    def update(self):
181        if not module_activated(self.context.student.current_session):
182            return
183        if self.context.p_state in ('paid', 'waived'):
184            self.flash(_('This ticket has already been paid.'), type='danger')
185            return
186        student = self.context.student
187        verify = False
188        raw, form = query_history(self.host, self.terminal_id,
189                                  self.context.p_id, self.https)
190        success, msg, log = process_response(self.context, form, self, verify)
191        student.writeLogMessage(self, log)
192        if not success:
193            self.flash(msg, type='danger')
194            return
195        write_payments_log(student.student_id, self.context)
196        flashtype, msg, log = self.context.doAfterStudentPayment()
197        if log is not None:
198            student.writeLogMessage(self, log)
199        self.flash(msg, type=flashtype)
200        return
201
202    def render(self):
203        self.redirect(self.url(self.context))
204        return
Note: See TracBrowser for help on using the repository browser.