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

Last change on this file since 15755 was 15755, checked in by Henrik Bettermann, 5 years ago

Prepare all payment gateway modules for net amount fee configuration. In the future, provider and gateway surcharges will be determined and added just before the data are being send to the gateways for the first time.

  • Property svn:keywords set to Id
File size: 13.4 KB
RevLine 
[15586]1## $Id: tests.py 15755 2019-11-05 23:19:58Z henrik $
[15585]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
[15589]23import httplib
24from urllib import urlencode
[15585]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
[15734]34from kofacustom.nigeria.etranzact.helpers import (
35    query_history, query_payoutlet, ERROR_PART1, ERROR_PART2)
[15585]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
[15755]43EXTERNAL_TESTS = False
[15585]44
[15730]45TERMINAL_ID = '5003021194'
[15585]46HOST = 'demo.etranzact.com'
47HTTPS = True
48SECRET_KEY = 'DEMO_KEY'
49LOGO_URL = 'https://iuokada.waeup.org/static_custom/iou_logo.png'
[15755]50GATEWAY_AMT = 500.0
[15585]51
[15702]52# Valid transaction id in Etranzact system
[15598]53TID = 'p5689785145198'
54
[15585]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
[15589]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
[15585]112class HelperTests(unittest.TestCase):
113
114    terminal_id = TERMINAL_ID
115
116    @external_test
[15589]117    def test_query_history(self):
[15585]118        transaction_id = str(random.randint(100000000, 999999999))
[15596]119        raw, formvars = query_history(HOST, self.terminal_id,
120                                transaction_id, HTTPS)
[15593]121        self.assertTrue(
[15585]122            'Transaction with the given transaction_id (%s) not found'
[15596]123            % transaction_id in raw)
[15585]124        # Okay, let's create a transaction
[15589]125        caller_response = create_transaction(transaction_id)
[15585]126        self.assertEqual(caller_response, None)
127        # It seems that the transaction has been created but we don't get a
128        # useful response
[15596]129        raw, formvars = query_history(HOST, self.terminal_id,
130                                transaction_id, HTTPS)
[15593]131        self.assertTrue(
132            '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"\r\n    '
[15596]133            '"http://www.w3.org/TR/html4/loose.dtd">' in raw)
[15585]134        # The same, an 'empty' response obviously means that the transaction
[15593]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
[15598]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)
[15702]146        # Now Etranzact is redirecting but the response is still useless
[15596]147        self.assertTrue('Redirecting...' in raw)
[15598]148        self.assertEqual(formvars['TRANSACTION_ID'], TID)
[15585]149        return
150
[15730]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
[15585]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
[15702]179        configuration.etranzact_webconnect_enabled = True
180        configuration.etranzact_payoutlet_enabled = True
[15585]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()
[15598]186        self.applicantscontainer.application_fee = 3333.0
[15585]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
[15600]197    def test_applicant_views(self):
[15702]198        # Manager can access Etranzact form
199        self.browser.getLink("Pay via Etranzact").click()
[15585]200        self.assertTrue("Pay now" in self.browser.contents)
[15598]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)
[15702]205        self.browser.getLink("Requery Etranzact History").click()
[15598]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.
[15585]211        return
212
[15600]213class EtranzactTestsStudents(StudentsFullSetup):
214    """Tests for the Etranzact payment gateway.
215    """
[15585]216
[15600]217    layer = FunctionalLayer
218
219    def setUp(self):
220        super(EtranzactTestsStudents, self).setUp()
[15702]221        self.app['configuration']['2004'].etranzact_webconnect_enabled = True
222        self.app['configuration']['2004'].etranzact_payoutlet_enabled = True
[15600]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        ctrl = self.browser.getControl(name='val_id')
233        self.value = ctrl.options[0]
234        self.browser.getLink(self.value).click()
235        self.assertMatches('...Amount Authorized...',
236                           self.browser.contents)
237        self.assertTrue('<span>40000.0</span>', self.browser.contents)
238        self.payment_url = self.browser.url
239        self.payment = self.student['payments'][self.value]
240
241    @external_test
242    def test_student_views(self):
[15702]243        # Manager can access Etranzact form
244        self.browser.getLink("Pay via Etranzact").click()
[15600]245        self.assertTrue("Pay now" in self.browser.contents)
246        # Means of testing end here.
247        # We requery an existing paiment now.
248        self.payment.p_id = TID
249        self.browser.open(self.payment_url)
[15702]250        self.browser.getLink("Requery Etranzact History").click()
[15600]251        self.assertTrue('Wrong checksum.' in self.browser.contents)
252        # ... probably because responseurl and amount stored in the
253        # system and the responseurl generated in process_response are
254        # different
255        # Means of testing end here again.
256        return
[15702]257
258    @external_test
259    def test_student_payoutlet_views(self):
260        self.browser.getLink("Enter Etranzact PIN").click()
[15730]261        self.browser.getControl(name="confirmation_number").value = '600854291572447457669'
[15702]262        self.browser.getControl("Submit to Etranzact").click()
[15730]263        # This response is strange
264        self.assertTrue('-3:Wrong Setup' in self.browser.contents)
265        self.browser.getLink("Enter Etranzact PIN").click()
266        # This confirmation number exists
267        self.browser.getControl(name="confirmation_number").value = '500854291572447457669'
268        self.browser.getControl("Submit to Etranzact").click()
269        self.assertTrue('Wrong amount' in self.browser.contents)
270        # Some attributes have been set
271        self.assertEqual(self.payment.r_desc, 'Test Test Test-CLEARANCE -001-p5723474039401')
272        return
[15734]273
274    def test_webservice(self):
275        self.browser.open(
276            'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=SCHOOLFEE'
277            % self.payment.p_id)
278        self.assertEqual(self.browser.contents,
279            'PayeeName=Anna Tester~'
280            'Faculty=fac1~Department=dep1~'
281            'Level=100~ProgrammeType=CERT1~'
282            'StudyType=ug_ft~Session=2004/2005~'
283            'PayeeID=%s~'
284            'Amount=40000.0~FeeStatus=unpaid~'
285            'Semester=N/A~PaymentType=School Fee~'
286            'MatricNumber=234~Email=aa@aa.ng~'
287            'PhoneNumber=1234' % self.payment.p_id)
288        self.browser.open('http://localhost/app/feerequest')
289        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Missing PAYEE_ID' + ERROR_PART2)
290
291        self.browser.open('http://localhost/app/feerequest?NONSENSE=nonsense')
292        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Missing PAYEE_ID' + ERROR_PART2)
293
294        self.browser.open(
295            'http://localhost/app/feerequest?PAYEE_ID=nonsense&PAYMENT_TYPE=SCHOOLFEE')
296        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Invalid PAYEE_ID' + ERROR_PART2)
297
298        self.browser.open(
299            'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=NONSENSE'
300            % self.payment.p_id)
301        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Invalid PAYMENT_TYPE' + ERROR_PART2)
302
303        self.browser.open(
304            'http://localhost/app/feerequest?PAYEE_ID=%s' % self.payment.p_id)
305        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Invalid PAYMENT_TYPE' + ERROR_PART2)
306
307        self.browser.open(
308            'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=CLEARANCE'
309            % self.payment.p_id)
310        self.assertEqual(self.browser.contents, ERROR_PART1 + 'Wrong PAYMENT_TYPE' + ERROR_PART2)
311
312        # Change payment state
313        self.student['payments'][self.payment.p_id].p_state = 'paid'
314
315        self.browser.open(
316            'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=SCHOOLFEE'
317            % self.payment.p_id)
318        self.assertEqual(self.browser.contents, ERROR_PART1 + 'PAYEE_ID already used' + ERROR_PART2)
Note: See TracBrowser for help on using the repository browser.