source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/etranzact/applicantsbrowser.py @ 15599

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

Redirect to payment view.

  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
1## $Id: applicantsbrowser.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 waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant
28from kofacustom.nigeria.etranzact.helpers import (
29    write_payments_log, process_response, query_history)
30from kofacustom.nigeria.applicants.browser import NigeriaOnlinePaymentDisplayFormPage
31from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
32from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment
33from kofacustom.nigeria.interfaces import MessageFactory as _
34
35from kofacustom.nigeria.etranzact.tests import (
36    TERMINAL_ID, HOST, HTTPS, SECRET_KEY, LOGO_URL)
37
38grok.templatedir('browser_templates')
39
40def module_activated(session):
41    try:
42        return getattr(grok.getSite()['configuration'][str(session)],
43            'etranzact_enabled', False)
44    except KeyError:
45        return False
46
47class EtranzactActionButtonApplicant(ManageActionButton):
48    grok.order(1)
49    grok.context(INigeriaOnlinePayment)
50    grok.view(OPDPApplicant)
51    grok.require('waeup.payApplicant')
52    icon = 'actionicon_pay.png'
53    text = _('Pay via eTranzact')
54    target = 'goto_etranzact'
55
56    @property
57    def target_url(self):
58        if not module_activated(self.context.__parent__.__parent__.year):
59            return ''
60        if self.context.p_state != 'unpaid':
61            return ''
62        return self.view.url(self.view.context, self.target)
63
64class EtranzactRequeryActionButtonApplicant(ManageActionButton):
65    grok.order(2)
66    grok.context(INigeriaOnlinePayment)
67    grok.view(OPDPApplicant)
68    grok.require('waeup.payApplicant')
69    icon = 'actionicon_call.png'
70    text = _('Requery eTranzact History')
71    target = 'requery_history'
72
73    @property
74    def target_url(self):
75        if not module_activated(self.context.__parent__.__parent__.year):
76            return ''
77        if self.context.p_state in ('paid', 'waived'):
78            return ''
79        return self.view.url(self.view.context, self.target)
80
81class EtranzactPageApplicant(KofaPage):
82    """ View which sends a POST request to the eTranzact payment gateway.
83    """
84    grok.context(INigeriaApplicantOnlinePayment)
85    grok.name('goto_etranzact')
86    grok.template('goto_etranzact')
87    grok.require('waeup.payApplicant')
88    label = _('Pay via eTranzact')
89    submit_button = _('Pay now')
90
91    host = HOST
92    https = HTTPS
93    secret_key = SECRET_KEY
94    terminal_id = TERMINAL_ID
95    logo_url = LOGO_URL
96
97    @property
98    def action(self):
99        if self.https:
100            return 'https://' + self.host + '/webconnect/v3/caller.jsp'
101        return 'http://' + self.host + '/webconnect/v3/caller.jsp'
102
103    def init_update(self):
104        if self.context.p_state == 'paid':
105            return _("Payment ticket can't be re-sent to eTranzact.")
106        now = datetime.utcnow()
107        if self.context.creation_date.tzinfo is not None:
108            # That's bad. Please store timezone-naive datetimes only!
109            now = self.context.creation_date.tzinfo.localize(now)
110        time_delta = now - self.context.creation_date
111        if time_delta.days > 7:
112            return _("This payment ticket is too old. Please create a new ticket.")
113        # In contrast to the procedure in the Remita and Interswitch modules,
114        # we do not call requery_history but receive and evaluate
115        # the response form from eTranzact directly. This is possible
116        # because eTranzact provides the FINAL_CHECKSUM hash value
117        # which authenticates the response.
118        self.responseurl = self.url(self.context, 'receive_etranzact')
119        # Already now it becomes a eTranzact payment
120        self.context.r_company = u'etranzact'
121        hashargs =      self.amount + self.terminal_id+self.transaction_id \
122            + self.responseurl + self.secret_key
123        self.hashvalue = hashlib.md5(hashargs).hexdigest()
124        self.customer = self.context.__parent__
125        return
126
127    def update(self):
128        if not module_activated(self.context.__parent__.__parent__.year):
129            return
130        self.transaction_id = self.context.p_id
131        self.amount = "%.1f" % self.context.amount_auth
132        error = self.init_update()
133        if error:
134            self.flash(error, type='danger')
135            self.redirect(self.url(self.context, '@@index'))
136            return
137        return
138
139class EtranzactReceiveResponseApplicant(NigeriaOnlinePaymentDisplayFormPage):
140    """ View that receives the response from eTrantact payment gateway.
141    """
142    grok.name('receive_etranzact')
143
144    secret_key = SECRET_KEY
145    terminal_id = TERMINAL_ID
146
147    def update(self):
148        super(EtranzactReceiveResponseApplicant, self).update()
149        if not module_activated(self.context.__parent__.__parent__.year):
150            return
151        applicant = self.context.__parent__
152        form = self.request.form
153        verify = False
154        if self.context.p_state == 'paid':
155            verify = True
156        success, msg, log = process_response(self.context, form, self, verify)
157        applicant.writeLogMessage(self, log)
158        if not success:
159            self.flash(msg, type='danger')
160            return
161        write_payments_log(applicant.applicant_id, self.context)
162        flashtype, msg, log = self.context.doAfterApplicantPayment()
163        if log is not None:
164            applicant.writeLogMessage(self, log)
165        self.flash(msg, type=flashtype)
166        return
167
168class EtranzactRequestPaymentStatusPageApplicant(UtilityView, grok.View):
169    """ Request webservice view for the eTranzact gateway.
170    """
171    grok.context(INigeriaApplicantOnlinePayment)
172    grok.name('requery_history')
173    grok.require('waeup.payApplicant')
174
175    host = HOST
176    https = HTTPS
177    secret_key = SECRET_KEY
178    terminal_id = TERMINAL_ID
179    logo_url = LOGO_URL
180
181    def update(self):
182        if not module_activated(self.context.__parent__.__parent__.year):
183            return
184        if self.context.p_state in ('paid', 'waived'):
185            self.flash(_('This ticket has already been paid.'), type='danger')
186            return
187        applicant = self.context.__parent__
188        verify = False
189        raw, form = query_history(self.host, self.terminal_id,
190                                  self.context.p_id, self.https)
191        success, msg, log = process_response(self.context, form, self, verify)
192        applicant.writeLogMessage(self, log)
193        if not success:
194            self.flash(msg, type='danger')
195            return
196        write_payments_log(applicant.applicant_id, self.context)
197        flashtype, msg, log = self.context.doAfterApplicantPayment()
198        if log is not None:
199            applicant.writeLogMessage(self, log)
200        self.flash(msg, type=flashtype)
201        return
202
203    def render(self):
204        self.redirect(self.url(self.context))
205        return
Note: See TracBrowser for help on using the repository browser.