- Timestamp:
- 7 Dec 2012, 16:37:15 (12 years ago)
- Location:
- main/waeup.kwarapoly/trunk/src/waeup/kwarapoly/interswitch
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.kwarapoly/trunk/src/waeup/kwarapoly/interswitch/browser.py
r9751 r9789 21 21 from zope.interface import Interface 22 22 from zope.component import getUtility, queryAdapter 23 from kofacustom.nigeria.interswitch.helpers import query_interswitch 23 from kofacustom.nigeria.interswitch.browser import ( 24 InterswitchPaymentRequestWebservicePageStudent 25 ) 24 26 from waeup.kofa.browser.layout import KofaPage, UtilityView 25 27 from waeup.kofa.interfaces import IKofaUtils 26 28 from waeup.kofa.utils.helpers import to_timezone 27 from waeup.kofa.students.viewlets import ApprovePaymentActionButton as APABStudent28 from waeup.kofa.applicants.viewlets import ApprovePaymentActionButton as APABApplicant29 29 from waeup.kwarapoly.students.interfaces import ICustomStudentOnlinePayment 30 30 from waeup.kwarapoly.applicants.interfaces import ICustomApplicantOnlinePayment … … 38 38 INSTITUTION_NAME = 'KwaraPoly' 39 39 CURRENCY = '566' 40 GATEWAY_AMT = 300.0 40 41 #QUERY_URL = 'https://webpay.interswitchng.com/paydirect/services/TransactionQueryURL.aspx' 41 42 #QUERY_URL = 'https://testwebpay.interswitchng.com/test_paydirect/services/TransactionQueryURL.aspx' … … 58 59 view.request, Interface, name='waeup.kwarapoly.interswitch') 59 60 return static['interswitch_verve_mastercard.gif']() 60 61 class InterswitchActionButtonStudent(APABStudent):62 grok.order(1)63 grok.context(ICustomStudentOnlinePayment)64 grok.require('waeup.payStudent')65 icon = 'actionicon_pay.png'66 text = _('CollegePAY')67 target = 'goto_interswitch'68 69 @property70 def target_url(self):71 if self.context.p_state != 'unpaid':72 return ''73 return self.view.url(self.view.context, self.target)74 75 class InterswitchActionButtonApplicant(APABApplicant):76 grok.order(1)77 grok.context(ICustomApplicantOnlinePayment)78 grok.require('waeup.payApplicant')79 icon = 'actionicon_pay.png'80 text = _('CollegePAY')81 target = 'goto_interswitch'82 83 @property84 def target_url(self):85 if self.context.p_state != 'unpaid':86 return ''87 return self.view.url(self.view.context, self.target)88 89 class InterswitchRequestWebserviceActionButtonStudent(APABStudent):90 grok.order(2)91 grok.context(ICustomStudentOnlinePayment)92 grok.require('waeup.payStudent')93 icon = 'actionicon_call.png'94 text = _('Requery CollegePAY')95 target = 'request_webservice'96 97 class InterswitchRequestWebserviceActionButtonApplicant(APABApplicant):98 grok.order(2)99 grok.context(ICustomApplicantOnlinePayment)100 grok.require('waeup.payApplicant')101 icon = 'actionicon_call.png'102 text = _('Requery CollegePAY')103 target = 'request_webservice'104 61 105 62 class InterswitchPageStudent(KofaPage): … … 149 106 xmldict['provider_bank_id'] = PROVIDER_BANK_ID 150 107 xmldict['provider_item_name'] = PROVIDER_ITEM_NAME 151 xmldict['provider_amt'] = 100 * 1200152 108 # Institution data 153 109 xmldict['institution_acct'] = "0000000000000" … … 155 111 xmldict['institution_item_name'] = self.category 156 112 xmldict['institution_name'] = INSTITUTION_NAME 157 xmldict['institution_amt'] = 100 * (self.context.amount_auth -300)158 xmldict['dalash_amt'] = 0159 113 self.pay_item_id = '000' 160 114 if self.context.p_category == 'schoolfee': 115 provider_amt = 1200.0 116 xmldict['provider_amt'] = 100 * provider_amt 161 117 self.pay_item_id = '101' 162 # Dalash data 163 xmldict['dalash_amt'] = 100 * 1800 118 dalash_amt = 1800.0 119 xmldict['dalash_amt'] = 100 * dalash_amt 120 xmldict['institution_amt'] = 100 * ( 121 self.context.amount_auth - provider_amt - 122 GATEWAY_AMT - dalash_amt) 164 123 if xmldict['faculty'] in ('CPGS',): 165 124 xmldict['institution_acct'] = "1771180233" … … 178 137 xmldict['institution_acct'] = "2013910271" 179 138 xmldict['institution_bank_id'] = '8' 180 xmldict['institution_amt'] = 100 * (181 self.context.amount_auth - 1200 - 300 - 1800)182 139 183 140 elif 'maintenance' in self.context.p_category: … … 185 142 xmldict['institution_acct'] = "0039050937" 186 143 xmldict['institution_bank_id'] = '31' 144 xmldict['institution_amt'] = 100 * ( 145 self.context.amount_auth - GATEWAY_AMT) 146 dalash_amt = 0.0 147 provider_amt = 0.0 187 148 188 149 hashargs = ( … … 197 158 # Interswitch amount is not part of the xml data 198 159 199 if self.context.p_category in ('schoolfee', 'co1', 'co2', 'co3'):160 if self.context.p_category == 'schoolfee': 200 161 xmltext = """<payment_item_detail> 201 162 <item_details detail_ref="%(detail_ref)s" college="%(institution_name)s" department="%(department)s" faculty="%(faculty)s"> 202 163 <item_detail item_id="1" item_name="%(institution_item_name)s" item_amt="%(institution_amt)d" bank_id="%(institution_bank_id)s" acct_num="%(institution_acct)s" /> 203 <item_detail item_id="2" item_name="Dalash" item_amt="%(dalash_amt) s" bank_id="117" acct_num="1013196791" />164 <item_detail item_id="2" item_name="Dalash" item_amt="%(dalash_amt)d" bank_id="117" acct_num="1013196791" /> 204 165 <item_detail item_id="3" item_name="%(provider_item_name)s" item_amt="%(provider_amt)d" bank_id="%(provider_bank_id)s" acct_num="%(provider_acct)s" /> 205 166 </item_details> … … 214 175 215 176 self.xml_data = """<input type="hidden" name="xml_data" value='%s' />""" % xmltext 177 self.context.provider_amt = provider_amt 178 self.context.gateway_amt = GATEWAY_AMT 179 self.context.thirdparty_amt = dalash_amt 216 180 return 217 181 218 class InterswitchPageApplicant(KofaPage): 219 """ View which sends a POST request to the Interswitch 220 CollegePAY payment gateway. 221 """ 222 grok.context(ICustomApplicantOnlinePayment) 223 grok.require('waeup.payApplicant') 224 grok.template('applicant_goto_interswitch') 225 grok.name('goto_interswitch') 226 label = _('Submit data to CollegePAY (Interswitch Payment Gateway)') 227 submit_button = _('Submit') 228 action = POST_ACTION 229 site_name = SITE_NAME 230 currency = CURRENCY 231 pay_item_id = '' 232 product_id = PRODUCT_ID 233 234 def interswitch_img_url(self): 235 return interswitch_img_url(self) 236 237 def update(self): 238 if self.context.p_state != 'unpaid': 239 self.flash(_("Payment ticket can't be re-send to CollegePAY.")) 240 self.redirect(self.url(self.context, '@@index')) 241 return 242 if self.context.__parent__.__parent__.expired \ 243 and self.context.__parent__.__parent__.strict_deadline: 244 self.flash(_("Payment ticket can't be send to CollegePAY. " 245 "Application period has expired.")) 246 self.redirect(self.url(self.context, '@@index')) 247 return 248 self.applicant = self.context.__parent__ 249 self.amount_auth = 100 * self.context.amount_auth 250 xmldict = {} 251 self.category = getUtility(IKofaUtils).PAYMENT_CATEGORIES[self.context.p_category] 252 tz = getUtility(IKofaUtils).tzinfo 253 self.local_date_time = to_timezone( 254 self.context.creation_date, tz).strftime("%Y-%m-%d %H:%M:%S %Z") 255 self.site_redirect_url = self.url(self.context, 'request_webservice') 256 xmldict['detail_ref'] = self.context.p_id 257 # Provider data 258 xmldict['provider_amt'] = 100 * 500 259 xmldict['provider_acct'] = PROVIDER_ACCT 260 xmldict['provider_bank_id'] = PROVIDER_BANK_ID 261 xmldict['provider_item_name'] = PROVIDER_ITEM_NAME 262 # Institution data 263 xmldict['institution_amt'] = 100 * (self.context.amount_auth - 500 - 150) 264 xmldict['institution_acct'] = '0' 265 xmldict['institution_bank_id'] = '0' 266 xmldict['institution_item_name'] = self.context.p_category 267 xmldict['institution_name'] = INSTITUTION_NAME 268 # Interswitch amount is not part of the xml data 269 xmltext = """<payment_item_detail> 270 <item_details detail_ref="%(detail_ref)s" college="%(institution_name)s"> 271 <item_detail item_id="1" item_name="%(institution_item_name)s" item_amt="%(institution_amt)d" bank_id="%(institution_bank_id)s" acct_num="%(institution_acct)s" /> 272 <item_detail item_id="2" item_name="%(provider_item_name)s" item_amt="%(provider_amt)d" bank_id="%(provider_bank_id)s" acct_num="%(provider_acct)s" /> 273 </item_details> 274 </payment_item_detail>""" % xmldict 275 self.xml_data = """<input type="hidden" name="xml_data" value='%s' />""" % xmltext 276 return 277 278 279 class InterswitchPaymentRequestWebservicePageStudent(UtilityView, grok.View): 182 class InterswitchPaymentRequestWebservicePageStudent( 183 InterswitchPaymentRequestWebservicePageStudent): 280 184 """ Request webservice view for the CollegePAY gateway 281 185 """ 282 186 grok.context(ICustomStudentOnlinePayment) 283 grok.name('request_webservice') 284 grok.require('waeup.payStudent') 285 286 def update(self): 287 if self.context.p_state == 'paid': 288 self.flash(_('This ticket has already been paid.')) 289 return 290 student = self.context.student 291 success, msg, log = query_interswitch( 292 self.context, PRODUCT_ID, HOST, URL) 293 student.writeLogMessage(self, log) 294 if not success: 295 self.flash(msg) 296 return 297 success, msg, log = self.context.doAfterStudentPayment() 298 if log is not None: 299 student.writeLogMessage(self, log) 300 self.flash(msg) 301 return 302 303 def render(self): 304 self.redirect(self.url(self.context, '@@index')) 305 return 306 307 class InterswitchPaymentRequestWebservicePageApplicant(UtilityView, grok.View): 308 """ Request webservice view for the CollegePAY gateway 309 """ 310 grok.context(ICustomApplicantOnlinePayment) 311 grok.name('request_webservice') 312 grok.require('waeup.payApplicant') 313 314 def update(self): 315 if self.context.p_state == 'paid': 316 self.flash(_('This ticket has already been paid.')) 317 return 318 applicant = self.context.__parent__ 319 success, msg, log = query_interswitch( 320 self.context, PRODUCT_ID, HOST, URL) 321 applicant.writeLogMessage(self, log) 322 if not success: 323 self.flash(msg) 324 return 325 success, msg, log = self.context.doAfterApplicantPayment() 326 if log is not None: 327 applicant.writeLogMessage(self, log) 328 self.flash(msg) 329 return 330 331 def render(self): 332 self.redirect(self.url(self.context, '@@index')) 333 return 187 product_id = PRODUCT_ID 188 gateway_host = HOST 189 gateway_url = URL -
main/waeup.kwarapoly/trunk/src/waeup/kwarapoly/interswitch/tests.py
r9737 r9789 16 16 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 17 ## 18 import os 18 19 import grok 19 20 from hurry.workflow.interfaces import IWorkflowState … … 31 32 # If you enable this, please make sure the external services 32 33 # do exist really and are not bothered by being spammed by a test programme. 33 EXTERNAL_TESTS = False34 EXTERNAL_TESTS = True 34 35 35 36 def external_test(func): … … 84 85 self.browser.contents) 85 86 ctrl = self.browser.getControl(name='val_id') 86 value = ctrl.options[0]87 self.browser.getLink( value).click()87 self.value = ctrl.options[0] 88 self.browser.getLink(self.value).click() 88 89 self.assertMatches('...Amount Authorized...', 89 90 self.browser.contents) … … 107 108 def test_interswitch_form(self): 108 109 # Manager can access InterswitchForm 110 self.assertEqual(self.student['payments'][self.value].provider_amt, 0.0) 111 self.assertEqual(self.student['payments'][self.value].gateway_amt, 0.0) 112 self.assertEqual(self.student['payments'][self.value].thirdparty_amt, 0.0) 109 113 self.browser.getLink("CollegePAY", index=0).click() 114 # Split amounts have been set. 115 self.assertEqual(self.student['payments'][self.value].provider_amt, 1200.0) 116 self.assertEqual(self.student['payments'][self.value].gateway_amt, 300.0) 117 self.assertEqual(self.student['payments'][self.value].thirdparty_amt, 1800.0) 110 118 self.assertMatches('...Total Amount Authorized:...', 111 119 self.browser.contents) … … 162 170 # Manager can access InterswitchForm 163 171 self.browser.getLink("CollegePAY", index=0).click() 172 # Split amounts have been set. 173 self.assertEqual(self.student['payments'][value].provider_amt, 0.0) 174 self.assertEqual(self.student['payments'][value].thirdparty_amt, 0.0) 175 self.assertEqual(self.student['payments'][value].gateway_amt, 300.0) 164 176 # The total amount to be processed by Interswitch 165 177 # has been reduced by the Interswitch fee of 150 Nairas … … 188 200 # Manager can access InterswitchForm 189 201 self.browser.getLink("CollegePAY", index=0).click() 202 # Split amounts have been set. 203 self.assertEqual(self.student['payments'][self.value].provider_amt, 1200.0) 204 self.assertEqual(self.student['payments'][self.value].gateway_amt, 300.0) 205 self.assertEqual(self.student['payments'][self.value].thirdparty_amt, 1800.0) 190 206 self.assertMatches('...<input type="hidden" name="pay_item_id" value="101" />...', 191 207 self.browser.contents) … … 204 220 '...item_name="BT Education" item_amt="120000" bank_id="117" acct_num="1010764827"...', 205 221 self.browser.contents) 206 207 # @external_test208 # def test_callback(self):209 210 # Manager can call callback manually211 # self.browser.open(self.callback_url(self.payment_url, 'XX', '300'))212 # self.assertMatches('...Unsuccessful callback: Something went wrong...',213 # self.browser.contents)214 # self.assertMatches('...Failed...',215 # self.browser.contents)216 # self.browser.open(self.payment_url + '/isw_callback')217 # self.assertMatches('...Unsuccessful callback: Incomplete query string...',218 # self.browser.contents)219 # self.assertMatches('...Failed...',220 # self.browser.contents)221 # self.browser.open(self.callback_url(self.payment_url, '00', '300000'))222 # self.assertMatches('...Wrong amount...',223 # self.browser.contents)224 # self.browser.open(self.callback_url(self.payment_url, '00', '4000000'))225 # self.assertMatches('...Valid callback received...',226 # self.browser.contents)227 222 228 223 @external_test 229 224 def test_webservice(self): 230 225 # First we have open InterswitchPageStudent to set provider_amt 226 # and gateway_amt 227 self.browser.open(self.payment_url + '/goto_interswitch') 228 # Now we can call the webservice 231 229 self.browser.open(self.payment_url + '/request_webservice') 232 230 self.assertMatches('...Unsuccessful callback...', … … 242 240 self.assertEqual(results[0].p_state, 'failed') 243 241 244 class InterswitchTestsApplicants(ApplicantsFullSetup): 245 """Tests for the Interswitch payment gateway. 246 """ 247 248 layer = FunctionalLayer 249 250 def setUp(self): 251 super(InterswitchTestsApplicants, self).setUp() 252 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') 253 self.browser.open(self.manage_path) 254 #IWorkflowState(self.student).setState('started') 255 super(InterswitchTestsApplicants, self).fill_correct_values() 256 self.applicantscontainer.application_fee = 1000.0 257 self.browser.getControl(name="form.nationality").value = ['NG'] 258 self.browser.getControl(name="transition").value = ['start'] 259 self.browser.getControl("Save").click() 260 self.browser.getControl("Add online").click() 261 self.assertMatches('...ticket created...', 262 self.browser.contents) 263 #ctrl = self.browser.getControl(name='val_id') 264 #value = ctrl.options[0] 265 #self.browser.getLink(value).click() 266 self.assertMatches('...Amount Authorized...', 267 self.browser.contents) 268 self.assertMatches( 269 '...<span>1000.0</span>...', 270 self.browser.contents) 271 self.payment_url = self.browser.url 272 273 274 def test_interswitch_form(self): 275 276 # Manager can access InterswitchForm 277 self.browser.getLink("CollegePAY", index=0).click() 278 self.assertMatches('...Total Amount Authorized:...', 279 self.browser.contents) 280 self.assertMatches( 281 '...<input type="hidden" name="amount" value="100000.0" />...', 282 self.browser.contents) 283 284 @external_test 285 def test_webservice(self): 286 242 # Let's replace the p_id with a valid p_id of the Kwarapoly 243 # live system. This is definitely not an appropriate 244 # solution for testing, but we have no choice since 245 # Interswitch doesn't provide any interface 246 # for testing. 247 payment = self.student['payments'][self.value] 248 payment.p_id = 'p3543612043224' 287 249 self.browser.open(self.payment_url + '/request_webservice') 288 self.assertMatches('... Unsuccessful callback...',289 self.browser.contents) 290 # The payment is now in state failed 250 self.assertMatches('...Callback amount does not match...', 251 self.browser.contents) 252 # The payment is now in state failed ... 291 253 self.assertMatches('...<span>Failed</span>...', 292 254 self.browser.contents) 255 # Let's replace the amount autorized with the amount of the 256 # live system payment 257 payment.amount_auth = payment.r_amount_approved 258 self.browser.open(self.payment_url + '/request_webservice') 259 self.assertMatches('...Successful payment...', 260 self.browser.contents) 261 # The payment is now in state paid ... 262 self.assertMatches('...<span>Paid</span>...', 263 self.browser.contents) 264 # ... and the catalog has been updated 265 cat = getUtility(ICatalog, name='payments_catalog') 266 results = list( 267 cat.searchResults(p_state=('paid', 'paid'))) 268 self.assertEqual(len(results), 1) 269 self.assertEqual(results[0].p_state, 'paid') 270 # Approval is logged in students.log ... 271 logfile = os.path.join( 272 self.app['datacenter'].storage, 'logs', 'students.log') 273 logcontent = open(logfile).read() 274 self.assertTrue( 275 'zope.mgr - ' 276 'waeup.kwarapoly.interswitch.browser.InterswitchPaymentRequestWebservicePageStudent - ' 277 'W1000000 - successful schoolfee payment: p3543612043224\n' 278 in logcontent) 279 # ... and in payments.log 280 logfile = os.path.join( 281 self.app['datacenter'].storage, 'logs', 'payments.log') 282 logcontent = open(logfile).read() 283 self.assertTrue( 284 '"zope.mgr",W1000000,p3543612043224,schoolfee,' 285 '52100.0,00,1200.0,300.0,1800.0,,,\n' 286 in logcontent)
Note: See TracChangeset for help on using the changeset viewer.