source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/etranzact/credobrowser.py @ 17929

Last change on this file since 17929 was 17799, checked in by Henrik Bettermann, 4 months ago

No service code no payment.

  • Property svn:executable set to *
File size: 11.1 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, KofaEditFormPage, action, NullValidator
26from waeup.kofa.browser.viewlets import ManageActionButton
27from kofacustom.nigeria.etranzact.helpers import (
28    write_payments_log,
29    initiate_payment,
30    query_credo_payment)
31from kofacustom.nigeria.students.browser import NigeriaOnlinePaymentDisplayFormPage as NOPDPStudent
32from kofacustom.nigeria.applicants.browser import NigeriaOnlinePaymentDisplayFormPage as NOPDPApplicant
33from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
34from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment
35from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment
36from kofacustom.nigeria.interfaces import MessageFactory as _
37
38from kofacustom.nigeria.etranzact.tests import (
39    TERMINAL_ID, CREDO_HOST, HTTPS, SECRET_API_KEY, API_PUBLIC_KEY,
40    LOGO_URL, GATEWAY_AMT)
41
42grok.templatedir('browser_templates')
43
44def credo_module_activated(session, payment):
45    if payment.p_currency != 'NGN':
46        return False
47    if payment.r_company and payment.r_company != 'etranzact':
48        return False
49    try:
50        return getattr(grok.getSite()['configuration'][str(session)],
51            'etranzact_credo_enabled', False)
52    except KeyError:
53        session = datetime.now().year
54        try:
55            return getattr(grok.getSite()['configuration'][str(session)],
56                'etranzact_credo_enabled', False)
57        except KeyError:
58            return False
59
60class CredoActionButtonStudent(ManageActionButton):
61    grok.order(8)
62    grok.context(INigeriaOnlinePayment)
63    grok.view(NOPDPStudent)
64    grok.require('waeup.payStudent')
65    icon = 'actionicon_pay.png'
66    text = _('Pay via Etranzact Credo')
67    target = 'goto_credo'
68
69    @property
70    def target_url(self):
71        if not credo_module_activated(
72            self.context.student.current_session, self.context):
73            return ''
74        if self.context.p_state != 'unpaid':
75            return ''
76        return self.view.url(self.view.context, self.target)
77
78class CredoActionButtonApplicant(CredoActionButtonStudent):
79    grok.context(INigeriaOnlinePayment)
80    grok.require('waeup.payApplicant')
81    grok.view(NOPDPApplicant)
82
83    @property
84    def target_url(self):
85        if not credo_module_activated(
86            self.context.__parent__.__parent__.year, self.context):
87            return ''
88        if self.context.p_state != 'unpaid':
89            return ''
90        return self.view.url(self.view.context, self.target)
91
92class CredoVerifyActionButtonStudent(ManageActionButton):
93    grok.order(9)
94    grok.context(INigeriaOnlinePayment)
95    grok.view(NOPDPStudent)
96    grok.require('waeup.payStudent')
97    icon = 'actionicon_call.png'
98    text = _('Requery Etranzact Credo')
99    target = 'requery_credo'
100
101    @property
102    def target_url(self):
103        if not credo_module_activated(
104            self.context.student.current_session, self.context):
105            return ''
106        if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'):
107            return ''
108        return self.view.url(self.view.context, self.target)
109
110class CredoVerifyActionButtonApplicant(CredoVerifyActionButtonStudent):
111    grok.view(NOPDPApplicant)
112    grok.require('waeup.payApplicant')
113    icon = 'actionicon_call.png'
114    text = _('Requery Etranzact Credo')
115    target = 'requery_credo'
116
117    @property
118    def target_url(self):
119        if not credo_module_activated(
120            self.context.__parent__.__parent__.year, self.context):
121            return ''
122        if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'):
123            return ''
124        return self.view.url(self.view.context, self.target)
125
126class CredoPageStudent(KofaEditFormPage):
127    """ View which sends a POST request to the Credo payment gateway.
128    """
129    grok.context(INigeriaStudentOnlinePayment)
130    grok.name('goto_credo')
131    grok.template('goto_credo')
132    grok.require('waeup.payStudent')
133    label = _('Pay via Credo')
134    submit_button = _('Pay now')
135
136    host = CREDO_HOST
137    api_public_key = API_PUBLIC_KEY
138    gateway_amt = 0.0 # is being added by Etranzact
139
140    serviceCode = None
141
142    def init_update(self):
143        if self.context.p_state == 'paid':
144            return _("Payment ticket can't be re-sent to Etranzact.")
145        now = datetime.utcnow()
146        if self.context.creation_date.tzinfo is not None:
147            # That's bad. Please store timezone-naive datetimes only!
148            now = self.context.creation_date.tzinfo.localize(now)
149        time_delta = now - self.context.creation_date
150        if time_delta.days > 7:
151            return _("This payment ticket is too old. Please create a new ticket.")
152        self.callbackUrl = self.url(self.context, 'requery_credo')
153        return
154
155    def update(self):
156        if not credo_module_activated(
157            self.context.student.current_session, self.context):
158            self.flash(_('Forbidden'), type='danger')
159            self.redirect(self.url(self.context, '@@index'))
160            return
161        # Already now it becomes an Etranzact payment. We set the net amount
162        # and add the gateway amount.
163        if not self.context.r_company:
164            self.context.net_amt = self.context.amount_auth
165            #self.context.amount_auth += self.gateway_amt
166            #self.context.gateway_amt = self.gateway_amt
167            self.context.r_company = u'etranzact'
168        #self.amount = "%.1f" % (100.0 * self.context.amount_auth)
169        error = self.init_update()
170        self.customer = self.context.student
171        if error:
172            self.flash(error, type='danger')
173            self.redirect(self.url(self.context, '@@index'))
174            return
175        return
176
177    @action(_('Pay now'), validator=NullValidator, style='primary')
178    def pay(self, **data):
179        if not self.serviceCode:
180            self.flash('Payment via Credo not possible.', type='danger')
181            self.redirect(self.url(self.context, '@@index'))
182            return
183        success, url_or_message = initiate_payment(
184            self.context, self.host, self.callbackUrl,
185            self.api_public_key, self.serviceCode)
186        if success:
187            self.redirect(url_or_message, trusted=True)
188        else:
189            self.flash(url_or_message, type='danger')
190            self.redirect(self.url(self.context, '@@index'))
191        return
192
193class CredoPageApplicant(CredoPageStudent):
194    """ View which sends a POST request to the Credo payment gateway.
195    """
196    grok.require('waeup.payApplicant')
197    grok.context(INigeriaApplicantOnlinePayment)
198
199    def update(self):
200        if not credo_module_activated(
201            self.context.__parent__.__parent__.year, self.context):
202            self.flash(_('Forbidden'), type='danger')
203            self.redirect(self.url(self.context, '@@index'))
204            return
205        # Already now it becomes an Etranzact payment. We set the net amount
206        # and add the gateway amount.
207        if not self.context.r_company:
208            self.context.net_amt = self.context.amount_auth
209            #self.context.amount_auth += self.gateway_amt
210            #self.context.gateway_amt = self.gateway_amt
211            self.context.r_company = u'etranzact'
212        #self.amount = "%.1f" % (100.0 * self.context.amount_auth)
213        error = self.init_update()
214        self.customer = self.context.__parent__
215        if error:
216            self.flash(error, type='danger')
217            self.redirect(self.url(self.context, '@@index'))
218            return
219        return
220
221class CredoVerifyPaymentStatusPageStudent(UtilityView, grok.View):
222    """ Request webservice view for the Etranzact Credo gateway.
223    """
224    grok.context(INigeriaStudentOnlinePayment)
225    grok.name('requery_credo')
226    grok.require('waeup.payStudent')
227
228    host = CREDO_HOST
229    secret_api_key = SECRET_API_KEY
230
231    def update(self):
232        if not credo_module_activated(
233            self.context.student.current_session, self.context):
234            self.flash(_('Forbidden'), type='danger')
235            self.redirect(self.url(self.context, '@@index'))
236            return
237        if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'):
238            self.flash(_('This ticket has already been processed.'), type='danger')
239            return
240        student = self.context.student
241        #verify = False
242        success, msg, log = query_credo_payment(self.context, self.host, self.secret_api_key)
243        student.writeLogMessage(self, log)
244        if not success:
245            self.flash(msg, type='danger')
246            return
247        write_payments_log(student.student_id, self.context)
248        flashtype, msg, log = self.context.doAfterStudentPayment()
249        if log is not None:
250            student.writeLogMessage(self, log)
251        self.flash(msg, type=flashtype)
252        return
253
254    def render(self):
255        self.redirect(self.url(self.context))
256        return
257
258
259class CredoVerifyPaymentStatusPageApplicant(CredoVerifyPaymentStatusPageStudent):
260    """ Request webservice view for the Etranzact Credo gateway.
261    """
262    grok.context(INigeriaApplicantOnlinePayment)
263    grok.name('requery_credo')
264    grok.require('waeup.payApplicant')
265
266    def update(self):
267        if not credo_module_activated(
268            self.context.__parent__.__parent__.year, self.context):
269            self.flash(_('Forbidden'), type='danger')
270            self.redirect(self.url(self.context, '@@index'))
271            return
272        if self.context.p_state in ('paid', 'waived', 'scholarship', 'failed'):
273            self.flash(_('This ticket has already been processed.'), type='danger')
274            return
275        applicant = self.context.__parent__
276        #verify = False
277        success, msg, log = query_credo_payment(self.context, self.host, self.secret_api_key)
278        applicant.writeLogMessage(self, log)
279        if not success:
280            self.flash(msg, type='danger')
281            return
282        write_payments_log(applicant.applicant_id, self.context)
283        flashtype, msg, log = self.context.doAfterApplicantPayment()
284        if log is not None:
285            applicant.writeLogMessage(self, log)
286        self.flash(msg, type=flashtype)
287        return
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
Note: See TracBrowser for help on using the repository browser.