## $Id: browser.py 16247 2020-09-24 06:49:25Z henrik $ ## ## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## import grok from datetime import datetime, timedelta from zope.component import getUtility from zope.security import checkPermission from waeup.kofa.interfaces import IKofaUtils from waeup.kofa.utils.helpers import to_timezone from waeup.kofa.browser.layout import UtilityView, KofaPage from waeup.kofa.browser.viewlets import ManageActionButton from waeup.kofa.students.interfaces import IStudentsUtils from waeup.kofa.students.browser import OnlinePaymentDisplayFormPage as OPDPStudent from waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant from kofacustom.nigeria.interswitch.helpers import ( query_interswitch, write_payments_log) from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment from kofacustom.nigeria.interfaces import MessageFactory as _ GATEWAY_AMT = 300.0 # Buttons def module_activated(session, payment): if payment.r_company and payment.r_company != 'interswitch': return False try: return getattr(grok.getSite()['configuration'][str(session)], 'interswitch_enabled', True) except KeyError: session = datetime.now().year try: return getattr(grok.getSite()['configuration'][str(session)], 'interswitch_enabled', True) except KeyError: return False class InterswitchActionButtonStudent(ManageActionButton): grok.order(1) grok.context(INigeriaOnlinePayment) grok.view(OPDPStudent) grok.require('waeup.payStudent') icon = 'actionicon_pay.png' text = _('Pay via Interswitch') target = 'goto_interswitch' @property def target_url(self): if not module_activated( self.context.student.current_session, self.context): return '' if self.context.p_state != 'unpaid': return '' return self.view.url(self.view.context, self.target) class InterswitchActionButtonApplicant(InterswitchActionButtonStudent): grok.view(OPDPApplicant) grok.require('waeup.payApplicant') @property def target_url(self): if not module_activated( self.context.__parent__.__parent__.year, self.context): return '' if self.context.p_state != 'unpaid': return '' return self.view.url(self.view.context, self.target) class InterswitchRequestWebserviceActionButtonStudent(ManageActionButton): grok.order(2) grok.context(INigeriaOnlinePayment) grok.view(OPDPStudent) grok.require('waeup.payStudent') icon = 'actionicon_call.png' text = _('Requery Interswitch History') target = 'request_webservice' @property def target_url(self): if not module_activated( self.context.student.current_session, self.context): return '' if self.context.p_state in ('paid', 'waived', 'scholarship'): return '' return self.view.url(self.view.context, self.target) class InterswitchRequestWebserviceActionButtonApplicant( InterswitchRequestWebserviceActionButtonStudent): grok.view(OPDPApplicant) grok.require('waeup.payApplicant') @property def target_url(self): if not module_activated( self.context.__parent__.__parent__.year, self.context): return '' if self.context.p_state in ('paid', 'waived', 'scholarship'): return '' return self.view.url(self.view.context, self.target) class InterswitchVerifyWebserviceActionButtonStudent(ManageActionButton): grok.order(3) grok.context(INigeriaOnlinePayment) grok.view(OPDPStudent) grok.require('waeup.manageStudent') icon = 'actionicon_call.png' text = _('Verify Payment') target = 'verify_payment' @property def target_url(self): if not module_activated( self.context.student.current_session, self.context): return '' if self.context.p_state != 'paid' \ or self.context.r_company != u'interswitch': return '' return self.view.url(self.view.context, self.target) class InterswitchVerifyWebserviceActionButtonApplicant( InterswitchVerifyWebserviceActionButtonStudent): grok.view(OPDPApplicant) grok.require('waeup.manageApplication') @property def target_url(self): if not module_activated( self.context.__parent__.__parent__.year, self.context): return '' if self.context.p_state != 'paid' \ or self.context.r_company != u'interswitch': return '' return self.view.url(self.view.context, self.target) # Webservice request views class InterswitchPaymentRequestWebservicePageStudent(UtilityView, grok.View): """ Request webservice view for the CollegePAY gateway """ grok.context(INigeriaStudentOnlinePayment) grok.name('request_webservice') grok.require('waeup.payStudent') product_id = None gateway_host = None gateway_url = None https = True mac = None def update(self): if not module_activated( self.context.student.current_session, self.context): return if self.context.p_state in ('paid', 'waived', 'scholarship'): self.flash(_('This ticket has already been paid.'), type='danger') return student = self.context.student success, msg, log = query_interswitch( self.context, self.product_id, self.gateway_host, self.gateway_url, self.https, self.mac, False) student.writeLogMessage(self, log) if not success: self.flash(msg, type='danger') return write_payments_log(student.student_id, self.context) flashtype, msg, log = self.context.doAfterStudentPayment() if log is not None: student.writeLogMessage(self, log) self.flash(msg, type=flashtype) return def render(self): self.redirect(self.url(self.context, '@@index')) return class InterswitchPaymentRequestWebservicePageApplicant(UtilityView, grok.View): """ Request webservice view for the CollegePAY gateway """ grok.context(INigeriaApplicantOnlinePayment) grok.name('request_webservice') grok.require('waeup.payApplicant') product_id = None gateway_host = None gateway_url = None https = True mac = None def update(self): if not module_activated( self.context.__parent__.__parent__.year, self.context): return if self.context.p_state == 'paid': self.flash(_('This ticket has already been paid.'), type='danger') return applicant = self.context.__parent__ success, msg, log = query_interswitch( self.context, self.product_id, self.gateway_host, self.gateway_url, self.https, self.mac, False) applicant.writeLogMessage(self, log) if not success: self.flash(msg, type='danger') return write_payments_log(applicant.applicant_id, self.context) flashtype, msg, log = self.context.doAfterApplicantPayment() if log is not None: applicant.writeLogMessage(self, log) self.flash(msg, type=flashtype) return def render(self): self.redirect(self.url(self.context.__parent__, 'edit')) return class InterswitchPaymentVerifyWebservicePageStudent(UtilityView, grok.View): """ Verify payment view for the CollegePAY gateway """ grok.context(INigeriaStudentOnlinePayment) grok.name('verify_payment') grok.require('waeup.manageStudent') product_id = None gateway_host = None gateway_url = None https = True mac = None def update(self): if not module_activated( self.context.student.current_session, self.context): return if self.context.p_state != 'paid' \ or self.context.r_company != u'interswitch': self.flash(_('This ticket has not been paid.'), type='danger') return student = self.context.student success, msg, log = query_interswitch( self.context, self.product_id, self.gateway_host, self.gateway_url, self.https, self.mac, True) student.writeLogMessage(self, log) if not success: self.flash(msg, type='danger') return self.flash(msg) return def render(self): self.redirect(self.url(self.context, '@@index')) return class InterswitchPaymentVerifyWebservicePageApplicant(UtilityView, grok.View): """ Verify payment view for the CollegePAY gateway """ grok.context(INigeriaApplicantOnlinePayment) grok.name('verify_payment') grok.require('waeup.manageApplication') product_id = None gateway_host = None gateway_url = None https = True mac = None def update(self): if not module_activated( self.context.__parent__.__parent__.year, self.context): return if self.context.p_state != 'paid' \ or self.context.r_company != u'interswitch': self.flash(_('This ticket has not been paid.'), type='danger') return applicant = self.context.__parent__ success, msg, log = query_interswitch( self.context, self.product_id, self.gateway_host, self.gateway_url, self.https, self.mac, True) applicant.writeLogMessage(self, log) if not success: self.flash(msg, type='danger') return self.flash(msg) return def render(self): self.redirect(self.url(self.context, '@@index')) return # Forwarding pages class InterswitchPageStudent(KofaPage): """ View which sends a POST request to the Interswitch CollegePAY payment gateway. """ grok.context(INigeriaOnlinePayment) grok.name('goto_interswitch') grok.template('student_goto_interswitch') grok.require('waeup.payStudent') label = _('Submit data to CollegePAY (Interswitch Payment Gateway)') submit_button = _('Submit') action = None site_name = None currency = None pay_item_id = None product_id = None xml_data = None hashvalue = None gateway_amt = GATEWAY_AMT def init_update(self): if self.context.p_state == 'paid': return _("Payment ticket can't be re-sent to CollegePAY.") now = datetime.utcnow() if self.context.creation_date.tzinfo is not None: # That's bad. Please store timezone-naive datetimes only! now = self.context.creation_date.tzinfo.localize(now) time_delta = now - self.context.creation_date if time_delta.days > 7: return _("This payment ticket is too old. Please create a new ticket.") if self.context.r_company and self.context.r_company != 'interswitch': return _("Payment ticket has been used for another payment gateway.") student = self.context.student certificate = getattr(student['studycourse'],'certificate',None) if certificate is None: return _("Study course data are incomplete.") kofa_utils = getUtility(IKofaUtils) student_utils = getUtility(IStudentsUtils) if student_utils.samePaymentMade(student, self.context.p_category, self.context.p_item, self.context.p_session): return _("This type of payment has already been made.") xmldict = {} if certificate is not None: xmldict['department'] = certificate.__parent__.__parent__.code xmldict['faculty'] = certificate.__parent__.__parent__.__parent__.code else: xmldict['department'] = None xmldict['faculty'] = None self.category = self.context.category tz = kofa_utils.tzinfo self.local_date_time = to_timezone( self.context.creation_date, tz).strftime("%Y-%m-%d %H:%M:%S %Z") self.site_redirect_url = self.url(self.context, 'request_webservice') self.student = student self.xmldict = xmldict return def update(self): if not module_activated( self.context.student.current_session, self.context): self.flash(_('Forbidden'), type='danger') self.redirect(self.url(self.context, '@@index')) return error = self.init_update() if error: self.flash(error, type='danger') self.redirect(self.url(self.context, '@@index')) # Already now it becomes an Interswitch payment. We set the net amount # and add the gateway amount. if not self.context.r_company: self.context.net_amt = self.context.amount_auth self.context.amount_auth += self.gateway_amt self.context.gateway_amt = self.gateway_amt self.context.r_company = u'interswitch' self.amount_auth = int(100 * self.context.amount_auth) return class InterswitchPageApplicant(KofaPage): """ View which sends a POST request to the Interswitch CollegePAY payment gateway. """ grok.context(INigeriaApplicantOnlinePayment) grok.require('waeup.payApplicant') grok.template('applicant_goto_interswitch') grok.name('goto_interswitch') label = _('Submit data to CollegePAY (Interswitch Payment Gateway)') submit_button = _('Submit') action = None site_name = None currency = None pay_item_id = None product_id = None xml_data = None hashvalue = None gateway_amt = GATEWAY_AMT def init_update(self): if self.context.p_state != 'unpaid': return _("Payment ticket can't be re-sent to CollegePAY.") if self.context.__parent__.__parent__.expired \ and self.context.__parent__.__parent__.strict_deadline: return _("Payment ticket can't be sent to CollegePAY. " "Application period has expired.") if self.context.r_company and self.context.r_company != 'interswitch': return _("Payment ticket has been used for another payment gateway.") tz = getUtility(IKofaUtils).tzinfo time_delta = datetime.utcnow() - self.context.creation_date if time_delta.days > 7: return _("This payment ticket is too old. Please create a new ticket.") self.applicant = self.context.__parent__ self.category = self.context.category tz = getUtility(IKofaUtils).tzinfo self.local_date_time = to_timezone( self.context.creation_date, tz).strftime("%Y-%m-%d %H:%M:%S %Z") self.site_redirect_url = self.url(self.context, 'request_webservice') return def update(self): if not module_activated( self.context.__parent__.__parent__.year, self.context): self.flash(_('Forbidden'), type='danger') self.redirect(self.url(self.context, '@@index')) return error = self.init_update() if error: self.flash(error, type='danger') self.redirect(self.url(self.context, '@@index')) # Already now it becomes an Interswitch payment. We set the net amount # and add the gateway amount. if not self.context.r_company: self.context.net_amt = self.context.amount_auth self.context.amount_auth += self.gateway_amt self.context.gateway_amt = self.gateway_amt self.context.r_company = u'interswitch' self.amount_auth = int(100 * self.context.amount_auth) return