source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/etranzact/tests.py @ 16487

Last change on this file since 16487 was 16484, checked in by Henrik Bettermann, 4 years ago

Implement PAYDirect Bank Branch payment.

  • Property svn:keywords set to Id
File size: 13.5 KB
Line 
1## $Id: tests.py 16484 2021-05-19 07:47:21Z 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 os
19import unittest
20import random
21import json
22import hashlib
23import httplib
24from urllib import urlencode
25from datetime import datetime, timedelta, date
26from zope.component import createObject, getUtility
27from zope.catalog.interfaces import ICatalog
28from hurry.workflow.interfaces import IWorkflowState
29from waeup.kofa.students.tests.test_browser import StudentsFullSetup
30from waeup.kofa.applicants.tests.test_browser import ApplicantsFullSetup
31from waeup.kofa.configuration import SessionConfiguration
32from kofacustom.nigeria.students.payments import NigeriaStudentOnlinePayment
33from kofacustom.nigeria.testing import FunctionalLayer
34from kofacustom.nigeria.etranzact.helpers import (
35    query_history, query_payoutlet, ERROR_PART1, ERROR_PART2)
36
37#from kofacustom.nigeria.etranzact.helpers import (query_etranzact)
38
39# Also run tests that send requests to external servers?
40#   If you enable this, please make sure the external services
41#   do exist really and are not bothered by being spammed by a test programme.
42
43EXTERNAL_TESTS = False
44
45TERMINAL_ID = '5003021194'
46HOST = 'demo.etranzact.com'
47HTTPS = True
48SECRET_KEY = 'DEMO_KEY'
49LOGO_URL = 'https://iuokada.waeup.org/static_custom/iou_logo.png'
50GATEWAY_AMT = 500.0
51
52# Valid transaction id in Etranzact system
53TID = 'p5689785145198'
54
55def external_test(func):
56    if not EXTERNAL_TESTS:
57        myself = __file__
58        if myself.endswith('.pyc'):
59            myself = myself[:-1]
60        print "WARNING: external tests are skipped!"
61        print "WARNING: edit %s to enable them." % myself
62        return
63    return func
64
65def post_caller(host, https, terminal_id, transaction_id, responseurl,
66                        amount_auth, email, phone, display_fullname, hashvalue,
67                        logo_url):
68    headers={"Content-type": "application/x-www-form-urlencoded",
69             "Accept": "text/plain"}
70    url = "/webconnect/v3/caller.jsp"
71    if https:
72        h = httplib.HTTPSConnection(host)
73    else:
74        h = httplib.HTTPConnection(host)
75    args = {'TERMINAL_ID': terminal_id,
76            'TRANSACTION_ID': transaction_id,
77            'RESPONSE_URL': responseurl,
78            'AMOUNT': amount_auth,
79            'EMAIL': email,
80            'PHONENO': phone,
81            'FULL_NAME': display_fullname,
82            'CURRENCY_CODE': 'NGN',
83            'CHECKSUM': hashvalue,
84            'LOGO_URL': logo_url,
85            }
86    h.request('POST', url, urlencode(args), headers)
87    return
88    response = h.getresponse()
89    if response.status!=200:
90        return 'Connection error (%s, %s)' % (response.status, response.reason)
91    resp = response.read()
92    return resp
93
94def create_transaction(transaction_id):
95    responseurl = 'http://xxxx'
96    amount = '4444.0'
97    email = 'aa@aa.ng'
98    phone = '12324'
99    display_fullname = 'Tester'
100    logo_url = 'http://xxxx'
101    hashargs =  amount + TERMINAL_ID + transaction_id \
102        + responseurl + 'DEMO_KEY'
103    hashvalue = hashlib.md5(hashargs).hexdigest()
104    response = post_caller(HOST, HTTPS, TERMINAL_ID,
105                         transaction_id, responseurl,
106                         amount, email, phone,
107                         display_fullname, hashvalue,
108                         logo_url)
109    return response
110
111
112class HelperTests(unittest.TestCase):
113
114    terminal_id = TERMINAL_ID
115
116    @external_test
117    def test_query_history(self):
118        transaction_id = str(random.randint(100000000, 999999999))
119        raw, formvars = query_history(HOST, self.terminal_id,
120                                transaction_id, HTTPS)
121        self.assertTrue(
122            'Transaction with the given transaction_id (%s) not found'
123            % transaction_id in raw)
124        # Okay, let's create a transaction
125        caller_response = create_transaction(transaction_id)
126        self.assertEqual(caller_response, None)
127        # It seems that the transaction has been created but we don't get a
128        # useful response
129        raw, formvars = query_history(HOST, self.terminal_id,
130                                transaction_id, HTTPS)
131        self.assertTrue(
132            '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"\r\n    '
133            '"http://www.w3.org/TR/html4/loose.dtd">' in raw)
134        # The same, an 'empty' response obviously means that the transaction
135        # was found but no result was  sent to the response_url because the
136        # payment was cancelled.
137
138        # Peter: No response would be returned because payment status information
139        # was not saved. Whenever you get a null response, means payment was
140        # not received only payments with error code 0 is successful.
141        # So in this case transaction fails.
142
143        # We manually created and tried to pay a transaction
144        # which seems to be valid till next restart of the demo portal.
145        raw, formvars = query_history(HOST, self.terminal_id, TID, HTTPS)
146        # Now Etranzact is redirecting but the response is still useless
147        self.assertTrue('Redirecting...' in raw)
148        self.assertEqual(formvars['TRANSACTION_ID'], TID)
149        return
150
151    @external_test
152    def test_query_payoutlet(self):
153        # We've got some test numbers from Etranzact for testing
154        payment = NigeriaStudentOnlinePayment()
155        payment.p_id = 'p5723474039401'
156        success, msg, log = query_payoutlet(
157            HOST, '5003021194', '500854291572447457669', payment, True)
158        self.assertTrue(msg, 'Wrong amount')
159        payment.amount_auth = 200000.0
160        success, msg, log = query_payoutlet(
161            HOST, '5003021194', '500854291572447457669', payment, True)
162        self.assertTrue(success)
163        payment.p_id = 'xyz'
164        success, msg, log = query_payoutlet(
165            HOST, '5003021194', '500854291572447457669', payment, True)
166        self.assertTrue(msg, 'Wrong payment id')
167        return
168
169class EtranzactTestsApplicants(ApplicantsFullSetup):
170    """Tests for the Etranzact payment gateway.
171    """
172
173    layer = FunctionalLayer
174
175    def setUp(self):
176        super(EtranzactTestsApplicants, self).setUp()
177        configuration = SessionConfiguration()
178        configuration.academic_session = datetime.now().year - 2
179        configuration.etranzact_webconnect_enabled = True
180        configuration.etranzact_payoutlet_enabled = True
181        self.app['configuration'].addSessionConfiguration(configuration)
182        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
183        self.browser.open(self.manage_path)
184        #IWorkflowState(self.student).setState('started')
185        super(EtranzactTestsApplicants, self).fill_correct_values()
186        self.applicantscontainer.application_fee = 3333.0
187        self.browser.getControl(name="form.nationality").value = ['NG']
188        self.browser.getControl(name="transition").value = ['start']
189        self.browser.getControl("Save").click()
190        self.browser.getControl("Add online").click()
191        self.assertMatches('...ticket created...',
192                           self.browser.contents)
193        self.payment = self.applicant.values()[0]
194        self.payment_url = self.browser.url
195
196    @external_test
197    def test_applicant_views(self):
198        # Manager can access Etranzact form
199        self.browser.getLink("Pay via Etranzact WebConnect").click()
200        self.assertTrue("Pay now" in self.browser.contents)
201        # Means of testing end here.
202        # We requery an existing paiment now.
203        self.payment.p_id = TID
204        self.browser.open(self.payment_url)
205        self.browser.getLink("Requery Etranzact WebConnect History").click()
206        self.assertTrue('Wrong checksum.' in self.browser.contents)
207        # ... probably because responseurl of the transaction stored in the
208        # system and the responseurl generated in process_response are
209        # different
210        # Means of testing end here again.
211        return
212
213class EtranzactTestsStudents(StudentsFullSetup):
214    """Tests for the Etranzact payment gateway.
215    """
216
217    layer = FunctionalLayer
218
219    def setUp(self):
220        super(EtranzactTestsStudents, self).setUp()
221        self.app['configuration']['2004'].etranzact_webconnect_enabled = True
222        self.app['configuration']['2004'].etranzact_payoutlet_enabled = True
223        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
224        self.browser.open(self.payments_path)
225        IWorkflowState(self.student).setState('cleared')
226        self.student.nationality = u'NG'
227        self.browser.open(self.payments_path + '/addop')
228        self.browser.getControl(name="form.p_category").value = ['schoolfee']
229        self.browser.getControl("Create ticket").click()
230        self.assertMatches('...ticket created...',
231                           self.browser.contents)
232        self.browser.open(self.payments_path)
233        ctrl = self.browser.getControl(name='val_id')
234        self.value = ctrl.options[0]
235        self.browser.getLink(self.value).click()
236        self.assertMatches('...Amount Authorized...',
237                           self.browser.contents)
238        self.assertTrue('<span>40000.0</span>', self.browser.contents)
239        self.payment_url = self.browser.url
240        self.payment = self.student['payments'][self.value]
241
242    @external_test
243    def test_student_views(self):
244        # Manager can access Etranzact form
245        self.browser.getLink("Pay via Etranzact WebConnect").click()
246        self.assertTrue("Pay now" in self.browser.contents)
247        # Means of testing end here.
248        # We requery an existing paiment now.
249        self.payment.p_id = TID
250        self.browser.open(self.payment_url)
251        self.browser.getLink("Requery Etranzact WebConnect History").click()
252        self.assertTrue('Wrong checksum.' in self.browser.contents)
253        # ... probably because responseurl and amount stored in the
254        # system and the responseurl generated in process_response are
255        # different
256        # Means of testing end here again.
257        return
258
259    @external_test
260    def test_student_payoutlet_views(self):
261        self.browser.getLink("Pay via Etranzact PayOutlet").click()
262        self.browser.getControl(name="confirmation_number").value = '600854291572447457669'
263        self.browser.getControl("Requery now").click()
264        # This response is strange
265        self.assertTrue('-3:Wrong Setup' in self.browser.contents)
266        self.browser.getLink("Pay via Etranzact PayOutlet").click()
267        # This confirmation number exists
268        self.browser.getControl(name="confirmation_number").value = '500854291572447457669'
269        self.browser.getControl("Requery now").click()
270        self.assertTrue('Wrong amount' in self.browser.contents)
271        # Some attributes have been set
272        self.assertEqual(self.payment.r_desc, 'Test Test Test-CLEARANCE -001-p5723474039401')
273        return
274
275    def test_webservice(self):
276        self.browser.open(
277            'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=SCHOOLFEE'
278            % self.payment.p_id)
279        self.assertEqual(self.browser.contents,
280            'PayeeName=Anna Tester~'
281            'Faculty=fac1~Department=dep1~'
282            'Level=100~ProgrammeType=CERT1~'
283            'StudyType=ug_ft~Session=2004/2005~'
284            'PayeeID=%s~'
285            'Amount=40000.0~FeeStatus=unpaid~'
286            'Semester=N/A~PaymentType=School Fee~'
287            'MatricNumber=234~Email=aa@aa.ng~'
288            'PhoneNumber=1234' % self.payment.p_id)
289        self.browser.open('http://localhost/app/feerequest')
290        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Missing PAYEE_ID' + ERROR_PART2)
291
292        self.browser.open('http://localhost/app/feerequest?NONSENSE=nonsense')
293        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Missing PAYEE_ID' + ERROR_PART2)
294
295        self.browser.open(
296            'http://localhost/app/feerequest?PAYEE_ID=nonsense&PAYMENT_TYPE=SCHOOLFEE')
297        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Invalid PAYEE_ID' + ERROR_PART2)
298
299        self.browser.open(
300            'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=NONSENSE'
301            % self.payment.p_id)
302        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Invalid PAYMENT_TYPE' + ERROR_PART2)
303
304        self.browser.open(
305            'http://localhost/app/feerequest?PAYEE_ID=%s' % self.payment.p_id)
306        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Invalid PAYMENT_TYPE' + ERROR_PART2)
307
308        self.browser.open(
309            'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=CLEARANCE'
310            % self.payment.p_id)
311        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Wrong PAYMENT_TYPE' + ERROR_PART2)
312
313        # Change payment state
314        self.student['payments'][self.payment.p_id].p_state = 'paid'
315
316        self.browser.open(
317            'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=SCHOOLFEE'
318            % self.payment.p_id)
319        self.assertEqual(self.browser.contents, ERROR_PART1 + 'PAYEE_ID already used' + ERROR_PART2)
Note: See TracBrowser for help on using the repository browser.