source: main/waeup.aaue/trunk/src/waeup/aaue/etranzact/browser.py @ 8731

Last change on this file since 8731 was 8731, checked in by Henrik Bettermann, 12 years ago

Change response string again and add missing webservice test.

  • Property svn:keywords set to Id
File size: 8.8 KB
Line 
1## $Id: browser.py 8731 2012-06-15 08:24:33Z 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##
18from datetime import datetime
19import httplib
20import urllib
21from xml.dom.minidom import parseString
22import grok
23from zope.component import getUtility
24from zope.catalog.interfaces import ICatalog
25from waeup.kofa.interfaces import IUniversity
26from waeup.kofa.payments.interfaces import IPaymentWebservice
27from waeup.kofa.browser.layout import KofaPage, UtilityView
28from waeup.kofa.students.viewlets import ApprovePaymentActionButton as APABStudent
29from waeup.kofa.applicants.viewlets import ApprovePaymentActionButton as APABApplicant
30from waeup.aaue.interfaces import academic_sessions_vocab
31from waeup.aaue.interfaces import MessageFactory as _
32from waeup.aaue.students.interfaces import ICustomStudentOnlinePayment
33from waeup.aaue.applicants.interfaces import ICustomApplicantOnlinePayment
34
35# Kofa's webservice
36
37class KofaFeeRequest(grok.View):
38    grok.context(IUniversity)
39    grok.name('feerequest')
40    grok.require('waeup.Public')
41
42    def update(self, PAYEE_ID=None):
43        cat = getUtility(ICatalog, name='payments_catalog')
44        results = list(cat.searchResults(p_id=(PAYEE_ID, PAYEE_ID)))
45        if len(results) != 1:
46            self.output = '-1'
47        else:
48            try:
49                owner = IPaymentWebservice(results[0])
50                full_name = owner.display_fullname
51                matric_no = owner.id
52                faculty = owner.faculty
53                department = owner.department
54            except (TypeError, AttributeError):
55                self.output = '-1'
56                return
57            amount = results[0].amount_auth
58            payment_type = results[0].category
59            programme_type = results[0].p_item
60            academic_session = academic_sessions_vocab.getTerm(
61                results[0].p_session).title
62            status = results[0].p_state
63            self.output = ('FULL_NAME=%s&MATRIC_NO=%s&' +
64                'ACADEMIC_SESSION=%s&PAYMENT_TYPE=%s&' +
65                'FACULTY=%s&' +
66                'DEPARTMENT=%s&PROGRAMME_TYPE=%s&' +
67                'RETURN_TYPE=%s&FEE_AMOUNT=%s&' +
68                'TRANSACTION_STATUS=%s') % (full_name, matric_no,
69                academic_session, payment_type, faculty, department,
70                programme_type, PAYEE_ID, amount, status)
71        return
72
73    def render(self):
74        return self.output
75
76
77# Requerying eTranzact payments
78
79#TERMINAL_ID = '0330000046'
80#QUERY_URL =   'https://www.etranzact.net/Query/queryPayoutletTransaction.jsp'
81
82# Test environment
83QUERY_URL =   'http://demo.etranzact.com:8080/WebConnect/queryPayoutletTransaction.jsp'
84TERMINAL_ID = '5009892287'
85
86def query_etranzact(confirmation_number, payment):
87   
88    postdict = {}
89    postdict['TERMINAL_ID'] = TERMINAL_ID
90    #postdict['RESPONSE_URL'] = 'http://dummy'
91    postdict['CONFIRMATION_NO'] = confirmation_number
92    data = urllib.urlencode(postdict)
93    payment.conf_number = confirmation_number
94    try:
95        f = urllib.urlopen(url=QUERY_URL, data=data)
96        success = f.read()
97        success = success.replace('\r\n','')
98        if 'COL1' not in success:
99            msg = _('Invalid or unsuccessful callback: ${a}',
100                mapping = {'a': success})
101            log = 'invalid callback for payment %s: %s' % (payment.p_id, success)
102            payment.p_state = 'failed'
103            return False, msg, log
104        success = success.replace('%20',' ').split('&')
105        # We expect at least two parameters
106        if len(success) < 2:
107            msg = _('Invalid callback: ${a}', mapping = {'a': success})
108            log = 'invalid callback for payment %s: %s' % (payment.p_id, success)
109            payment.p_state = 'failed'
110            return False, msg, log
111        try:
112            success_dict = dict([tuple(i.split('=')) for i in success])
113        except ValueError:
114            msg = _('Invalid callback: ${a}', mapping = {'a': success})
115            log = 'invalid callback for payment %s: %s' % (payment.p_id, success)
116            payment.p_state = 'failed'
117            return False, msg, log
118    except IOError:
119        msg = _('eTranzact IOError')
120        log = 'eTranzact IOError'
121        return False, msg, log
122    payment.r_code = u'ET'
123    payment.r_desc = u'%s' % success_dict.get('TRANS_DESCR')
124    payment.r_amount_approved = float(success_dict.get('TRANS_AMOUNT',0.0))
125    payment.r_card_num = None
126    payment.r_pay_reference = u'%s' % success_dict.get('RECEIPT_NO')
127    if payment.r_amount_approved != payment.amount_auth:
128        msg = _('Wrong amount')
129        log = 'wrong callback for payment %s: %s' % (payment.p_id, success)
130        payment.p_state = 'failed'
131        return False, msg, log
132    #tcode = payment.p_id
133    #tcode = tcode[len(tcode)-8:len(tcode)]
134    col1 = success_dict.get('COL1')
135    #col1 = col1[len(col1)-8:len(col1)]
136    #if tcode != col1:
137    if payment.p_id != col1:
138        #msg = _('Wrong transaction code')
139        msg = _('Wrong payment id')
140        log = 'wrong callback for payment %s: %s' % (payment.p_id, success)
141        payment.p_state = 'failed'
142        return False, msg, log
143    log = 'valid callback for payment %s: %s' % (payment.p_id, success)
144    msg = _('Successful callback received')
145    payment.p_state = 'paid'
146    payment.payment_date = datetime.utcnow()
147    return True, msg, log
148
149class EtranzactEnterPinActionButtonApplicant(APABApplicant):
150    grok.context(ICustomApplicantOnlinePayment)
151    grok.require('waeup.payApplicant')
152    grok.order(3)
153    icon = 'actionicon_call.png'
154    text = _('Query eTranzact History')
155    target = 'enterpin'
156
157class EtranzactEnterPinActionButtonStudent(APABStudent):
158    grok.context(ICustomStudentOnlinePayment)
159    grok.require('waeup.payStudent')
160    grok.order(3)
161    icon = 'actionicon_call.png'
162    text = _('Query eTranzact History')
163    target = 'enterpin'
164
165class EtranzactEnterPinPageStudent(KofaPage):
166    """
167    """
168    grok.context(ICustomStudentOnlinePayment)
169    grok.name('enterpin')
170    grok.template('enterpin')
171    grok.require('waeup.payStudent')
172
173    buttonname = _('Submit to eTranzact')
174    label = _('Requery eTranzact History')
175    action = 'query_history'
176
177class EtranzactEnterPinPageApplicant(EtranzactEnterPinPageStudent):
178    """
179    """
180    grok.require('waeup.payApplicant')
181    grok.context(ICustomApplicantOnlinePayment)
182
183class EtranzactQueryHistoryPageStudent(UtilityView, grok.View):
184    """ Query history of eTranzact payments
185    """
186    grok.context(ICustomStudentOnlinePayment)
187    grok.name('query_history')
188    grok.require('waeup.payStudent')
189
190    def update(self, confirmation_number=None):
191        ob_class = self.__implemented__.__name__
192        if self.context.p_state == 'paid':
193            self.flash(_('This ticket has already been paid.'))
194            return
195        student = self.context.getStudent()
196        success, msg, log = query_etranzact(confirmation_number,self.context)
197        student.loggerInfo(ob_class, log)
198        if not success:
199            self.flash(msg)
200            return
201        success, msg, log = self.context.doAfterStudentPayment()
202        if log is not None:
203            student.loggerInfo(ob_class, log)
204        self.flash(msg)
205        return
206
207    def render(self):
208        self.redirect(self.url(self.context, '@@index'))
209        return
210
211class EtranzactQueryHistoryPageApplicant(UtilityView, grok.View):
212    """ Query history of eTranzact payments
213    """
214    grok.context(ICustomApplicantOnlinePayment)
215    grok.name('query_history')
216    grok.require('waeup.payApplicant')
217
218    def update(self, confirmation_number=None):
219        ob_class = self.__implemented__.__name__
220        if self.context.p_state == 'paid':
221            self.flash(_('This ticket has already been paid.'))
222            return
223        applicant = self.context.__parent__
224        success, msg, log = query_etranzact(confirmation_number,self.context)
225        applicant.loggerInfo(ob_class, log)
226        if not success:
227            self.flash(msg)
228            return
229        success, msg, log = self.context.doAfterApplicantPayment()
230        if log is not None:
231            applicant.loggerInfo(ob_class, log)
232        self.flash(msg)
233        return
234
235    def render(self):
236        self.redirect(self.url(self.context, '@@index'))
237        return
Note: See TracBrowser for help on using the repository browser.