- Timestamp:
- 19 May 2021, 07:47:21 (4 years ago)
- Location:
- main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/interswitch
- Files:
-
- 2 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/interswitch/browser.py
r16247 r16484 22 22 from waeup.kofa.interfaces import IKofaUtils 23 23 from waeup.kofa.utils.helpers import to_timezone 24 from waeup.kofa.browser.layout import UtilityView, KofaPage 24 from waeup.kofa.browser.layout import UtilityView, KofaPage, KofaFormPage, action 25 25 from waeup.kofa.browser.viewlets import ManageActionButton 26 26 from waeup.kofa.students.interfaces import IStudentsUtils … … 28 28 from waeup.kofa.applicants.browser import OnlinePaymentDisplayFormPage as OPDPApplicant 29 29 from kofacustom.nigeria.interswitch.helpers import ( 30 query_interswitch, write_payments_log )30 query_interswitch, write_payments_log, fetch_booking_details) 31 31 from kofacustom.nigeria.payments.interfaces import INigeriaOnlinePayment 32 32 from kofacustom.nigeria.students.interfaces import INigeriaStudentOnlinePayment 33 33 from kofacustom.nigeria.applicants.interfaces import INigeriaApplicantOnlinePayment 34 from kofacustom.nigeria.interswitch.tests import PAYDIRECT_URL, PAYDIRECT_HOST, MERCHANT_ID 34 35 from kofacustom.nigeria.interfaces import MessageFactory as _ 35 36 … … 58 59 grok.require('waeup.payStudent') 59 60 icon = 'actionicon_pay.png' 60 text = _('Pay via Interswitch ')61 text = _('Pay via Interswitch CollegePAY') 61 62 target = 'goto_interswitch' 62 63 … … 89 90 grok.require('waeup.payStudent') 90 91 icon = 'actionicon_call.png' 91 text = _('Requery InterswitchHistory')92 text = _('Requery CollegePAY History') 92 93 target = 'request_webservice' 93 94 … … 315 316 grok.template('student_goto_interswitch') 316 317 grok.require('waeup.payStudent') 317 label = _('Submit data to CollegePAY (Interswitch Payment Gateway)')318 label = _('Submit data to CollegePAY') 318 319 submit_button = _('Submit') 319 320 … … 392 393 grok.template('applicant_goto_interswitch') 393 394 grok.name('goto_interswitch') 394 label = _('Submit data to CollegePAY (Interswitch Payment Gateway)')395 label = _('Submit data to CollegePAY') 395 396 submit_button = _('Submit') 396 397 … … 444 445 self.amount_auth = int(100 * self.context.amount_auth) 445 446 return 447 -
main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/interswitch/helpers.py
r16167 r16484 30 30 def SOAP_post(soap_action, xml, host, url, https): 31 31 """Handles making the SOAP request. 32 33 Further reading:34 http://testwebpay.interswitchng.com/test_paydirect/services/TransactionQueryWs.asmx?op=getTransactionData35 32 """ 36 33 if https: … … 48 45 return response 49 46 47 def write_payments_log(id, payment): 48 payment.logger.info( 49 '%s,%s,%s,%s,%s,%s,%s,%s,,,' % ( 50 id, payment.p_id, payment.p_category, 51 payment.amount_auth, payment.r_code, 52 payment.provider_amt, payment.gateway_amt, 53 payment.thirdparty_amt)) 54 55 # CollegePAY helper functions 50 56 51 57 def get_SOAP_response(product_id, transref, host, url, https): … … 228 234 return True, msg, log 229 235 230 def write_payments_log(id, payment): 231 payment.logger.info( 232 '%s,%s,%s,%s,%s,%s,%s,%s,,,' % ( 233 id, payment.p_id, payment.p_category, 234 payment.amount_auth, payment.r_code, 235 payment.provider_amt, payment.gateway_amt, 236 payment.thirdparty_amt)) 236 # PAYDirect helper functions 237 238 def get_SOAP_response_paydirect(merchant_id, p_id, host, url, https): 239 xml="""\ 240 <?xml version="1.0" encoding="utf-8"?> 241 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:book="http://interswitchng.com/bookonhold"> 242 <soap:Header/> 243 <soap:Body> 244 <book:FetchBookingDetails> 245 <book:ReservationDetailsRequest> 246 <book:MerchantId>%s</book:MerchantId> 247 <book:Bookings> 248 <book:Booking> 249 <book:ReferenceNumber>%s%s</book:ReferenceNumber> 250 </book:Booking> 251 </book:Bookings> 252 </book:ReservationDetailsRequest> 253 </book:FetchBookingDetails> 254 </soap:Body> 255 </soap:Envelope>""" % (merchant_id, merchant_id, p_id[1:]) 256 257 response=SOAP_post( 258 "http://interswitchng.com/bookonhold/FetchBookingDetails", 259 xml, host, url, https) 260 if response.status!=200: 261 error = 'Connection error (%s, %s)' % (response.status, response.reason) 262 return error 263 result_xml = response.read() 264 return result_xml 265 266 def fetch_booking_details(payment, merchant_id, host, url, https): 267 result_xml = get_SOAP_response_paydirect( 268 merchant_id, payment.p_id, host, url, https) 269 if result_xml.startswith('Connection error'): 270 return False, result_xml, result_xml 271 doc=parseString(result_xml) 272 if not doc.getElementsByTagName('PaymentStatus'): 273 msg = _('Your payment %s was not found.' % payment.p_id) 274 log = 'payment %s cannot be found' % payment.p_id 275 return False, msg, log 276 p_status = doc.getElementsByTagName('PaymentStatus')[0].firstChild.data 277 payment.r_code = p_status 278 try: 279 payment.r_desc = "%s - %s - %s" % ( 280 doc.getElementsByTagName('ChannelName')[0].firstChild.data, 281 doc.getElementsByTagName('TerminalId')[0].firstChild.data, 282 doc.getElementsByTagName('Location'))[0].firstChild.data 283 except AttributeError: 284 pass 285 try: 286 amount = doc.getElementsByTagName('Amount')[0].firstChild.data 287 payment.r_amount_approved = int(amount) 288 except AttributeError: 289 pass 290 try: 291 payment.r_pay_reference = doc.getElementsByTagName( 292 'ReferenceNumber').firstChild.data 293 except AttributeError: 294 pass 295 if p_status not in ('Pending', 'Completed'): 296 msg = _('Unknown status: %s' % sr[0]) 297 log = 'invalid callback for payment %s: %s' % (payment.p_id, status) 298 payment.p_state = 'failed' 299 notify(grok.ObjectModifiedEvent(payment)) 300 return False, msg, log 301 if p_status == 'Completed' and not payment.r_amount_approved: 302 msg = _('Amount unconfirmed') 303 log = 'unsuccessful callback for payment %s: amount unconfirmed' % payment.p_id 304 payment.p_state = 'failed' 305 notify(grok.ObjectModifiedEvent(payment)) 306 return False, msg, log 307 if p_status == 'Pending': 308 msg = _('Payment pending') 309 log = 'unsuccessful callback for payment %s: pending' % payment.p_id 310 payment.p_state = 'failed' 311 notify(grok.ObjectModifiedEvent(payment)) 312 return False, msg, log 313 if payment.r_amount_approved != payment.amount_auth: 314 msg = _('Callback amount does not match.') 315 log = 'unsuccessful callback for %s payment %s: callback amount %s does not match' % ( 316 payment.p_category, payment.p_id, amount) 317 payment.p_state = 'failed' 318 notify(grok.ObjectModifiedEvent(payment)) 319 return False, msg, log 320 payment.p_state = 'paid' 321 payment.payment_date = datetime.utcnow() 322 msg = _('Successful callback received') 323 log = 'valid callback for %s payment %s: %s' % ( 324 payment.p_category, payment.p_id, p_status) 325 notify(grok.ObjectModifiedEvent(payment)) 326 return True, msg, log -
main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/interswitch/tests.py
r16378 r16484 20 20 from zope.component import createObject, getUtility 21 21 from zope.catalog.interfaces import ICatalog 22 from xml.dom.minidom import parseString 22 23 from hurry.workflow.interfaces import IWorkflowState 23 24 from waeup.kofa.students.tests.test_browser import StudentsFullSetup … … 25 26 from waeup.kofa.configuration import SessionConfiguration 26 27 from waeup.kofa.students.payments import StudentOnlinePayment 27 from kofacustom.nigeria.interswitch.helpers import query_interswitch 28 from waeup.kofa.browser.tests.test_pdf import samples_dir 29 from kofacustom.nigeria.interswitch.helpers import ( 30 query_interswitch, get_SOAP_response_paydirect, SOAP_post) 28 31 from kofacustom.nigeria.testing import FunctionalLayer 29 32 … … 31 34 # If you enable this, please make sure the external services 32 35 # do exist really and are not bothered by being spammed by a test programme. 33 EXTERNAL_TESTS = False 34 35 def external_test(func): 36 if not EXTERNAL_TESTS: 36 EXTERNAL_TESTS_1 = True 37 EXTERNAL_TESTS_2 = True 38 39 PAYDIRECT_HOST = 'sandbox.interswitchng.com' 40 PAYDIRECT_URL = '/bookonhold/bookonhold.asmx' 41 MERCHANT_ID = '6033' 42 43 def external_test_1(func): 44 if not EXTERNAL_TESTS_1: 45 myself = __file__ 46 if myself.endswith('.pyc'): 47 myself = myself[:-1] 48 print "WARNING: external tests are skipped!" 49 print "WARNING: edit %s to enable them." % myself 50 return 51 return func 52 53 def external_test_2(func): 54 if not EXTERNAL_TESTS_2: 37 55 myself = __file__ 38 56 if myself.endswith('.pyc'): … … 72 90 def test_interswitch_form(self): 73 91 # Manager can access InterswitchForm 74 self.browser.getLink("Pay via Interswitch", index=0).click() 75 # The total amount to be processed by Interswitch 76 # has been reduced by the Interswitch fee of 150 Nairas 92 self.browser.getLink("Pay via Interswitch CollegePAY", index=0).click() 77 93 self.assertMatches('...<input type="hidden" name="pay_item_id" />...', 78 94 self.browser.contents) … … 101 117 self.assertEqual(self.student['payments'][value].gateway_amt, 0.0) 102 118 self.browser.getLink(value).click() 103 self.browser.getLink("Pay via Interswitch ", index=0).click()119 self.browser.getLink("Pay via Interswitch CollegePAY", index=0).click() 104 120 # Split amounts have been set. 105 121 self.assertEqual(self.student['payments'][value].provider_amt, 0.0) … … 113 129 def test_interswitch_form_ticket_expired(self): 114 130 # Manager can access InterswitchForm 115 self.browser.getLink("Pay via Interswitch ", index=0).click()131 self.browser.getLink("Pay via Interswitch CollegePAY", index=0).click() 116 132 self.assertMatches('...<input type="hidden" name="pay_item_id" />...', 117 133 self.browser.contents) … … 125 141 self.payment.creation_date -= delta 126 142 self.browser.open(self.payment_url) 127 self.browser.getLink("Pay via Interswitch ", index=0).click()143 self.browser.getLink("Pay via Interswitch CollegePAY", index=0).click() 128 144 self.assertMatches( 129 145 '...This payment ticket is too old. Please create a new ticket...', … … 132 148 self.payment.creation_date += delta 133 149 self.browser.open(self.payment_url) 134 self.browser.getLink("Pay via Interswitch ", index=0).click()150 self.browser.getLink("Pay via Interswitch CollegePAY").click() 135 151 self.assertMatches('...Total Amount Authorized:...', 136 152 self.browser.contents) … … 140 156 # We should not have TZ data in timestamps processed, but it looks 141 157 # like we get some with imports :-/ 142 self.browser.getLink("Pay via Interswitch ", index=0).click()158 self.browser.getLink("Pay via Interswitch CollegePAY", index=0).click() 143 159 delta = timedelta(days=8) 144 160 self.payment.creation_date -= delta … … 147 163 self.payment.creation_date) 148 164 self.browser.open(self.payment_url) 149 self.browser.getLink("Pay via Interswitch ", index=0).click()165 self.browser.getLink("Pay via Interswitch CollegePAY", index=0).click() 150 166 self.assertMatches( 151 167 '...This payment ticket is too old. Please create a new ticket...', … … 154 170 self.payment.creation_date += delta 155 171 self.browser.open(self.payment_url) 156 self.browser.getLink("Pay via Interswitch ", index=0).click()157 self.assertMatches('...Total Amount Authorized:...', 158 self.browser.contents) 159 160 @external_test 172 self.browser.getLink("Pay via Interswitch CollegePAY").click() 173 self.assertMatches('...Total Amount Authorized:...', 174 self.browser.contents) 175 176 @external_test_1 161 177 def test_query_interswitch_SOAP(self): 162 178 host = 'webpay.interswitchng.com' … … 176 192 'ZIB|WEB|ABAL|3-11-2015|021336:000457580882' in log) 177 193 178 @external_test 194 @external_test_1 179 195 def test_query_interswitch_JSON(self): 180 196 host = 'webpay.interswitchng.com' … … 209 225 "u'LeadBankName': None}" in log) 210 226 227 # PAYDirect tests 228 229 def create_booking(self, p_id): 230 xml="""\ 231 <?xml version="1.0" encoding="utf-8"?> 232 <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 233 <soap:Body> 234 <CreateBooking xmlns="http://interswitchng.com/bookonhold"> 235 <ReservationRequest> 236 <MerchantId>%s</MerchantId> 237 <Bookings> 238 <Booking> 239 <ReferenceNumber>%s%s</ReferenceNumber> 240 <ResponseCode>01</ResponseCode> 241 <ResponseDescription>02</ResponseDescription> 242 <Description>My Description</Description> 243 <Amount>1000</Amount> 244 <DateBooked>2021-05-05</DateBooked> 245 <DateExpired>2025-05-05</DateExpired> 246 <FirstName>Dummy</FirstName> 247 <LastName>Student</LastName> 248 <Status>string</Status> 249 <PaymentStatus>string</PaymentStatus> 250 <PaymentReference>string</PaymentReference> 251 <ChannelName>04</ChannelName> 252 <TerminalId>05</TerminalId> 253 <Location>string</Location> 254 <PaymentDate>2020-05-05</PaymentDate> 255 <PaymentMethod>string</PaymentMethod> 256 <Email>aa@aa.aa</Email> 257 <ItemCode>01</ItemCode> 258 </Booking> 259 </Bookings> 260 </ReservationRequest> 261 </CreateBooking> 262 </soap:Body> 263 </soap:Envelope>""" % (MERCHANT_ID, MERCHANT_ID, p_id[1:]) 264 265 SOAP_post("http://interswitchng.com/bookonhold/CreateBooking",xml, 266 PAYDIRECT_HOST, PAYDIRECT_URL, True) 267 268 @external_test_2 269 def test_get_SOAP_response_paydirect(self): 270 p_id = 'p6021570467807' 271 self.create_booking(p_id) 272 result_xml = get_SOAP_response_paydirect( 273 MERCHANT_ID, p_id, PAYDIRECT_HOST, PAYDIRECT_URL, True) 274 doc=parseString(result_xml) 275 status=doc.getElementsByTagName('PaymentStatus')[0].firstChild.data 276 amount=doc.getElementsByTagName('Amount')[0].firstChild 277 self.assertEqual(status, 'Pending') 278 self.assertEqual(amount, None) 279 p_id = 'p5812734587097' 280 result_xml = get_SOAP_response_paydirect(MERCHANT_ID, p_id, PAYDIRECT_HOST, PAYDIRECT_URL, True) 281 doc=parseString(result_xml) 282 self.assertEqual(doc.getElementsByTagName('PaymentStatus'), []) 283 284 @external_test_2 285 def test_paydirect(self): 286 # Manager can access InterswitchForm 287 self.browser.getLink("Pay via Interswitch PAYDirect").click() 288 self.assertMatches('...Total Amount Authorized:...', 289 self.browser.contents) 290 self.assertEqual(self.student.current_mode, 'ug_ft') 291 # Create school fee ticket for returning students. Payment is made 292 # for next session. 293 current_payment_key = self.student['payments'].keys()[0] 294 self.certificate.study_mode = u'ug_pt' 295 IWorkflowState(self.student).setState('returning') 296 configuration = createObject('waeup.SessionConfiguration') 297 configuration.academic_session = 2005 298 self.app['configuration'].addSessionConfiguration(configuration) 299 self.browser.open(self.payments_path + '/addop') 300 self.browser.getControl(name="form.p_category").value = ['schoolfee'] 301 self.browser.getControl("Create ticket").click() 302 self.browser.open(self.payments_path) 303 ctrl = self.browser.getControl(name='val_id') 304 value = ctrl.options[1] 305 self.assertEqual(self.student['payments'][value].provider_amt, 0.0) 306 self.assertEqual(self.student['payments'][value].gateway_amt, 0.0) 307 self.browser.getLink(value).click() 308 self.browser.getLink("Pay via Interswitch PAYDirect").click() 309 # Split amounts have been set. 310 self.assertEqual(self.student['payments'][value].provider_amt, 0.0) 311 self.assertEqual(self.student['payments'][value].gateway_amt, 300.0) 312 # Reference number has not yet been saved but can be seen in browser 313 self.assertEqual(self.student['payments'][value].r_pay_reference, None) 314 ref_number = '%s%s' % (MERCHANT_ID,value[1:]) 315 self.assertTrue(ref_number in self.browser.contents) 316 self.browser.getControl("Requery").click() 317 self.assertTrue('Your payment %s was not found.' % value in self.browser.contents) 318 self.create_booking(value) 319 self.browser.getLink("Pay via Interswitch PAYDirect").click() 320 self.browser.getControl("Requery").click() 321 self.assertTrue('pending' in self.browser.contents) 322 # Reference number has still not been saved because the element was empty 323 self.assertEqual(self.student['payments'][value].r_pay_reference, None) 324 # Here we have to stop testing because we cannot create completed bookings 325 326 # Students can download reference number slip 327 self.browser.getLink("Pay via Interswitch PAYDirect").click() 328 self.browser.getLink("Download reference number slip").click() 329 self.assertEqual(self.browser.headers['Status'], '200 Ok') 330 self.assertEqual(self.browser.headers['Content-Type'], 'application/pdf') 331 path = os.path.join(samples_dir(), 'refnumberslip.pdf') 332 open(path, 'wb').write(self.browser.contents) 333 print "Sample PDF refnumberslip.pdf written to %s" % path 334 211 335 class InterswitchTestsApplicants(ApplicantsFullSetup): 212 336 """Tests for the Interswitch payment gateway. … … 241 365 self.browser.contents) 242 366 # Manager can access InterswitchForm 243 self.browser.getLink("Pay via Interswitch ", index=0).click()367 self.browser.getLink("Pay via Interswitch CollegePAY", index=0).click() 244 368 self.assertMatches('...Total Amount Authorized:...', 245 369 self.browser.contents)
Note: See TracChangeset for help on using the changeset viewer.