## $Id: browser.py 8710 2012-06-13 13:56:50Z 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 ## from datetime import datetime import httplib import urllib from xml.dom.minidom import parseString import grok from zope.component import getUtility from zope.catalog.interfaces import ICatalog from waeup.kofa.interfaces import IUniversity from waeup.kofa.payments.interfaces import IPaymentWebservice from waeup.kofa.browser.layout import KofaPage, UtilityView from waeup.kofa.students.viewlets import ApprovePaymentActionButton as APABStudent from waeup.kofa.applicants.viewlets import ApprovePaymentActionButton as APABApplicant from waeup.aaue.interfaces import academic_sessions_vocab from waeup.aaue.interfaces import MessageFactory as _ from waeup.aaue.students.interfaces import ICustomStudentOnlinePayment from waeup.aaue.applicants.interfaces import ICustomApplicantOnlinePayment # Kofa's webservice class KofaFeeRequest(grok.View): grok.context(IUniversity) grok.name('feerequest') grok.require('waeup.Public') def update(self, PAYEE_ID=None): cat = getUtility(ICatalog, name='payments_catalog') results = list(cat.searchResults(p_id=(PAYEE_ID, PAYEE_ID))) if len(results) != 1: self.output = '-1' else: try: owner = IPaymentWebservice(results[0]) full_name = owner.display_fullname matric_no = owner.id faculty = owner.faculty department = owner.department except (TypeError, AttributeError): self.output = '-1' return amount = results[0].amount_auth payment_type = results[0].category programme_type = results[0].p_item academic_session = academic_sessions_vocab.getTerm( results[0].p_session).title status = results[0].p_state self.output = ('FULL_NAME1=%s&MATRIC_NO1=%s&' + 'ACADEMIC_SESSION1=%s&PAYMENT_TYPE1=%s&' + 'PAYMENT_TYPE3=&FACULTY1=%s&' + 'DEPARTMENT1=%s&PROGRAMME_TYPE1=%s&' + 'RETURN_TYPE1=&FEE_AMOUNT1=%s&' + 'TRANSACTION_STATUS1=%s') % (full_name, matric_no, academic_session, payment_type, faculty, department, programme_type, amount, status) return def render(self): return self.output # Requerying eTranzact payments #TERMINAL_ID = '0330000046' #QUERY_URL = 'https://www.etranzact.net/Query/queryPayoutletTransaction.jsp' # Test environment QUERY_URL = 'http://demo.etranzact.com:8080/WebConnect/queryPayoutletTransaction.jsp' TERMINAL_ID = '5009892287' def query_etranzact(confirmation_number, payment): postdict = {} postdict['TERMINAL_ID'] = TERMINAL_ID #postdict['RESPONSE_URL'] = 'http://dummy' postdict['CONFIRMATION_NO'] = confirmation_number data = urllib.urlencode(postdict) payment.conf_number = confirmation_number try: f = urllib.urlopen(url=QUERY_URL, data=data) success = f.read() success = success.replace('\r\n','') if 'COL1' not in success: msg = _('Invalid or unsuccessful callback: ${a}', mapping = {'a': success}) log = 'invalid callback for payment %s: %s' % (payment.p_id, success) payment.p_state = 'failed' return False, msg, log success = success.replace('%20',' ').split('&') # We expect at least two parameters if len(success) < 2: msg = _('Invalid callback: ${a}', mapping = {'a': success}) log = 'invalid callback for payment %s: %s' % (payment.p_id, success) payment.p_state = 'failed' return False, msg, log try: success_dict = dict([tuple(i.split('=')) for i in success]) except ValueError: msg = _('Invalid callback: ${a}', mapping = {'a': success}) log = 'invalid callback for payment %s: %s' % (payment.p_id, success) payment.p_state = 'failed' return False, msg, log except IOError: msg = _('eTranzact IOError') log = 'eTranzact IOError' return False, msg, log payment.r_code = u'ET' payment.r_desc = u'%s' % success_dict.get('TRANS_DESCR') payment.r_amount_approved = float(success_dict.get('TRANS_AMOUNT',0.0)) payment.r_card_num = None payment.r_pay_reference = u'%s' % success_dict.get('RECEIPT_NO') if payment.r_amount_approved != payment.amount_auth: msg = _('Wrong amount') log = 'wrong callback for payment %s: %s' % (payment.p_id, success) payment.p_state = 'failed' return False, msg, log tcode = payment.p_id tcode = tcode[len(tcode)-8:len(tcode)] col1 = success_dict.get('COL1') col1 = col1[len(col1)-8:len(col1)] if tcode != col1: msg = _('Wrong transaction code') log = 'wrong callback for payment %s: %s' % (payment.p_id, success) payment.p_state = 'failed' return False, msg, log log = 'valid callback for payment %s: %s' % (payment.p_id, success) msg = _('Successful callback received') payment.p_state = 'paid' payment.payment_date = datetime.utcnow() return True, msg, log class EtranzactEnterPinActionButtonApplicant(APABApplicant): grok.context(ICustomApplicantOnlinePayment) grok.require('waeup.payApplicant') grok.order(3) icon = 'actionicon_call.png' text = _('Query eTranzact History') target = 'enterpin' class EtranzactEnterPinActionButtonStudent(APABStudent): grok.context(ICustomStudentOnlinePayment) grok.require('waeup.payStudent') grok.order(3) icon = 'actionicon_call.png' text = _('Query eTranzact History') target = 'enterpin' class EtranzactEnterPinPageStudent(KofaPage): """ """ grok.context(ICustomStudentOnlinePayment) grok.name('enterpin') grok.template('enterpin') grok.require('waeup.payStudent') buttonname = _('Submit to eTranzact') label = _('Requery eTranzact History') action = 'query_history' class EtranzactEnterPinPageApplicant(EtranzactEnterPinPageStudent): """ """ grok.require('waeup.payApplicant') grok.context(ICustomApplicantOnlinePayment) class EtranzactQueryHistoryPageStudent(UtilityView, grok.View): """ Query history of eTranzact payments """ grok.context(ICustomStudentOnlinePayment) grok.name('query_history') grok.require('waeup.payStudent') def update(self, confirmation_number=None): ob_class = self.__implemented__.__name__ if self.context.p_state == 'paid': self.flash(_('This ticket has already been paid.')) return student = self.context.getStudent() success, msg, log = query_etranzact(confirmation_number,self.context) student.loggerInfo(ob_class, log) if not success: self.flash(msg) return success, msg, log = self.context.doAfterStudentPayment() if log is not None: student.loggerInfo(ob_class, log) self.flash(msg) return def render(self): self.redirect(self.url(self.context, '@@index')) return class EtranzactQueryHistoryPageApplicant(UtilityView, grok.View): """ Query history of eTranzact payments """ grok.context(ICustomApplicantOnlinePayment) grok.name('query_history') grok.require('waeup.payApplicant') def update(self, confirmation_number=None): ob_class = self.__implemented__.__name__ if self.context.p_state == 'paid': self.flash(_('This ticket has already been paid.')) return applicant = self.context.__parent__ success, msg, log = query_etranzact(confirmation_number,self.context) applicant.loggerInfo(ob_class, log) if not success: self.flash(msg) return success, msg, log = self.context.doAfterApplicantPayment() if log is not None: applicant.loggerInfo(ob_class, log) self.flash(msg) return def render(self): self.redirect(self.url(self.context, '@@index')) return