## $Id: tests.py 17783 2024-05-14 08:46:27Z 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 os
import unittest
import random
import json
import hashlib
import httplib
from urllib import urlencode
from datetime import datetime, timedelta, date
from zope.component import createObject, getUtility
from zope.catalog.interfaces import ICatalog
from hurry.workflow.interfaces import IWorkflowState
from waeup.kofa.students.tests.test_browser import StudentsFullSetup
from waeup.kofa.applicants.tests.test_browser import ApplicantsFullSetup
from waeup.kofa.configuration import SessionConfiguration
from kofacustom.nigeria.students.payments import NigeriaStudentOnlinePayment
from kofacustom.nigeria.testing import FunctionalLayer
from kofacustom.nigeria.etranzact.helpers import (
query_history, query_payoutlet, ERROR_PART1, ERROR_PART2,
)
#from kofacustom.nigeria.etranzact.helpers import (query_etranzact)
# Also run tests that send requests to external servers?
# If you enable this, please make sure the external services
# do exist really and are not bothered by being spammed by a test programme.
EXTERNAL_TESTS = False
TERMINAL_ID = '5003021194'
HOST = 'demo.etranzactng.com'
HTTPS = True
SECRET_KEY = 'DEMO_KEY'
LOGO_URL = 'https://iuokada.waeup.org/static_custom/iou_logo.png'
GATEWAY_AMT = 500.0
# Valid transaction id in Etranzact system
TID = 'p5689785145198'
def external_test(func):
if not EXTERNAL_TESTS:
myself = __file__
if myself.endswith('.pyc'):
myself = myself[:-1]
print "WARNING: external tests are skipped!"
print "WARNING: edit %s to enable them." % myself
return
return func
def post_caller(host, https, terminal_id, transaction_id, responseurl,
amount_auth, email, phone, display_fullname, hashvalue,
logo_url):
headers={"Content-type": "application/x-www-form-urlencoded",
"Accept": "text/plain"}
url = "/webconnect/v3/caller.jsp"
if https:
h = httplib.HTTPSConnection(host)
else:
h = httplib.HTTPConnection(host)
args = {'TERMINAL_ID': terminal_id,
'TRANSACTION_ID': transaction_id,
'RESPONSE_URL': responseurl,
'AMOUNT': amount_auth,
'EMAIL': email,
'PHONENO': phone,
'FULL_NAME': display_fullname,
'CURRENCY_CODE': 'NGN',
'CHECKSUM': hashvalue,
'LOGO_URL': logo_url,
}
h.request('POST', url, urlencode(args), headers)
return
response = h.getresponse()
if response.status!=200:
return 'Connection error (%s, %s)' % (response.status, response.reason)
resp = response.read()
return resp
def create_transaction(transaction_id):
responseurl = 'http://xxxx'
amount = '4444.0'
email = 'aa@aa.ng'
phone = '12324'
display_fullname = 'Tester'
logo_url = 'http://xxxx'
hashargs = amount + TERMINAL_ID + transaction_id \
+ responseurl + 'DEMO_KEY'
hashvalue = hashlib.md5(hashargs).hexdigest()
response = post_caller(HOST, HTTPS, TERMINAL_ID,
transaction_id, responseurl,
amount, email, phone,
display_fullname, hashvalue,
logo_url)
return response
class HelperTests(unittest.TestCase):
terminal_id = TERMINAL_ID
@external_test
def test_query_history(self):
transaction_id = str(random.randint(100000000, 999999999))
raw, formvars = query_history(HOST, self.terminal_id,
transaction_id, HTTPS)
self.assertTrue(
'Transaction with the given transaction_id (%s) not found'
% transaction_id in raw)
# Okay, let's create a transaction
caller_response = create_transaction(transaction_id)
self.assertEqual(caller_response, None)
# It seems that the transaction has been created but we don't get a
# useful response
raw, formvars = query_history(HOST, self.terminal_id,
transaction_id, HTTPS)
self.assertTrue(
'' in raw)
# The same, an 'empty' response obviously means that the transaction
# was found but no result was sent to the response_url because the
# payment was cancelled.
# Peter: No response would be returned because payment status information
# was not saved. Whenever you get a null response, means payment was
# not received only payments with error code 0 is successful.
# So in this case transaction fails.
# We manually created and tried to pay a transaction
# which seems to be valid till next restart of the demo portal.
raw, formvars = query_history(HOST, self.terminal_id, TID, HTTPS)
# Now Etranzact is redirecting but the response is still useless
self.assertTrue('Redirecting...' in raw)
self.assertEqual(formvars['TRANSACTION_ID'], TID)
return
@external_test
def test_query_payoutlet(self):
# We've got some test numbers from Etranzact for testing
payment = NigeriaStudentOnlinePayment()
payment.p_id = 'p5723474039401'
success, msg, log = query_payoutlet(
HOST, '5003021194', '500854291572447457669', payment, True)
self.assertTrue(msg, 'Wrong amount')
payment.amount_auth = 200000.0
success, msg, log = query_payoutlet(
HOST, '5003021194', '500854291572447457669', payment, True)
self.assertTrue(success)
payment.p_id = 'xyz'
success, msg, log = query_payoutlet(
HOST, '5003021194', '500854291572447457669', payment, True)
self.assertTrue(msg, 'Wrong payment id')
return
class EtranzactTestsApplicants(ApplicantsFullSetup):
"""Tests for the Etranzact payment gateway.
"""
layer = FunctionalLayer
def setUp(self):
super(EtranzactTestsApplicants, self).setUp()
configuration = SessionConfiguration()
configuration.academic_session = datetime.now().year - 2
configuration.etranzact_webconnect_enabled = True
configuration.etranzact_payoutlet_enabled = True
self.app['configuration'].addSessionConfiguration(configuration)
self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
self.browser.open(self.manage_path)
#IWorkflowState(self.student).setState('started')
super(EtranzactTestsApplicants, self).fill_correct_values()
self.applicantscontainer.application_fee = 3333.0
self.browser.getControl(name="form.nationality").value = ['NG']
self.browser.getControl(name="transition").value = ['start']
self.browser.getControl("Save").click()
self.browser.getControl("Add online").click()
self.assertMatches('...ticket created...',
self.browser.contents)
self.payment = self.applicant.values()[0]
self.payment_url = self.browser.url
@external_test
def test_applicant_views(self):
# Manager can access Etranzact form
self.browser.getLink("Pay via Etranzact WebConnect").click()
self.assertTrue("Pay now" in self.browser.contents)
# Means of testing end here.
# We requery an existing paiment now.
self.payment.p_id = TID
self.browser.open(self.payment_url)
self.browser.getLink("Requery Etranzact WebConnect History").click()
self.assertTrue('Wrong checksum.' in self.browser.contents)
# ... probably because responseurl of the transaction stored in the
# system and the responseurl generated in process_response are
# different
# Means of testing end here again.
return
class EtranzactTestsStudents(StudentsFullSetup):
"""Tests for the Etranzact payment gateway.
"""
layer = FunctionalLayer
def setUp(self):
super(EtranzactTestsStudents, self).setUp()
self.app['configuration']['2004'].etranzact_webconnect_enabled = True
self.app['configuration']['2004'].etranzact_payoutlet_enabled = True
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)
self.browser.open(self.payments_path)
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('40000.0', self.browser.contents)
self.payment_url = self.browser.url
self.payment = self.student['payments'][self.value]
@external_test
def test_student_views(self):
# Manager can access Etranzact form
self.browser.getLink("Pay via Etranzact WebConnect").click()
self.assertTrue("Pay now" in self.browser.contents)
# Means of testing end here.
# We requery an existing paiment now.
self.payment.p_id = TID
self.browser.open(self.payment_url)
self.browser.getLink("Requery Etranzact WebConnect History").click()
self.assertTrue('Wrong checksum.' in self.browser.contents)
# ... probably because responseurl and amount stored in the
# system and the responseurl generated in process_response are
# different
# Means of testing end here again.
return
@external_test
def test_student_payoutlet_views(self):
self.browser.getLink("Pay via Etranzact PayOutlet").click()
self.browser.getControl(name="confirmation_number").value = '600854291572447457669'
self.browser.getControl("Requery now").click()
# This response is strange
self.assertTrue('-3:Wrong Setup' in self.browser.contents)
self.browser.getLink("Pay via Etranzact PayOutlet").click()
# This confirmation number exists
self.browser.getControl(name="confirmation_number").value = '500854291572447457669'
self.browser.getControl("Requery now").click()
self.assertTrue('Wrong amount' in self.browser.contents)
# Some attributes have been set
self.assertEqual(self.payment.r_desc, 'Test Test Test-CLEARANCE -001-p5723474039401')
return
def test_webservice(self):
self.browser.open(
'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=SCHOOLFEE'
% self.payment.p_id)
self.assertEqual(self.browser.contents,
'PayeeName=Anna Tester~'
'Faculty=fac1~Department=dep1~'
'Level=100~ProgrammeType=CERT1~'
'StudyType=ug_ft~Session=2004/2005~'
'PayeeID=%s~'
'Amount=40000.0~FeeStatus=unpaid~'
'Semester=N/A~PaymentType=School Fee~'
'MatricNumber=234~Email=aa@aa.ng~'
'PhoneNumber=1234' % self.payment.p_id)
self.browser.open('http://localhost/app/feerequest')
self.assertEqual(self.browser.contents, ERROR_PART1 + 'Missing PAYEE_ID' + ERROR_PART2)
self.browser.open('http://localhost/app/feerequest?NONSENSE=nonsense')
self.assertEqual(self.browser.contents, ERROR_PART1 + 'Missing PAYEE_ID' + ERROR_PART2)
self.browser.open(
'http://localhost/app/feerequest?PAYEE_ID=nonsense&PAYMENT_TYPE=SCHOOLFEE')
self.assertEqual(self.browser.contents, ERROR_PART1 + 'Invalid PAYEE_ID' + ERROR_PART2)
self.browser.open(
'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=NONSENSE'
% self.payment.p_id)
self.assertEqual(self.browser.contents, ERROR_PART1 + 'Invalid PAYMENT_TYPE' + ERROR_PART2)
self.browser.open(
'http://localhost/app/feerequest?PAYEE_ID=%s' % self.payment.p_id)
self.assertEqual(self.browser.contents, ERROR_PART1 + 'Invalid PAYMENT_TYPE' + ERROR_PART2)
self.browser.open(
'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=CLEARANCE'
% self.payment.p_id)
self.assertEqual(self.browser.contents, ERROR_PART1 + 'Wrong PAYMENT_TYPE' + ERROR_PART2)
# Change payment state
self.student['payments'][self.payment.p_id].p_state = 'paid'
self.browser.open(
'http://localhost/app/feerequest?PAYEE_ID=%s&PAYMENT_TYPE=SCHOOLFEE'
% self.payment.p_id)
self.assertEqual(self.browser.contents, ERROR_PART1 + 'PAYEE_ID already used' + ERROR_PART2)
# Credo tests
from kofacustom.nigeria.etranzact.helpers import (
query_credo_payment, get_JSON_response_initialize)
SECRET_API_KEY = "0PRI0500LB11cBSSLcW0DcW1BcWgmf45"
API_PUBLIC_KEY = "0PUB0500wuoOe9sdtSOLj5peqHKc8Q9W"
EXTERNAL_TESTS_CREDO = True
CREDO_HOST = "api.credodemo.com"
def external_test_credo(func):
if not EXTERNAL_TESTS_CREDO:
myself = __file__
if myself.endswith('.pyc'):
myself = myself[:-1]
print "WARNING: external Credo tests are skipped!"
print "WARNING: edit %s to enable them." % myself
return
return func
class CredoTestsStudents(StudentsFullSetup):
layer = FunctionalLayer
P_ID = 'p7120340727304' # works only if such a payment was made on the test platform
def setUp(self):
super(CredoTestsStudents, self).setUp()
self.app['configuration']['2004'].etranzact_credo_enabled = True
payment = createObject('waeup.StudentOnlinePayment')
payment.p_id = self.P_ID
payment.p_category = 'schoolfee'
payment.amount_auth = 100000.0
self.student['payments'][payment.p_id] = payment
self.payment2 = payment
@external_test_credo
def test_initialize(self):
public_api_key = API_PUBLIC_KEY
callbackUrl = 'aa.aa.aa'
response = get_JSON_response_initialize(self.payment2, CREDO_HOST, callbackUrl, public_api_key, None)
## A typical response
#{u'status': 200,
# u'execTime': 5.109764,
# u'message': u'Successfully processed',
# u'data':
# {u'credoReference': u'vsb200B5oM0521Mb00og',
# u'reference': u'xyz',
# u'authorizationUrl': u'https://pay.credodemo.com/vsb200B5oM0521Mb00og'
# },
# u'error': []
#}
# Payment already exists
self.assertEqual(response, {'error': u'Reference must be unique. '})
#self.assertEqual(response['status'], 200)
#self.assertEqual(response['message'], 'Successfully processed')
#self.assertEqual(response['data']['reference'], self.P_ID)
#self.assertTrue('https://pay.credodemo.com/' in response['data']['authorizationUrl'])
return
@external_test_credo
def test_verify(self):
self.payment2.p_id = 'anything'
success, msg, log = query_credo_payment(self.payment2, CREDO_HOST, SECRET_API_KEY)
self.assertEqual(log, 'Transaction with ref# anything not found')
self.payment2.p_id = self.P_ID # manually paid
success, msg, log = query_credo_payment(self.payment2, CREDO_HOST, SECRET_API_KEY)
self.assertEqual(msg, 'Successful callback received')
self.assertEqual(self.payment2.r_code, '0')
self.assertEqual(self.payment2.r_desc, 'Successfully processed')
self.assertEqual(self.payment2.p_state, 'paid')
return
@external_test_credo
def test_student_credo_views(self):
self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
self.browser.open(self.payments_path)
self.browser.getLink(self.P_ID).click()
self.browser.getLink("Requery Etranzact Credo").click()
self.assertTrue('Successfully processed' in self.browser.contents)
self.assertEqual(self.payment2.r_desc, 'Successfully processed')
return
class CredoTestsApplicants(ApplicantsFullSetup):
layer = FunctionalLayer
P_ID = 'p7120808915674' # works only if such a payment was made on the test platform
def setUp(self):
super(CredoTestsApplicants, self).setUp()
# Add session configuration object
configuration = SessionConfiguration()
configuration.academic_session = self.applicant.__parent__.year
configuration.etranzact_credo_enabled = True
self.app['configuration'].addSessionConfiguration(configuration)
payment = createObject('waeup.ApplicantOnlinePayment')
payment.p_id = self.P_ID
payment.p_category = 'application'
payment.amount_auth = 5000.0
self.applicant.email = 'xx@xx.xx'
self.applicant[payment.p_id] = payment
self.payment2 = payment
@external_test_credo
def test_initialize(self):
public_api_key = API_PUBLIC_KEY
callbackUrl = 'aa.aa.aa'
response = get_JSON_response_initialize(self.payment2, CREDO_HOST, callbackUrl, public_api_key, None)
# Payment already exists
self.assertEqual(response, {'error': u'Reference must be unique. '})
#self.assertEqual(response['status'], 200)
#self.assertEqual(response['message'], 'Successfully processed')
#self.assertEqual(response['data']['reference'], self.P_ID)
#self.assertTrue('https://pay.credodemo.com/' in response['data']['authorizationUrl'])
return
@external_test_credo
def test_verify(self):
self.payment2.p_id = 'anything'
success, msg, log = query_credo_payment(self.payment2, CREDO_HOST, SECRET_API_KEY)
self.assertEqual(log, 'Transaction with ref# anything not found')
self.payment2.p_id = self.P_ID # manually paid
success, msg, log = query_credo_payment(self.payment2, CREDO_HOST, SECRET_API_KEY)
self.assertEqual(msg, 'Successful callback received')
self.assertEqual(self.payment2.r_code, '0')
self.assertEqual(self.payment2.r_desc, 'Successfully processed')
self.assertEqual(self.payment2.p_state, 'paid')
return
@external_test_credo
def test_applicant_credo_views(self):
IWorkflowState(self.applicant).setState('started')
self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
self.browser.open(self.view_path)
self.browser.getLink(self.P_ID).click()
self.browser.getLink("Requery Etranzact Credo").click()
self.assertTrue('Successfully processed' in self.browser.contents)
self.assertEqual(self.payment2.r_desc, 'Successfully processed')
self.assertEqual(self.applicant.state, 'paid')
return