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

Last change on this file since 17958 was 17248, checked in by Henrik Bettermann, 23 months 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.