## $Id: webservices.py 15842 2019-11-25 11:02:44Z 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 = ('127.0.0.1',)

    # Here we use Remita test portal data
    merchantId = '2547916'
    host = 'www.remitademo.net'
    https = True
    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
        requ = self.request.bodyStream.read()
        self.context.logger.info(
            'PaymentNotificationListenerWebservice request: %s' % requ)
        try:
            parsed_json = json.loads(requ)
        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 in ('waived', 'scholarship'):
                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