source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/remita/applicantsbrowser.py @ 15554

Last change on this file since 15554 was 15529, checked in by Henrik Bettermann, 5 years ago

Redirect to edit page.

File size: 10.3 KB
RevLine 
[14766]1## $Id: browser.py 14759 2017-08-03 09:09:54Z 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.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant
28from kofacustom.nigeria.remita.helpers import (
29    get_JSON_POST_response, query_remita, write_payments_log)
30from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment
31from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment
32from kofacustom.nigeria.interfaces import MessageFactory as _
33from kofacustom.nigeria.remita.studentsbrowser import module_activated
34
[14790]35from kofacustom.nigeria.remita.tests import (
36    MERCHANTID, HOST, HTTPS, API_KEY, SERVICETYPEID)
37
[14766]38grok.templatedir('browser_templates')
39
40# Buttons
41
42class RemitaActionButtonApplicant(ManageActionButton):
43    grok.order(1)
44    grok.context(INigeriaOnlinePayment)
45    grok.view(OPDPApplicant)
46    grok.require('waeup.payApplicant')
47    icon = 'actionicon_pay.png'
48    text = _('Pay via Remita')
49    target = 'goto_remita'
50
51    @property
52    def target_url(self):
53        if not module_activated(self.context.__parent__.__parent__.year):
54            return ''
55        if self.context.p_state != 'unpaid':
56            return ''
57        return self.view.url(self.view.context, self.target)
58
59class RemitaRequestPaymentStatusActionButtonApplicant(ManageActionButton):
60    grok.order(2)
61    grok.context(INigeriaOnlinePayment)
62    grok.view(OPDPApplicant)
63    grok.require('waeup.payApplicant')
64    icon = 'actionicon_call.png'
65    text = _('Requery Remita Payment Status')
66    target = 'request_payment_status'
67
68    @property
69    def target_url(self):
70        if not module_activated(self.context.__parent__.__parent__.year):
71            return ''
72        if self.context.p_state in ('paid', 'waived'):
73            return ''
74        return self.view.url(self.view.context, self.target)
75
76class RemitaVerifyPaymentStatusActionButtonApplicant(ManageActionButton):
77    grok.order(3)
78    grok.context(INigeriaOnlinePayment)
79    grok.view(OPDPApplicant)
80    grok.require('waeup.manageApplication')
81    icon = 'actionicon_call.png'
82    text = _('Verify Remita Payment Status')
83    target = 'verify_payment_status'
84
85    @property
86    def target_url(self):
87        if not module_activated(self.context.__parent__.__parent__.year):
88            return ''
89        if self.context.p_state != 'paid' \
90            or self.context.r_company != u'remita':
91            return ''
92        return self.view.url(self.view.context, self.target)
93
94# Webservice request views
95
96class RemitaRequestPaymentStatusPageApplicant(UtilityView, grok.View):
97    """ Request webservice view for the Remita gateway.
98    """
99    grok.context(INigeriaApplicantOnlinePayment)
100    grok.name('request_payment_status')
101    grok.require('waeup.payApplicant')
102
[14790]103    merchantId = MERCHANTID
104    host = HOST
105    https = HTTPS
106    api_key = API_KEY
[14766]107
108    def update(self):
109        if not module_activated(self.context.__parent__.__parent__.year):
110            return
111        if self.context.p_state in ('paid', 'waived'):
112            self.flash(_('This ticket has already been paid.'), type='danger')
113            return
114        applicant = self.context.__parent__
115        RRR = self.context.r_pay_reference
116        if not RRR:
117            self.flash(_('Remita Retrieval Reference not found.'), type='danger')
118            return
119        # Remita sends a POST request which may contain more information
120        # if a payment was not successful.
121        resp = self.request.form
122        if resp and resp.get('statuscode') not in (None, '025', '00', '01'):
123            self.flash('Transaction status message from Remita: %s'
124                % resp.get('status'), type='warning')
125        success, msg, log = query_remita(
126            self.context,
127            self.merchantId,
128            self.api_key,
129            RRR,
130            self.host,
131            self.https,
132            False)
133        applicant.writeLogMessage(self, log)
134        if not success:
135            self.flash(msg, type='danger')
136            return
137        write_payments_log(applicant.applicant_id, self.context)
138        flashtype, msg, log = self.context.doAfterApplicantPayment()
139        if log is not None:
140            applicant.writeLogMessage(self, log)
141        self.flash(msg, type=flashtype)
142        return
143
144    def render(self):
[15529]145        self.redirect(self.url(self.context.__parent__, 'edit'))
[14766]146        return
147
148class RemitaVerifyPaymentStatusPageApplicant(UtilityView, grok.View):
149    """ Request webservice view for the Remita gateway.
150    """
151    grok.context(INigeriaApplicantOnlinePayment)
152    grok.name('verify_payment_status')
153    grok.require('waeup.manageApplication')
154
[14790]155    merchantId = MERCHANTID
156    host = HOST
157    https = HTTPS
158    api_key = API_KEY
[14766]159
160    def update(self):
161        if not module_activated(self.context.__parent__.__parent__.year):
162            return
163        if self.context.p_state  != 'paid' \
164            or self.context.r_company != u'remita':
165            self.flash(_('This ticket has not been paid.'), type='danger')
166            return
167        applicant = self.context.__parent__
168        RRR = self.context.r_pay_reference
169        if not RRR:
170            self.flash(_('Remita Retrieval Reference not found.'), type='danger')
171            return
172        # Remita sends a POST request which may contain more information
173        # if a payment was not successful.
174        resp = self.request.form
175        if resp and resp.get('statuscode') not in (None, '025', '00', '01'):
176            self.flash('Transaction status message from Remita: %s'
177                % resp.get('status'), type='warning')
178        success, msg, log = query_remita(
179            self.context,
180            self.merchantId,
181            self.api_key,
182            RRR,
183            self.host,
184            self.https,
185            True)
186        applicant.writeLogMessage(self, log)
187        if not success:
188            self.flash(msg, type='danger')
189            return
190        self.flash(msg)
191        return
192
193    def render(self):
[15456]194        self.redirect(self.url(self.context))
[14766]195        return
196
197
198# Forwarding pages
199
200class RemitaPageApplicant(KofaPage):
201    """ View which sends a POST request to the Remita payment gateway.
202    """
203    grok.context(INigeriaApplicantOnlinePayment)
204    grok.name('goto_remita')
205    grok.template('goto_remita')
206    grok.require('waeup.payApplicant')
207    label = _('Pay via Remita')
208    submit_button = _('Pay now')
209
[14790]210    merchantId = MERCHANTID
211    host = HOST
212    https = HTTPS
213    api_key = API_KEY
214    serviceTypeId = SERVICETYPEID
215
[14805]216    #orderId = '3456346346'
[14766]217    init_url = '/remita/ecomm/split/init.reg'
218    amount='1000'
219    lineitems = (
220                  {"lineItemsId":"itemid1","beneficiaryName":"Klaus Mueller",
221                  "beneficiaryAccount":"6020067886","bankCode":"011",
222                  "beneficiaryAmount":"500","deductFeeFrom":"1"},
223                  {"lineItemsId":"itemid2","beneficiaryName":"Werner Rumm",
224                  "beneficiaryAccount":"0360883515","bankCode":"050",
225                  "beneficiaryAmount":"500","deductFeeFrom":"0"}
226                )
227
[14796]228    @property
229    def action(self):
[14798]230        if self.https:
231            return 'https://' + self.host + '/remita/ecomm/finalize.reg'
232        return 'http://' + self.host + '/remita/ecomm/finalize.reg'
[14766]233
234    def init_update(self):
235        if self.context.p_state == 'paid':
236            return _("Payment ticket can't be re-sent to Remita.")
237        now = datetime.utcnow()
238        if self.context.creation_date.tzinfo is not None:
239            # That's bad. Please store timezone-naive datetimes only!
240            now = self.context.creation_date.tzinfo.localize(now)
241        time_delta = now - self.context.creation_date
242        if time_delta.days > 7:
243            return _("This payment ticket is too old. Please create a new ticket.")
244        self.responseurl = self.url(self.context, 'request_payment_status')
245        resp = get_JSON_POST_response(
246            merchantId=self.merchantId,
247            serviceTypeId=self.serviceTypeId,
248            api_key=self.api_key,
249            orderId=self.orderId,
250            amount=self.amount,
251            responseurl=self.responseurl,
252            host=self.host,
253            url=self.init_url,
254            https=self.https,
255            fullname=self.context.__parent__.display_fullname,
256            email=self.context.__parent__.email,
257            lineitems=self.lineitems)
258        if resp.get('error'):
259            return resp.get('error')
260        if resp.get('statuscode') not in ('021', '025', '055'):
261            return 'RRR generation message from Remita: ' + resp.get('status')
262        # Already now it becomes a Remita payment
263        self.context.r_company = u'remita'
264        self.rrr = self.context.r_pay_reference = resp['RRR'].rstrip()
265        hashargs =      self.merchantId + self.rrr + self.api_key
266        self.hashvalue = hashlib.sha512(hashargs).hexdigest()
267        self.customer = self.context.__parent__
[14793]268        self.customer.writeLogMessage(self,
269            'RRR retrieved: %s, ServiceTypeId: %s'
270            % (self.rrr, self.serviceTypeId))
271
[14766]272        return
273
274    def update(self):
275        if not module_activated(self.context.__parent__.__parent__.year):
276            return
[14805]277        self.orderId = self.context.p_id
[14766]278        error = self.init_update()
279        if error:
280            self.flash(error, type='danger')
281            self.redirect(self.url(self.context, '@@index'))
282            return
283        return
Note: See TracBrowser for help on using the repository browser.