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

Last change on this file since 17639 was 17248, checked in by Henrik Bettermann, 2 years ago

Enable Paypal only for USD payments.
Enable all other gateway services only for NGN payments.

File size: 9.0 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, GATEWAY_AMT)
36
37grok.templatedir('browser_templates')
38
39def webconnect_module_activated(session, payment):
40    if payment.p_currency != 'NGN':
41        return False
42    if payment.r_company and payment.r_company != 'etranzact':
43        return False
44    try:
45        return getattr(grok.getSite()['configuration'][str(session)],
46            'etranzact_webconnect_enabled', False)
47    except KeyError:
48        session = datetime.now().year
49        try:
50            return getattr(grok.getSite()['configuration'][str(session)],
51                'etranzact_webconnect_enabled', False)
52        except KeyError:
53            return False
54
55class EtranzactActionButtonStudent(ManageActionButton):
56    grok.order(8)
57    grok.context(INigeriaOnlinePayment)
58    grok.view(NOPDPStudent)
59    grok.require('waeup.payStudent')
60    icon = 'actionicon_pay.png'
61    text = _('Pay via Etranzact WebConnect')
62    target = 'goto_etranzact'
63
64    @property
65    def target_url(self):
66        if not webconnect_module_activated(
67            self.context.student.current_session, self.context):
68            return ''
69        if self.context.p_state != 'unpaid':
70            return ''
71        return self.view.url(self.view.context, self.target)
72
73class EtranzactRequeryActionButtonStudent(ManageActionButton):
74    grok.order(9)
75    grok.context(INigeriaOnlinePayment)
76    grok.view(NOPDPStudent)
77    grok.require('waeup.payStudent')
78    icon = 'actionicon_call.png'
79    text = _('Requery Etranzact WebConnect History')
80    target = 'requery_history'
81
82    @property
83    def target_url(self):
84        if not webconnect_module_activated(
85            self.context.student.current_session, self.context):
86            return ''
87        if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'):
88            return ''
89        return self.view.url(self.view.context, self.target)
90
91class EtranzactPageStudent(KofaPage):
92    """ View which sends a POST request to the Etranzact payment gateway.
93    """
94    grok.context(INigeriaStudentOnlinePayment)
95    grok.name('goto_etranzact')
96    grok.template('goto_etranzact')
97    grok.require('waeup.payStudent')
98    label = _('Pay via Etranzact')
99    submit_button = _('Pay now')
100
101    host = HOST
102    https = HTTPS
103    secret_key = SECRET_KEY
104    terminal_id = TERMINAL_ID
105    logo_url = LOGO_URL
106    gateway_amt = GATEWAY_AMT
107
108    @property
109    def action(self):
110        if self.https:
111            return 'https://' + self.host + '/webconnect/v3/caller.jsp'
112        return 'http://' + self.host + '/webconnect/v3/caller.jsp'
113
114    def init_update(self):
115        if self.context.p_state == 'paid':
116            return _("Payment ticket can't be re-sent to Etranzact.")
117        now = datetime.utcnow()
118        if self.context.creation_date.tzinfo is not None:
119            # That's bad. Please store timezone-naive datetimes only!
120            now = self.context.creation_date.tzinfo.localize(now)
121        time_delta = now - self.context.creation_date
122        if time_delta.days > 7:
123            return _("This payment ticket is too old. Please create a new ticket.")
124        # In contrast to the procedure in the Remita and Interswitch modules,
125        # we do not call requery_history but receive and evaluate
126        # the response form from Etranzact directly. This is possible
127        # because Etranzact provides the FINAL_CHECKSUM hash value
128        # which authenticates the response.
129        self.responseurl = self.url(self.context, 'receive_etranzact')
130        self.transaction_id = self.context.p_id
131        self.description = "%s (%s)" % (
132            self.context.p_category, self.context.p_item)
133        hashargs =      self.amount + self.terminal_id + self.transaction_id \
134            + self.responseurl + self.secret_key
135        self.hashvalue = hashlib.md5(hashargs).hexdigest()
136        self.customer = self.context.student
137        return
138
139    def update(self):
140        if not webconnect_module_activated(
141            self.context.student.current_session, self.context):
142            self.flash(_('Forbidden'), type='danger')
143            self.redirect(self.url(self.context, '@@index'))
144            return
145        # Already now it becomes an Etranzact payment. We set the net amount
146        # and add the gateway amount.
147        if not self.context.r_company:
148            self.context.net_amt = self.context.amount_auth
149            self.context.amount_auth += self.gateway_amt
150            self.context.gateway_amt = self.gateway_amt
151            self.context.r_company = u'etranzact'
152        self.amount = "%.1f" % self.context.amount_auth
153        error = self.init_update()
154        if error:
155            self.flash(error, type='danger')
156            self.redirect(self.url(self.context, '@@index'))
157            return
158        return
159
160class EtranzactReceiveResponseStudent(NOPDPStudent):
161    """ View that receives the response from eTrantact payment gateway.
162    """
163    grok.name('receive_etranzact')
164
165    secret_key = SECRET_KEY
166    terminal_id = TERMINAL_ID
167
168    def update(self):
169        super(EtranzactReceiveResponseStudent, self).update()
170        if not webconnect_module_activated(
171            self.context.student.current_session, self.context):
172            self.flash(_('Forbidden'), type='danger')
173            self.redirect(self.url(self.context, '@@index'))
174            return
175        student = self.context.student
176        form = self.request.form
177        verify = False
178        if self.context.p_state == 'paid':
179            verify = True
180        success, msg, log = process_response(self.context, form, self, verify)
181        student.writeLogMessage(self, log)
182        if not success:
183            self.flash(msg, type='danger')
184            return
185        write_payments_log(student.student_id, self.context)
186        flashtype, msg, log = self.context.doAfterStudentPayment()
187        if log is not None:
188            student.writeLogMessage(self, log)
189        self.flash(msg, type=flashtype)
190        return
191
192class EtranzactRequestPaymentStatusPageStudent(UtilityView, grok.View):
193    """ Request webservice view for the Etranzact gateway.
194    """
195    grok.context(INigeriaStudentOnlinePayment)
196    grok.name('requery_history')
197    grok.require('waeup.payStudent')
198
199    host = HOST
200    https = HTTPS
201    secret_key = SECRET_KEY
202    terminal_id = TERMINAL_ID
203    logo_url = LOGO_URL
204
205    def update(self):
206        if not webconnect_module_activated(
207            self.context.student.current_session, self.context):
208            self.flash(_('Forbidden'), type='danger')
209            self.redirect(self.url(self.context, '@@index'))
210            return
211        if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'):
212            self.flash(_('This ticket has already been processed.'), type='danger')
213            return
214        student = self.context.student
215        verify = False
216        raw, form = query_history(self.host, self.terminal_id,
217                                  self.context.p_id, self.https)
218        success, msg, log = process_response(self.context, form, self, verify)
219        student.writeLogMessage(self, log)
220        if not success:
221            self.flash(msg, type='danger')
222            return
223        write_payments_log(student.student_id, self.context)
224        flashtype, msg, log = self.context.doAfterStudentPayment()
225        if log is not None:
226            student.writeLogMessage(self, log)
227        self.flash(msg, type=flashtype)
228        return
229
230    def render(self):
231        self.redirect(self.url(self.context))
232        return
Note: See TracBrowser for help on using the repository browser.