source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/interswitch/browser.py @ 14395

Last change on this file since 14395 was 13585, checked in by Henrik Bettermann, 9 years ago

Only Interswitch payments are suitable for verification.

Do no change payment ticket if response code is 20050.

  • Property svn:keywords set to Id
File size: 12.4 KB
RevLine 
[9781]1## $Id: browser.py 13585 2016-01-11 08:57:40Z henrik $
2##
3## Copyright (C) 2012 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
[12973]19from datetime import datetime, timedelta
[11630]20from zope.component import getUtility
[13578]21from zope.security import checkPermission
[11630]22from waeup.kofa.interfaces import IKofaUtils
23from waeup.kofa.utils.helpers import to_timezone
24from waeup.kofa.browser.layout import UtilityView, KofaPage
[9781]25from waeup.kofa.browser.viewlets import ManageActionButton
[11642]26from waeup.kofa.students.interfaces import IStudentsUtils
[9781]27from waeup.kofa.students.browser import OnlinePaymentDisplayFormPage as OPDPStudent
28from waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant
29from kofacustom.nigeria.interswitch.helpers import (
30    query_interswitch, write_payments_log)
31from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
32from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment
33from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment
34from kofacustom.nigeria.interfaces import MessageFactory as _
35
[13581]36# Buttons
37
[9781]38class InterswitchActionButtonStudent(ManageActionButton):
39    grok.order(1)
40    grok.context(INigeriaOnlinePayment)
41    grok.view(OPDPStudent)
42    grok.require('waeup.payStudent')
43    icon = 'actionicon_pay.png'
44    text = _('CollegePAY')
45    target = 'goto_interswitch'
46
47    @property
48    def target_url(self):
49        if self.context.p_state != 'unpaid':
50            return ''
51        return self.view.url(self.view.context, self.target)
52
53class InterswitchActionButtonApplicant(InterswitchActionButtonStudent):
54    grok.view(OPDPApplicant)
55    grok.require('waeup.payApplicant')
56
57class InterswitchRequestWebserviceActionButtonStudent(ManageActionButton):
58    grok.order(2)
59    grok.context(INigeriaOnlinePayment)
60    grok.view(OPDPStudent)
61    grok.require('waeup.payStudent')
62    icon = 'actionicon_call.png'
63    text = _('Requery CollegePAY')
64    target = 'request_webservice'
65
66    @property
67    def target_url(self):
[13580]68        if self.context.p_state in ('paid', 'waived'):
[9781]69            return ''
70        return self.view.url(self.view.context, self.target)
71
72class InterswitchRequestWebserviceActionButtonApplicant(
73    InterswitchRequestWebserviceActionButtonStudent):
74    grok.view(OPDPApplicant)
75    grok.require('waeup.payApplicant')
76
[13581]77class InterswitchVerifyWebserviceActionButtonStudent(ManageActionButton):
78    grok.order(3)
79    grok.context(INigeriaOnlinePayment)
80    grok.view(OPDPStudent)
81    grok.require('waeup.manageStudent')
82    icon = 'actionicon_call.png'
83    text = _('Verify Payment')
84    target = 'verify_payment'
85
86    @property
87    def target_url(self):
[13585]88        if self.context.p_state != 'paid' \
89            or self.context.r_company != u'interswitch':
[13581]90            return ''
91        return self.view.url(self.view.context, self.target)
92
93class InterswitchVerifyWebserviceActionButtonApplicant(
94    InterswitchVerifyWebserviceActionButtonStudent):
95    grok.view(OPDPApplicant)
96    grok.require('waeup.manageApplication')
97
98
99# Webservice request views
100
[9781]101class InterswitchPaymentRequestWebservicePageStudent(UtilityView, grok.View):
102    """ Request webservice view for the CollegePAY gateway
103    """
104    grok.context(INigeriaStudentOnlinePayment)
105    grok.name('request_webservice')
106    grok.require('waeup.payStudent')
107
108    product_id = None
109    gateway_host = None
110    gateway_url = None
[13044]111    https = True
[13387]112    mac = None
[9781]113
114    def update(self):
[13580]115        if self.context.p_state in ('paid', 'waived'):
[13579]116            self.flash(_('This ticket has already been paid.'), type='danger')
[9781]117            return
118        student = self.context.student
119        success, msg, log = query_interswitch(
[11915]120            self.context, self.product_id,
121            self.gateway_host, self.gateway_url,
[13584]122            self.https, self.mac, False)
[9781]123        student.writeLogMessage(self, log)
124        if not success:
[11579]125            self.flash(msg, type='danger')
[9781]126            return
127        write_payments_log(student.student_id, self.context)
[11581]128        flashtype, msg, log = self.context.doAfterStudentPayment()
[9781]129        if log is not None:
130            student.writeLogMessage(self, log)
[11581]131        self.flash(msg, type=flashtype)
[9781]132        return
133
134    def render(self):
135        self.redirect(self.url(self.context, '@@index'))
136        return
137
138class InterswitchPaymentRequestWebservicePageApplicant(UtilityView, grok.View):
139    """ Request webservice view for the CollegePAY gateway
140    """
141    grok.context(INigeriaApplicantOnlinePayment)
142    grok.name('request_webservice')
143    grok.require('waeup.payApplicant')
144
145    product_id = None
146    gateway_host = None
147    gateway_url = None
[13044]148    https = True
[13387]149    mac = None
[9781]150
151    def update(self):
[13580]152        if self.context.p_state == 'paid':
[11642]153            self.flash(_('This ticket has already been paid.'), type='danger')
[9781]154            return
155        applicant = self.context.__parent__
156        success, msg, log = query_interswitch(
[11915]157            self.context, self.product_id,
158            self.gateway_host, self.gateway_url,
[13584]159            self.https, self.mac, False)
[9781]160        applicant.writeLogMessage(self, log)
161        if not success:
[11579]162            self.flash(msg, type='danger')
[9781]163            return
164        write_payments_log(applicant.applicant_id, self.context)
[11581]165        flashtype, msg, log = self.context.doAfterApplicantPayment()
[9781]166        if log is not None:
167            applicant.writeLogMessage(self, log)
[11581]168        self.flash(msg, type=flashtype)
[9781]169        return
170
171    def render(self):
172        self.redirect(self.url(self.context, '@@index'))
173        return
[11630]174
[13581]175class InterswitchPaymentVerifyWebservicePageStudent(UtilityView, grok.View):
176    """ Verify payment view for the CollegePAY gateway
177    """
178    grok.context(INigeriaStudentOnlinePayment)
179    grok.name('verify_payment')
180    grok.require('waeup.manageStudent')
181
182    product_id = None
183    gateway_host = None
184    gateway_url = None
185    https = True
186    mac = None
187
188    def update(self):
[13585]189        if self.context.p_state  != 'paid' \
190            or self.context.r_company != u'interswitch':
[13581]191            self.flash(_('This ticket has not been paid.'), type='danger')
192            return
193        student = self.context.student
194        success, msg, log = query_interswitch(
195            self.context, self.product_id,
196            self.gateway_host, self.gateway_url,
[13584]197            self.https, self.mac, True)
[13581]198        student.writeLogMessage(self, log)
199        if not success:
200            self.flash(msg, type='danger')
201            return
202        self.flash(msg)
203        return
204
205    def render(self):
206        self.redirect(self.url(self.context, '@@index'))
207        return
208
209class InterswitchPaymentVerifyWebservicePageApplicant(UtilityView, grok.View):
210    """ Verify payment view for the CollegePAY gateway
211    """
212    grok.context(INigeriaApplicantOnlinePayment)
213    grok.name('verify_payment')
214    grok.require('waeup.manageApplication')
215
216    product_id = None
217    gateway_host = None
218    gateway_url = None
219    https = True
220    mac = None
221
222    def update(self):
[13585]223        if self.context.p_state != 'paid' \
224            or self.context.r_company != u'interswitch':
[13581]225            self.flash(_('This ticket has not been paid.'), type='danger')
226            return
227        applicant = self.context.__parent__
228        success, msg, log = query_interswitch(
229            self.context, self.product_id,
230            self.gateway_host, self.gateway_url,
[13584]231            self.https, self.mac, True)
[13581]232        applicant.writeLogMessage(self, log)
233        if not success:
234            self.flash(msg, type='danger')
235            return
236        self.flash(msg)
237        return
238
239    def render(self):
240        self.redirect(self.url(self.context, '@@index'))
241        return
242
243# Forwarding pages
244
[11630]245class InterswitchPageStudent(KofaPage):
246    """ View which sends a POST request to the Interswitch
247    CollegePAY payment gateway.
248    """
249    grok.context(INigeriaOnlinePayment)
250    grok.name('goto_interswitch')
251    grok.template('student_goto_interswitch')
252    grok.require('waeup.payStudent')
253    label = _('Submit data to CollegePAY (Interswitch Payment Gateway)')
254    submit_button = _('Submit')
255
[11639]256    action = None
257    site_name = None
258    currency = None
259    pay_item_id = None
260    product_id = None
261    xml_data = None
[12477]262    hashvalue = None
[11639]263
[11642]264    def init_update(self):
[11630]265        if self.context.p_state == 'paid':
[11642]266            return _("Payment ticket can't be re-sent to CollegePAY.")
[13478]267        now = datetime.utcnow()
268        if self.context.creation_date.tzinfo is not None:
269            # That's bad. Please store timezone-naive datetimes only!
270            now = self.context.creation_date.tzinfo.localize(now)
271        time_delta = now - self.context.creation_date
[13015]272        if time_delta.days > 7:
[12973]273            return _("This payment ticket is too old. Please create a new ticket.")
[11642]274        student = self.context.student
[11630]275        certificate = getattr(student['studycourse'],'certificate',None)
276        if certificate is None:
[11642]277            return _("Study course data are incomplete.")
[11639]278        kofa_utils = getUtility(IKofaUtils)
[11642]279        student_utils = getUtility(IStudentsUtils)
280        if student_utils.samePaymentMade(student, self.context.p_category,
281            self.context.p_item, self.context.p_session):
282            return _("This type of payment has already been made.")
[11767]283        self.amount_auth = int(100 * self.context.amount_auth)
[11630]284        xmldict = {}
285        if certificate is not None:
286            xmldict['department'] = certificate.__parent__.__parent__.code
287            xmldict['faculty'] = certificate.__parent__.__parent__.__parent__.code
288        else:
289            xmldict['department'] = None
290            xmldict['faculty'] = None
[12509]291        self.category = self.context.category
[11639]292        tz = kofa_utils.tzinfo
[11630]293        self.local_date_time = to_timezone(
294            self.context.creation_date, tz).strftime("%Y-%m-%d %H:%M:%S %Z")
295        self.site_redirect_url = self.url(self.context, 'request_webservice')
[11642]296        self.student = student
297        self.xmldict = xmldict
298        return
[11630]299
[11642]300    def update(self):
301        error = self.init_update()
302        if error:
303            self.flash(error, type='danger')
304            self.redirect(self.url(self.context, '@@index'))
305        return
306
[11630]307class InterswitchPageApplicant(KofaPage):
308    """ View which sends a POST request to the Interswitch
309    CollegePAY payment gateway.
310    """
311    grok.context(INigeriaApplicantOnlinePayment)
312    grok.require('waeup.payApplicant')
313    grok.template('applicant_goto_interswitch')
314    grok.name('goto_interswitch')
315    label = _('Submit data to CollegePAY (Interswitch Payment Gateway)')
316    submit_button = _('Submit')
[12477]317    hashvalue = None
[11630]318
[11639]319    action = None
320    site_name = None
321    currency = None
322    pay_item_id = None
323    product_id = None
324    xml_data = None
325
[11642]326    def init_update(self):
[11630]327        if self.context.p_state != 'unpaid':
[11642]328            return _("Payment ticket can't be re-sent to CollegePAY.")
[11630]329        if self.context.__parent__.__parent__.expired \
330            and self.context.__parent__.__parent__.strict_deadline:
[11642]331            return _("Payment ticket can't be send to CollegePAY. "
332                     "Application period has expired.")
[12973]333        tz = getUtility(IKofaUtils).tzinfo
334        time_delta = datetime.utcnow() - self.context.creation_date
[13015]335        if time_delta.days > 7:
[12973]336            return _("This payment ticket is too old. Please create a new ticket.")
[11630]337        self.applicant = self.context.__parent__
[11767]338        self.amount_auth = int(100 * self.context.amount_auth)
[12509]339        self.category = self.context.category
[11630]340        tz = getUtility(IKofaUtils).tzinfo
341        self.local_date_time = to_timezone(
342            self.context.creation_date, tz).strftime("%Y-%m-%d %H:%M:%S %Z")
343        self.site_redirect_url = self.url(self.context, 'request_webservice')
[11642]344        return
345
346    def update(self):
347        error = self.init_update()
348        if error:
349            self.flash(error, type='danger')
350            self.redirect(self.url(self.context, '@@index'))
[13478]351        return
Note: See TracBrowser for help on using the repository browser.