Index: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/remita/helpers.py
===================================================================
--- main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/remita/helpers.py	(revision 14736)
+++ main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/remita/helpers.py	(revision 14737)
@@ -18,4 +18,5 @@
 """General helper functions for the remita module in custom packages.
 """
+import grok
 from datetime import datetime
 import httplib
@@ -51,9 +52,11 @@
     h.request("POST", url, body=json.dumps(data), headers=headers)
     resp = h.getresponse()
+    if resp.status!=200:
+        return {'error': 'Connection error (%s, %s)' % (response.status, response.reason)}
     jsonout = resp.read()
     try:
         parsed_json = json.loads(jsonout[6:-1])
     except ValueError:
-        return None
+        return {'error': 'No JSON response'}
     return parsed_json
 
@@ -72,10 +75,68 @@
     h.request("GET", url, headers=headers)
     resp = h.getresponse()
+    if resp.status!=200:
+        return {'error': 'Connection error (%s, %s)' % (response.status, response.reason)}
     jsonout = resp.read()
     try:
         parsed_json = json.loads(jsonout)
     except ValueError:
-        return None
+        return {'error': 'No JSON response'}
     return parsed_json
+
+
+def query_remita(payment, merchantId, api_key, RRR, host, https, verify):
+
+    jr = get_payment_status_via_rrr(merchantId, api_key, RRR, host, https)
+    error = jr.get('error')
+    if error:
+        msg = log = error
+        return False, msg, log
+
+    # A typical JSON response
+    # {
+    # u'orderId': u'3456346346',
+    # u'status': u'021',
+    # u'amount': 1000.0,
+    # u'transactiontime': u'2017-07-31 11:17:24 AM',
+    # u'message': u'Transaction Pending',
+    # u'lineitems': [{u'status': u'021', u'lineItemsId': u'itemid1'},
+    #                {u'status': u'021', u'lineItemsId': u'itemid2'}
+    #               ],
+    # u'RRR': u'280007640804'}
+
+    payment.r_code = jr['status']
+    payment.r_desc = jr['message']
+    payment.r_amount_approved = jr['amount']
+    payment.r_pay_reference = jr['RRR']
+    payment.r_company = u'remita'
+    if payment.r_code != '00':
+        msg = _('Unsuccessful callback: ${a}', mapping = {'a': payment.r_desc})
+        log = 'unsuccessful callback for %s payment %s: %s' % (
+            payment.p_category, payment.p_id, payment.r_desc)
+        payment.p_state = 'failed'
+        notify(grok.ObjectModifiedEvent(payment))
+        return False, msg, log
+    if round(payment.r_amount_approved, 0) != round(payment.amount_auth, 0):
+        msg = _('Callback amount does not match.')
+        log = 'wrong callback for %s payment %s: %s' % (
+            payment.p_category, payment.p_id, str(jr))
+        payment.p_state = 'failed'
+        notify(grok.ObjectModifiedEvent(payment))
+        return False, msg, log
+    if jr['orderId'] != payment.p_id:
+        msg = _('Callback order id does not match.')
+        log = 'wrong callback for %s payment %s: %s' % (
+            payment.p_category, payment.p_id, str(jr))
+        payment.p_state = 'failed'
+        notify(grok.ObjectModifiedEvent(payment))
+        return False, msg, log
+    payment.p_state = 'paid'
+    if not verify:
+        payment.payment_date = datetime.utcnow()
+    msg = _('Successful callback received')
+    log = 'valid callback for %s payment %s: %s' % (
+        payment.p_category, payment.p_id, str(jr))
+    notify(grok.ObjectModifiedEvent(payment))
+    return True, msg, log
 
 
Index: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/remita/tests.py
===================================================================
--- main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/remita/tests.py	(revision 14736)
+++ main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/remita/tests.py	(revision 14737)
@@ -25,9 +25,9 @@
 from waeup.kofa.applicants.tests.test_browser import ApplicantsFullSetup
 from waeup.kofa.configuration import SessionConfiguration
-from waeup.kofa.students.payments import StudentOnlinePayment
+from kofacustom.nigeria.students.payments import NigeriaStudentOnlinePayment
 from kofacustom.nigeria.testing import FunctionalLayer
 
 from kofacustom.nigeria.remita.helpers import (
-    get_JSON_POST_response, get_payment_status_via_rrr)
+    get_JSON_POST_response, get_payment_status_via_rrr, query_remita)
 
 # Also run tests that send requests to external servers?
@@ -40,9 +40,10 @@
         myself = __file__
         if myself.endswith('.pyc'):
-            myself = myself[:-2]
+            myself = myself[:-1]
         print "WARNING: external tests are skipped!"
         print "WARNING: edit %s to enable them." % myself
         return
     return func
+
 
 class HelperTests(unittest.TestCase):
@@ -83,4 +84,5 @@
             u'statuscode': u'055'}
 
+
     @external_test
     def test_payment_status_via_rrr(self):
@@ -105,2 +107,55 @@
             u'RRR': u'280007640804'}
 
+
+class RemitaTestsStudents(StudentsFullSetup):
+    """Tests for the Remita payment gateway.
+    """
+
+    layer = FunctionalLayer
+
+    merchantId = '2547916'
+    serviceTypeId = '4430731'
+    api_key = '1946'
+    orderId = '3456346346'
+    amount = '1000'
+    responseurl = 'http://xxxx'
+    host = 'www.remitademo.net'
+
+    def setUp(self):
+        super(RemitaTestsStudents, self).setUp()
+        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+        self.browser.open(self.payments_path)
+        IWorkflowState(self.student).setState('cleared')
+        self.student.nationality = u'NG'
+        self.browser.open(self.payments_path + '/addop')
+        self.browser.getControl(name="form.p_category").value = ['schoolfee']
+        self.browser.getControl("Create ticket").click()
+        self.assertMatches('...ticket created...',
+                           self.browser.contents)
+        ctrl = self.browser.getControl(name='val_id')
+        self.value = ctrl.options[0]
+        self.browser.getLink(self.value).click()
+        self.assertMatches('...Amount Authorized...',
+                           self.browser.contents)
+        self.assertTrue('<span>40000.0</span>', self.browser.contents)
+        self.payment_url = self.browser.url
+        self.payment = self.student['payments'][self.value]
+
+
+    @external_test
+    def test_query_remita(self):
+        # We can only test the first part of query_interswitch since
+        # we have no succesful payment.
+        qr = query_remita(
+            self.payment,
+            merchantId=self.merchantId,
+            api_key=self.api_key,
+            RRR='280007640804',
+            host=self.host,
+            https=False,
+            verify=False)
+        assert qr == (
+            False,
+            u'Unsuccessful callback: ${a}',
+            u'unsuccessful callback for schoolfee payment %s: Transaction Pending'
+            % self.payment.p_id)
