[14781] | 1 | ## $Id: webservices.py 15842 2019-11-25 11:02:44Z 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 | ## |
---|
| 18 | |
---|
| 19 | import grok |
---|
| 20 | import json |
---|
| 21 | from zope.component import getUtility |
---|
| 22 | from zope.catalog.interfaces import ICatalog |
---|
| 23 | from waeup.kofa.interfaces import IUniversity |
---|
| 24 | from kofacustom.nigeria.remita.helpers import query_remita, write_payments_log |
---|
| 25 | |
---|
| 26 | class PaymentNotificationListenerWebservice(grok.View): |
---|
| 27 | """A webservice to receive payment notifications from |
---|
| 28 | accepted IP addresses without authentication which trigger |
---|
| 29 | a query of a Remita transaction status. |
---|
| 30 | """ |
---|
| 31 | grok.context(IUniversity) |
---|
| 32 | grok.name('paymentnotificationlistener') |
---|
| 33 | grok.require('waeup.Public') |
---|
| 34 | |
---|
[14790] | 35 | ACCEPTED_IP = ('127.0.0.1',) |
---|
[14781] | 36 | |
---|
| 37 | # Here we use Remita test portal data |
---|
| 38 | merchantId = '2547916' |
---|
| 39 | host = 'www.remitademo.net' |
---|
[15351] | 40 | https = True |
---|
[14781] | 41 | api_key = '1946' |
---|
| 42 | |
---|
| 43 | def update(self, P_ID=None): |
---|
| 44 | |
---|
| 45 | # Remita sends a JSON POST request with an array with |
---|
| 46 | # multiple JSON objects: |
---|
| 47 | # [ |
---|
| 48 | # { |
---|
| 49 | # "rrr": "A39359490", |
---|
| 50 | # "channnel": "BRANCH", |
---|
| 51 | # "amount": "6500.00", |
---|
| 52 | # "transactiondate": "19/01/2015", |
---|
| 53 | # "debitdate": "19/01/2015", |
---|
| 54 | # "bank": "033", |
---|
| 55 | # "branch": "033152763", |
---|
| 56 | # "serviceTypeId": "4430731", |
---|
| 57 | # "dateSent": "20/01/2015", |
---|
| 58 | # "dateRequested": "19/01/2015", |
---|
| 59 | # "orderRef": "4086852511", |
---|
| 60 | # "payerName": "mujib ishola", |
---|
| 61 | # "payerEmail": "ishola@specs.com", |
---|
| 62 | # "payerPhoneNumber": "08141376868", |
---|
| 63 | # "uniqueIdentifier": 10001 |
---|
| 64 | # }, |
---|
| 65 | # {...} |
---|
| 66 | # ] |
---|
| 67 | |
---|
| 68 | real_ip = self.request.get('HTTP_X_FORWARDED_FOR', None) |
---|
| 69 | if real_ip: |
---|
| 70 | self.context.logger.info( |
---|
[14786] | 71 | 'PaymentNotificationListenerWebservice called from %s' % real_ip) |
---|
[14781] | 72 | if real_ip and self.ACCEPTED_IP: |
---|
[14785] | 73 | if real_ip not in self.ACCEPTED_IP: |
---|
[14781] | 74 | self.output = '-1' |
---|
| 75 | return |
---|
[14801] | 76 | requ = self.request.bodyStream.read() |
---|
[14781] | 77 | self.context.logger.info( |
---|
[14801] | 78 | 'PaymentNotificationListenerWebservice request: %s' % requ) |
---|
[14781] | 79 | try: |
---|
[14801] | 80 | parsed_json = json.loads(requ) |
---|
[14781] | 81 | except ValueError: |
---|
| 82 | self.output = '-2' |
---|
| 83 | return |
---|
| 84 | successful = 0 |
---|
| 85 | failed = 0 |
---|
| 86 | for payment in parsed_json: |
---|
| 87 | orderRef = payment.get('orderRef') |
---|
| 88 | rrr = payment.get('rrr') |
---|
| 89 | if not orderRef or not rrr: |
---|
| 90 | failed += 1 |
---|
| 91 | continue |
---|
| 92 | cat = getUtility(ICatalog, name='payments_catalog') |
---|
| 93 | results = list(cat.searchResults(p_id=(orderRef, orderRef))) |
---|
| 94 | if len(results) != 1: |
---|
| 95 | failed += 1 |
---|
| 96 | continue |
---|
| 97 | ticket = results[0] |
---|
[15842] | 98 | if ticket.p_state in ('waived', 'scholarship'): |
---|
[14788] | 99 | failed += 1 |
---|
| 100 | continue |
---|
| 101 | waspaid = (ticket.p_state == 'paid') |
---|
[14781] | 102 | success, msg, log = query_remita( |
---|
| 103 | ticket, self.merchantId, self.api_key, |
---|
| 104 | rrr, self.host, self.https, False) |
---|
[14783] | 105 | if not success: |
---|
| 106 | failed += 1 |
---|
| 107 | continue |
---|
[14781] | 108 | if hasattr(ticket, 'doAfterStudentPayment'): |
---|
| 109 | ticket.student.writeLogMessage(self, log) |
---|
| 110 | successful += 1 |
---|
[14788] | 111 | if not waspaid: |
---|
| 112 | write_payments_log(ticket.student.student_id, ticket) |
---|
| 113 | flashtype, msg, log = ticket.doAfterStudentPayment() |
---|
| 114 | if log is not None: |
---|
| 115 | ticket.student.writeLogMessage(self, log) |
---|
[14781] | 116 | else: |
---|
| 117 | applicant = ticket.__parent__ |
---|
| 118 | applicant.writeLogMessage(self, log) |
---|
| 119 | successful += 1 |
---|
[14788] | 120 | if not waspaid: |
---|
| 121 | write_payments_log(applicant.applicant_id, ticket) |
---|
| 122 | flashtype, msg, log = ticket.doAfterApplicantPayment() |
---|
| 123 | if log is not None: |
---|
| 124 | applicant.writeLogMessage(self, log) |
---|
[14781] | 125 | self.output = '%s (%s)' % (successful, failed + successful) |
---|
| 126 | return |
---|
| 127 | |
---|
| 128 | def render(self): |
---|
| 129 | return self.output |
---|