source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/interswitch/paydirectbrowser.py @ 17238

Last change on this file since 17238 was 16587, checked in by Henrik Bettermann, 3 years ago

Set constant item_code.

  • Property svn:keywords set to Id
File size: 11.3 KB
RevLine 
[16484]1## $Id: paydirectbrowser.py 16587 2021-08-31 06:28:35Z henrik $
2##
3## Copyright (C) 2021 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
19from datetime import datetime, timedelta
20from zope.i18n import translate
21from zope.component import getUtility
22from zope.security import checkPermission
[16487]23from xml.dom.minidom import parseString
[16484]24from waeup.kofa.interfaces import IKofaUtils
25from waeup.kofa.utils.helpers import to_timezone
26from waeup.kofa.browser.layout import UtilityView, KofaPage, KofaFormPage, action
27from waeup.kofa.browser.viewlets import ManageActionButton
[16528]28from waeup.kofa.payments.interfaces import IPayer
[16484]29from waeup.kofa.students.interfaces import IStudentsUtils
30from waeup.kofa.students.browser import OnlinePaymentDisplayFormPage as OPDPStudent
31from waeup.kofa.students.browser import StudentBasePDFFormPage
32from waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant
[16487]33from waeup.kofa.applicants.browser import ApplicantBaseDisplayFormPage
[16484]34from kofacustom.nigeria.interswitch.helpers import (
[16487]35    query_interswitch, write_payments_log,
36    fetch_booking_details, create_paydirect_booking)
[16484]37from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
38from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment
39from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment
[16487]40from kofacustom.nigeria.interswitch.tests import (
41    PAYDIRECT_URL, PAYDIRECT_HOST, MERCHANT_ID)
[16484]42from kofacustom.nigeria.interfaces import MessageFactory as _
43
44GATEWAY_AMT = 300.0
45
46grok.templatedir('browser_templates')
47
48def paydirect_module_activated(session, payment):
49    if payment.r_company and payment.r_company != 'interswitch':
50        return False
51    try:
52        return getattr(grok.getSite()['configuration'][str(session)],
[16496]53            'interswitch_paydirect_enabled', False)
[16484]54    except KeyError:
55        session = datetime.now().year
56        try:
57            return getattr(grok.getSite()['configuration'][str(session)],
[16496]58                'interswitch_paydirect_enabled', False)
[16484]59        except KeyError:
60            return False
61
62class PAYDirectActionButtonStudent(ManageActionButton):
63    grok.order(2)
64    grok.context(INigeriaOnlinePayment)
65    grok.view(OPDPStudent)
66    grok.require('waeup.payStudent')
67    icon = 'actionicon_pay.png'
68    text = _('Pay via Interswitch PAYDirect')
69    target = 'paydirect'
70
71    @property
72    def target_url(self):
73        if not paydirect_module_activated(
74            self.context.student.current_session, self.context):
75            return ''
76        if self.context.p_state == 'paid':
77            return ''
78        return self.view.url(self.view.context, self.target)
79
80class PAYDirectActionButtonApplicant(PAYDirectActionButtonStudent):
81    grok.view(OPDPApplicant)
82    grok.require('waeup.payApplicant')
83
84    @property
85    def target_url(self):
86        if not paydirect_module_activated(
87            self.context.__parent__.__parent__.year, self.context):
88            return ''
89        if self.context.p_state != 'unpaid':
90            return ''
91        return self.view.url(self.view.context, self.target)
92
93class PAYDirectPageStudent(KofaFormPage):
94    """Inform student how to proceed
95    """
96    grok.context(INigeriaStudentOnlinePayment)
97    grok.template('paydirect')
98    grok.name('paydirect')
99    grok.require('waeup.payStudent')
100    label = _('Requery Interswitch PAYDirect History')
101
102    gateway_amt = GATEWAY_AMT
103    merchant_id = MERCHANT_ID
104    gateway_url = PAYDIRECT_URL
105    gateway_host = PAYDIRECT_HOST
106    https = True
107
[16587]108    @property
109    def item_code(self):
110        return '01' # for testing
111
[16484]112    def init_update(self):
113        if self.context.p_state == 'paid':
114            return _("Payment ticket can't be used again.")
115        if self.context.r_company and self.context.r_company != 'interswitch':
116            return _("Payment ticket has been used for another payment gateway.")
117        self.ref_number = self.merchant_id + self.context.p_id[1:]
[16487]118        # Create a PAYDirect Booking
[16555]119        result_xml = create_paydirect_booking(
[16587]120            self.merchant_id, self.context, self.item_code, self.gateway_host,
[16555]121            self.gateway_url, True)
122        if result_xml.startswith('Connection error'):
123            IPayer(self.context).payer.writeLogMessage(self, result_xml)
124            return result_xml
125        doc=parseString(result_xml)
126        if not doc.getElementsByTagName('ResponseCode'):
127            IPayer(self.context).payer.writeLogMessage(self, 'invalid callback')
128            return _('Invalid callback from Interswitch')
129        rc = doc.getElementsByTagName('ResponseCode')[0].firstChild.data
130        IPayer(self.context).payer.writeLogMessage(self, 'response code: %s' % rc)
131        if rc not in ('100', '108'):
132            return 'Error response code from Interswitch: %s' % rc
[16484]133        return
134
135    def update(self):
136        if not paydirect_module_activated(
137            self.context.student.current_session, self.context):
138            self.flash(_('Forbidden'), type='danger')
139            self.redirect(self.url(self.context, '@@index'))
140            return
141        # Already now it becomes an Interswitch payment. We set the net amount
142        # and add the gateway amount.
143        if not self.context.r_company:
144            self.context.net_amt = self.context.amount_auth
145            self.context.amount_auth += self.gateway_amt
146            self.context.gateway_amt = self.gateway_amt
147            self.context.r_company = u'interswitch'
[16555]148        error = self.init_update()
149        if error:
150            self.flash(error, type='danger')
151            self.redirect(self.url(self.context, '@@index'))
152            return
[16484]153        return
154
155    @action('Requery now', style='primary')
156    def fetch(self):
157        success, msg, log = fetch_booking_details(
158            self.context, self.merchant_id, self.gateway_host,
159            self.gateway_url, self.https)
[16528]160        IPayer(self.context).payer.writeLogMessage(self, log)
[16484]161        if not success:
162            self.flash(msg, type='warning')
163            self.redirect(self.url(self.context, '@@index'))
164            return
[16528]165        write_payments_log(IPayer(self.context).id, self.context)
166        flashtype, msg, log = IPayer(self.context).doAfterPayment()
[16484]167        if log is not None:
[16528]168            IPayer(self.context).payer.writeLogMessage(self, log)
[16484]169        self.flash(msg, type=flashtype)
170        return
171
172class PAYDirectPageApplicant(PAYDirectPageStudent):
173    """ Inform applicant how to proceed.
174    """
175    grok.context(INigeriaApplicantOnlinePayment)
176    grok.require('waeup.payApplicant')
177
178    def update(self):
179        if not paydirect_module_activated(
180            self.context.__parent__.__parent__.year, self.context):
181            self.flash(_('Forbidden'), type='danger')
182            self.redirect(self.url(self.context, '@@index'))
183            return
[16555]184        # Already now it becomes an Interswitch payment. We set the net amount
185        # and add the gateway amount.
186        if not self.context.r_company:
187            self.context.net_amt = self.context.amount_auth
188            self.context.amount_auth += self.gateway_amt
189            self.context.gateway_amt = self.gateway_amt
190            self.context.r_company = u'interswitch'
[16484]191        error = self.init_update()
192        if error:
193            self.flash(error, type='danger')
194            self.redirect(self.url(self.context, '@@index'))
195        if self.context.__parent__.__parent__.expired \
196            and self.context.__parent__.__parent__.strict_deadline:
197            return _("Payment ticket can't be used. "
198                     "Application period has expired.")
199        return
200
[16487]201class StudentPaymentRefNumberSlipActionButton(ManageActionButton):
202    grok.order(1)
203    grok.context(INigeriaStudentOnlinePayment)
[16484]204    grok.view(PAYDirectPageStudent)
205    grok.require('waeup.viewStudent')
206    icon = 'actionicon_pdf.png'
207    text = _('Download reference number slip')
208    target = 'refnumberslip.pdf'
209
210    @property
211    def target_url(self):
212        if self.context.p_state == 'paid':
213            return ''
214        return self.view.url(self.view.context, self.target)
215
[16487]216class ApplicantPaymentRefNumberSlipActionButton(StudentPaymentRefNumberSlipActionButton):
217    grok.context(INigeriaApplicantOnlinePayment)
218    grok.view(PAYDirectPageApplicant)
219    grok.require('waeup.viewApplication')
220
221class StudentRefNumberSlip(UtilityView, grok.View):
[16484]222    """Deliver a PDF slip of the context.
223    """
[16487]224    grok.context(INigeriaStudentOnlinePayment)
[16484]225    grok.name('refnumberslip.pdf')
226    grok.require('waeup.viewStudent')
227    form_fields = grok.AutoFields(INigeriaOnlinePayment).select(
228        'amount_auth', 'p_category')
229    prefix = 'form'
230    omit_fields = (
231        'password', 'suspended', 'phone', 'date_of_birth',
232        'adm_code', 'sex', 'suspended_comment', 'current_level',
233        'flash_notice', 'parents_email', 'current_mode',
234        'entry_session', 'reg_number')
235    merchant_id = MERCHANT_ID
236
237    @property
238    def refnumber(self):
239        return self.merchant_id + self.context.p_id[1:]
240
241    @property
242    def label(self):
243        portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
244        return translate(_('Interswitch PAYDirect Payment'),
245            'waeup.kofa', target_language=portal_language) \
246            + ' %s' % self.refnumber
247
248    @property
249    def note(self):
250        return """<br /><br />
251Go to your bank and make your PAYDirect payment with the reference number <strong>%s</strong>.
252""" % self.refnumber
253    def render(self):
254        if self.context.p_state == 'paid':
255            self.flash('Payment has already been made.')
256            self.redirect(self.url(self.context))
257            return
258        studentview = StudentBasePDFFormPage(self.context.student,
259            self.request, self.omit_fields)
260        students_utils = getUtility(IStudentsUtils)
261        return students_utils.renderPDF(self, 'refnumberslip.pdf',
262            self.context.student, studentview, note=self.note,
263            omit_fields=self.omit_fields)
[16487]264
265class ApplicantRefNumberSlip(StudentRefNumberSlip):
266    """Deliver a PDF slip of the context.
267    """
268    grok.context(INigeriaApplicantOnlinePayment)
269    grok.require('waeup.viewApplication')
270
271    @property
272    def note(self):
273        return """<br /><br />
274Go to your bank and make your PAYDirect payment with the reference number <strong>%s</strong>.
275""" % self.refnumber
276    def render(self):
277        if self.context.p_state == 'paid':
278            self.flash('Payment has already been made.')
279            self.redirect(self.url(self.context))
280            return
281        applicantview = ApplicantBaseDisplayFormPage(self.context.__parent__,
282            self.request)
283        students_utils = getUtility(IStudentsUtils)
284        return students_utils.renderPDF(self, 'refnumberslip.pdf',
285            self.context.__parent__, applicantview, note=self.note,
286            omit_fields=self.omit_fields)
Note: See TracBrowser for help on using the repository browser.