source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/remita/browser.py @ 14744

Last change on this file since 14744 was 14744, checked in by Henrik Bettermann, 7 years ago

It's not always a missing email address which causes an error message.

  • Property svn:keywords set to Id
File size: 7.7 KB
Line 
1## $Id: browser.py 14744 2017-08-02 09:01:14Z henrik $
2##
3## Copyright (C) 2017 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
19import hashlib
20from datetime import datetime, timedelta
21from zope.component import getUtility
22from zope.security import checkPermission
23from waeup.kofa.interfaces import IKofaUtils
24from waeup.kofa.utils.helpers import to_timezone
25from waeup.kofa.browser.layout import UtilityView, KofaPage
26from waeup.kofa.browser.viewlets import ManageActionButton
27from waeup.kofa.students.interfaces import IStudentsUtils
28from waeup.kofa.students.browser import OnlinePaymentDisplayFormPage as OPDPStudent
29from waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant
30from kofacustom.nigeria.remita.helpers import (
31    get_JSON_POST_response, query_remita, write_payments_log)
32from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
33from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment
34from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment
35from kofacustom.nigeria.interfaces import MessageFactory as _
36
37def module_activated(session):
38    try:
39        return getattr(grok.getSite()['configuration'][str(session)],
40            'remita_enabled', None)
41    except KeyError:
42        return False
43
44# Buttons
45
46class RemitaActionButtonStudent(ManageActionButton):
47    grok.order(1)
48    grok.context(INigeriaOnlinePayment)
49    grok.view(OPDPStudent)
50    grok.require('waeup.payStudent')
51    icon = 'actionicon_pay.png'
52    text = _('Pay via Remita')
53    target = 'goto_remita'
54
55    @property
56    def target_url(self):
57        if not module_activated(self.context.student.current_session):
58            return ''
59        if self.context.p_state != 'unpaid':
60            return ''
61        return self.view.url(self.view.context, self.target)
62
63# Webservice request views
64
65class RemitaPaymentRequestWebservicePageStudent(UtilityView, grok.View):
66    """ Request webservice view for the Remita gateway.
67    """
68    grok.context(INigeriaStudentOnlinePayment)
69    grok.name('request_payment_status')
70    grok.require('waeup.payStudent')
71
72    # Here we use Remita test portal data
73    merchantId = '2547916'
74    host = 'www.remitademo.net'
75    https = False
76    api_key = '1946'
77
78    def update(self):
79        if not module_activated(self.context.student.current_session):
80            return
81        if self.context.p_state in ('paid', 'waived'):
82            self.flash(_('This ticket has already been paid.'), type='danger')
83            return
84        student = self.context.student
85        RRR = self.context.r_pay_reference
86        if not RRR:
87            self.flash(_('Remita Retrieval Reference not found.'), type='danger')
88            return
89
90        # Remita sends a POST request which may contain more information
91        # if a payment was not successful.
92        resp = self.request.form
93        if resp and resp.get('statuscode') not in ('025', '00', '01'):
94            self.flash('Message from Remita: %s.'
95                % resp.get('status'), type='danger')
96
97        success, msg, log = query_remita(
98            self.context,
99            self.merchantId,
100            self.api_key,
101            RRR,
102            self.host,
103            self.https,
104            False)
105
106        student.writeLogMessage(self, log)
107        if not success:
108            self.flash(msg, type='danger')
109            return
110        write_payments_log(student.student_id, self.context)
111        flashtype, msg, log = self.context.doAfterStudentPayment()
112        if log is not None:
113            student.writeLogMessage(self, log)
114        self.flash(msg, type=flashtype)
115        return
116
117    def render(self):
118        self.redirect(self.url(self.context, '@@index'))
119        return
120
121# Forwarding pages
122
123class RemitaPageStudent(KofaPage):
124    """ View which sends a POST request to the Remita payment gateway.
125    """
126    grok.context(INigeriaOnlinePayment)
127    grok.name('goto_remita')
128    grok.template('student_goto_remita')
129    grok.require('waeup.payStudent')
130    label = _('Pay via Remita')
131    submit_button = _('Pay now')
132    https = False
133
134    # Here we use Remita test portal data
135    merchantId = '2547916'
136    serviceTypeId = '4430731'
137    api_key = '1946'
138    orderId = '3456346346'
139    host = 'www.remitademo.net'
140    init_url = '/remita/ecomm/split/init.reg'
141    amount='1000'
142    lineitems = (
143                  {"lineItemsId":"itemid1","beneficiaryName":"Klaus Mueller",
144                  "beneficiaryAccount":"6020067886","bankCode":"011",
145                  "beneficiaryAmount":"500","deductFeeFrom":"1"},
146                  {"lineItemsId":"itemid2","beneficiaryName":"Werner Rumm",
147                  "beneficiaryAccount":"0360883515","bankCode":"050",
148                  "beneficiaryAmount":"500","deductFeeFrom":"0"}
149                )
150
151    action = 'http://www.remitademo.net/remita/ecomm/finalize.reg'
152
153    def init_update(self):
154        if self.context.p_state == 'paid':
155            return _("Payment ticket can't be re-sent to Remita.")
156        now = datetime.utcnow()
157        if self.context.creation_date.tzinfo is not None:
158            # That's bad. Please store timezone-naive datetimes only!
159            now = self.context.creation_date.tzinfo.localize(now)
160        time_delta = now - self.context.creation_date
161        if time_delta.days > 7:
162            return _("This payment ticket is too old. Please create a new ticket.")
163        student = self.context.student
164        certificate = getattr(student['studycourse'],'certificate',None)
165        if certificate is None:
166            return _("Study course data are incomplete.")
167        kofa_utils = getUtility(IKofaUtils)
168        student_utils = getUtility(IStudentsUtils)
169        if student_utils.samePaymentMade(student, self.context.p_category,
170            self.context.p_item, self.context.p_session):
171            return _("This type of payment has already been made.")
172        self.responseurl = self.url(self.context, 'request_payment_status')
173        self.student = student
174        resp = get_JSON_POST_response(
175            merchantId=self.merchantId,
176            serviceTypeId=self.serviceTypeId,
177            api_key=self.api_key,
178            orderId=self.orderId,
179            amount=self.amount,
180            responseurl=self.responseurl,
181            host=self.host,
182            url=self.init_url,
183            https=self.https,
184            fullname=self.student.display_fullname,
185            email=self.student.email,
186            lineitems=self.lineitems)
187        if resp.get('error'):
188            return resp.get('error')
189        if resp.get('statuscode') not in ('021', '025', '055'):
190            return resp.get('status')
191        self.rrr = self.context.r_pay_reference = resp['RRR'].rstrip()
192        hashargs =      self.merchantId + self.rrr + self.api_key
193        self.hashvalue = hashlib.sha512(hashargs).hexdigest()
194        return
195
196    def update(self):
197        if not module_activated(self.context.student.current_session):
198            return
199        error = self.init_update()
200        if error:
201            self.flash(error, type='danger')
202            self.redirect(self.url(self.context, '@@index'))
203            return
204        return
Note: See TracBrowser for help on using the repository browser.