## $Id: webservices.py 14788 2017-08-09 14:03:33Z henrik $ ## ## Copyright (C) 2017 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 ## import grok import json from zope.component import getUtility from zope.catalog.interfaces import ICatalog from waeup.kofa.interfaces import IUniversity from kofacustom.nigeria.remita.helpers import query_remita, write_payments_log class PaymentNotificationListenerWebservice(grok.View): """A webservice to receive payment notifications from accepted IP addresses without authentication which trigger a query of a Remita transaction status. """ grok.context(IUniversity) grok.name('paymentnotificationlistener') grok.require('waeup.Public') ACCEPTED_IP = None # Here we use Remita test portal data merchantId = '2547916' host = 'www.remitademo.net' https = False api_key = '1946' def update(self, P_ID=None): # Remita sends a JSON POST request with an array with # multiple JSON objects: # [ # { # "rrr": "A39359490", # "channnel": "BRANCH", # "amount": "6500.00", # "transactiondate": "19/01/2015", # "debitdate": "19/01/2015", # "bank": "033", # "branch": "033152763", # "serviceTypeId": "4430731", # "dateSent": "20/01/2015", # "dateRequested": "19/01/2015", # "orderRef": "4086852511", # "payerName": "mujib ishola", # "payerEmail": "ishola@specs.com", # "payerPhoneNumber": "08141376868", # "uniqueIdentifier": 10001 # }, # {...} # ] real_ip = self.request.get('HTTP_X_FORWARDED_FOR', None) if real_ip: self.context.logger.info( 'PaymentNotificationListenerWebservice called from %s' % real_ip) if real_ip and self.ACCEPTED_IP: if real_ip not in self.ACCEPTED_IP: self.output = '-1' return resp = self.request.bodyStream.read() self.context.logger.info( 'PaymentNotificationListenerWebservice response: %s' % resp) try: parsed_json = json.loads(resp) except ValueError: self.output = '-2' return successful = 0 failed = 0 for payment in parsed_json: orderRef = payment.get('orderRef') rrr = payment.get('rrr') if not orderRef or not rrr: failed += 1 continue cat = getUtility(ICatalog, name='payments_catalog') results = list(cat.searchResults(p_id=(orderRef, orderRef))) if len(results) != 1: failed += 1 continue ticket = results[0] if ticket.p_state == 'waived': failed += 1 continue waspaid = (ticket.p_state == 'paid') success, msg, log = query_remita( ticket, self.merchantId, self.api_key, rrr, self.host, self.https, False) if not success: failed += 1 continue if hasattr(ticket, 'doAfterStudentPayment'): ticket.student.writeLogMessage(self, log) successful += 1 if not waspaid: write_payments_log(ticket.student.student_id, ticket) flashtype, msg, log = ticket.doAfterStudentPayment() if log is not None: ticket.student.writeLogMessage(self, log) else: applicant = ticket.__parent__ applicant.writeLogMessage(self, log) successful += 1 if not waspaid: write_payments_log(applicant.applicant_id, ticket) flashtype, msg, log = ticket.doAfterApplicantPayment() if log is not None: applicant.writeLogMessage(self, log) self.output = '%s (%s)' % (successful, failed + successful) return def render(self): return self.output