Index: main/waeup.uniben/trunk/src/waeup/uniben/applicants/interfaces.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/applicants/interfaces.py	(revision 8424)
+++ main/waeup.uniben/trunk/src/waeup/uniben/applicants/interfaces.py	(revision 8430)
@@ -269,2 +269,12 @@
 
     """
+
+    def doAfterApplicantPayment():
+        """Process applicant after payment was made.
+
+        """
+
+    def approveApplicantPayment():
+        """Approve payment and process applicant.
+
+        """
Index: main/waeup.uniben/trunk/src/waeup/uniben/applicants/utils.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/applicants/utils.py	(revision 8424)
+++ main/waeup.uniben/trunk/src/waeup/uniben/applicants/utils.py	(revision 8430)
@@ -25,12 +25,4 @@
 from waeup.uniben.interfaces import MessageFactory as _
 
-
-def actions_after_applicant_payment(applicant, view):
-    wf_info = IWorkflowInfo(applicant)
-    try:
-        wf_info.fireTransition('pay')
-    except InvalidTransitionError:
-        view.flash('Error: %s' % sys.exc_info()[1])
-        return
 
 class ApplicantsUtils(ApplicantsUtils):
Index: main/waeup.uniben/trunk/src/waeup/uniben/etranzact/browser.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/etranzact/browser.py	(revision 8424)
+++ main/waeup.uniben/trunk/src/waeup/uniben/etranzact/browser.py	(revision 8430)
@@ -22,9 +22,7 @@
 import grok
 from waeup.kofa.browser.layout import KofaPage, UtilityView
-from waeup.kofa.applicants.viewlets import RequestCallbackActionButton as RCABApplicant
-from waeup.kofa.students.viewlets import RequestCallbackActionButton as RCABStudent
+from waeup.kofa.students.viewlets import ApprovePaymentActionButton as APABStudent
+from waeup.kofa.applicants.viewlets import ApprovePaymentActionButton as APABApplicant
 from waeup.uniben.interfaces import MessageFactory as _
-from waeup.uniben.students.utils import actions_after_student_payment
-from waeup.uniben.applicants.utils import actions_after_applicant_payment
 from waeup.uniben.students.interfaces import ICustomStudentOnlinePayment
 from waeup.uniben.applicants.interfaces import ICustomApplicantOnlinePayment
@@ -35,6 +33,6 @@
 QUERY_URL =   'http://demo.etranzact.com:8080/WebConnect/queryPayoutletTransaction.jsp'
 
-def query_etranzact(confirmation_number, user, payment, view):
-    ob_class = view.__implemented__.__name__
+def query_etranzact(confirmation_number, payment):
+    
     postdict = {}
     postdict['TERMINAL_ID'] = TERMINAL_ID
@@ -45,30 +43,28 @@
         f = urllib.urlopen(url=QUERY_URL, data=data)
         success = f.read()
-        user.loggerInfo(ob_class, 'callback received: %s' % success)
         if 'COL1' not in success:
-            view.flash(_('Invalid or unsuccessful callback: ${a}',
-                mapping = {'a': success}))
-            user.loggerInfo(ob_class, 'invalid callback: %s' % payment.p_id)
+            msg = _('Invalid or unsuccessful callback: ${a}',
+                mapping = {'a': success})
+            log = 'invalid callback for payment %s: %s' % (payment.p_id, success)
             payment.p_state = 'failed'
-            return False
+            return False, msg, log
         success = success.replace('%20',' ').split('&')
         # We expect at least two parameters
         if len(success) < 2:
-            view.flash(_('Invalid callback: ${a}',
-                mapping = {'a': success}))
-            user.loggerInfo(ob_class, 'invalid callback: %s' % payment.p_id)
+            msg = _('Invalid callback: ${a}', mapping = {'a': success})
+            log = 'invalid callback for payment %s: %s' % (payment.p_id, success)
             payment.p_state = 'failed'
-            return False
+            return False, msg, log
         try:
             success_dict = dict([tuple(i.split('=')) for i in success])
         except ValueError:
-            view.flash(_('Invalid callback: ${a}',
-                mapping = {'a': success}))
-            user.loggerInfo(ob_class, 'invalid callback: %s' % payment.p_id)
+            msg = _('Invalid callback: ${a}', mapping = {'a': success})
+            log = 'invalid callback for payment %s: %s' % (payment.p_id, success)
             payment.p_state = 'failed'
-            return False
+            return False, msg, log
     except IOError:
-        view.flash(_('eTranzact IOError'))
-        return False
+        msg = _('eTranzact IOError')
+        log = 'eTranzact IOError'
+        return False, msg, log
     payment.r_code = u'ET'
     payment.r_desc = u'%s' % success_dict.get('TRANS_DESCR')
@@ -77,9 +73,8 @@
     payment.r_pay_reference = u'%s' % success_dict.get('RECEIPT_NO')
     if payment.r_amount_approved != payment.amount_auth:
-        view.flash(_('Wrong amount'))
-        user.loggerInfo(ob_class, 'successful callback but wrong amount: %s'
-            % payment.p_id)
+        msg = _('Wrong amount')
+        log = 'wrong callback for payment %s: %s' % (payment.p_id, success)
         payment.p_state = 'failed'
-        return False
+        return False, msg, log
     tcode = payment.p_id
     tcode = tcode[len(tcode)-8:len(tcode)]
@@ -87,19 +82,17 @@
     col1 = col1[len(col1)-8:len(col1)]
     if tcode != col1:
-        view.flash(_('Wrong transaction code'))
-        write_log_message(
-            view,'successful callback but wrong transaction code: %s'
-            % payment.p_id)
-        user.loggerInfo(ob_class, 'successful callback wrong transaction code: %s'
-            % payment.p_id)
+        msg = _('Wrong transaction code')
+        log = 'wrong callback for payment %s: %s' % (payment.p_id, success)
         payment.p_state = 'failed'
-        return False
-    user.loggerInfo(ob_class, 'successful callback: %s' % payment.p_id)
+        return False, msg, log
+    log = 'valid callback for payment %s: %s' % (payment.p_id, success)
+    msg = _('Successful callback received')
     payment.p_state = 'paid'
     payment.payment_date = datetime.now()
-    return True
+    return True, msg, log
 
-class EtranzactEnterPinActionButtonApplicant(RCABApplicant):
+class EtranzactEnterPinActionButtonApplicant(APABApplicant):
     grok.context(ICustomApplicantOnlinePayment)
+    grok.require('waeup.payApplicant')
     grok.order(3)
     icon = 'actionicon_call.png'
@@ -107,6 +100,7 @@
     target = 'enterpin'
 
-class EtranzactEnterPinActionButtonStudent(RCABStudent):
+class EtranzactEnterPinActionButtonStudent(APABStudent):
     grok.context(ICustomStudentOnlinePayment)
+    grok.require('waeup.payStudent')
     grok.order(3)
     icon = 'actionicon_call.png'
@@ -140,10 +134,18 @@
 
     def update(self, confirmation_number=None):
+        ob_class = self.__implemented__.__name__
         if self.context.p_state == 'paid':
             self.flash(_('This ticket has already been paid.'))
             return
         student = self.context.getStudent()
-        if query_etranzact(confirmation_number, student, self.context, self):
-            actions_after_student_payment(student, self.context, self)
+        success, msg, log = query_etranzact(confirmation_number,self.context)
+        student.loggerInfo(ob_class, log)
+        if not success:
+            self.flash(msg)
+            return
+        success, msg, log = self.context.doAfterStudentPayment()
+        if log is not None:
+            student.loggerInfo(ob_class, log)
+        self.flash(msg)
         return
 
@@ -160,10 +162,18 @@
 
     def update(self, confirmation_number=None):
+        ob_class = self.__implemented__.__name__
         if self.context.p_state == 'paid':
             self.flash(_('This ticket has already been paid.'))
             return
         applicant = self.context.__parent__
-        if query_etranzact(confirmation_number, applicant, self.context, self):
-            actions_after_applicant_payment(applicant, self)
+        success, msg, log = query_etranzact(confirmation_number,self.context)
+        applicant.loggerInfo(ob_class, log)
+        if not success:
+            self.flash(msg)
+            return
+        success, msg, log = self.context.doAfterApplicantPayment()
+        if log is not None:
+            applicant.loggerInfo(ob_class, log)
+        self.flash(msg)
         return
 
Index: main/waeup.uniben/trunk/src/waeup/uniben/etranzact/tests.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/etranzact/tests.py	(revision 8424)
+++ main/waeup.uniben/trunk/src/waeup/uniben/etranzact/tests.py	(revision 8430)
@@ -109,10 +109,8 @@
         configuration.application_fee = 1000.0
         self.app['configuration'].addSessionConfiguration(configuration)
+        self.browser.open(self.manage_path)
         self.browser.getControl("Add online").click()
         self.assertMatches('...ticket created...',
                            self.browser.contents)
-        ctrl = self.browser.getControl(name='val_id')
-        value = ctrl.options[0]
-        self.browser.getLink(value).click()
         self.assertMatches('...Amount Authorized...',
                            self.browser.contents)
Index: main/waeup.uniben/trunk/src/waeup/uniben/interswitch/browser.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/interswitch/browser.py	(revision 8424)
+++ main/waeup.uniben/trunk/src/waeup/uniben/interswitch/browser.py	(revision 8430)
@@ -32,6 +32,4 @@
 from waeup.uniben.students.interfaces import ICustomStudentOnlinePayment
 from waeup.uniben.applicants.interfaces import ICustomApplicantOnlinePayment
-from waeup.uniben.students.utils import actions_after_student_payment
-from waeup.uniben.applicants.utils import actions_after_applicant_payment
 from waeup.uniben.interfaces import MessageFactory as _
 
@@ -91,14 +89,11 @@
     return response
 
-def query_interswitch(user, payment, view):
-    ob_class = view.__implemented__.__name__
+def query_interswitch(payment):
     sr = get_SOAP_response(PRODUCT_ID, payment.p_id)
-    user.loggerInfo(ob_class, 'callback received: %s' % sr)
     wlist = sr.split(':')
     if len(wlist) != 7:
-        view.flash(_('Invalid callback: ${a}',
-            mapping = {'a': wlist}))
-        user.loggerInfo(ob_class,'invalid callback: %s' % payment.p_id)
-        return False
+        msg = _('Invalid callback: ${a}', mapping = {'a': sr})
+        log = 'invalid callback for payment %s: %s' % (payment.p_id, sr)
+        return False, msg, log
     payment.r_code = wlist[0]
     payment.r_desc = wlist[1]
@@ -107,28 +102,28 @@
     payment.r_pay_reference = wlist[5]
     if payment.r_code != '00':
-        view.flash(_('Unsuccessful callback: ${a}', mapping = {'a': wlist[1]}))
-        user.loggerInfo(ob_class,'unsuccessful callback: %s' % payment.p_id)
+        msg = _('Unsuccessful callback: ${a}', mapping = {'a': sr})
+        log = 'usuccessful callback for payment %s: %s' % (payment.p_id, sr)
         payment.p_state = 'failed'
-        return False
+        return False, msg, log
     if payment.r_amount_approved != payment.amount_auth:
-        view.flash(_('Wrong amount'))
-        user.loggerInfo(ob_class,'successful callback but wrong amount: %s'
-            % payment.p_id)
+        msg = _('Callback amount does not match.')
+        log = 'wrong callback for payment %s: %s' % (payment.p_id, sr)
         payment.p_state = 'failed'
-        return False
+        return False, msg, log
     if wlist[4] != payment.p_id:
-        view.flash(_('Wrong transaction id'))
-        user.loggerInfo(ob_class,'successful callback but wrong transaction id: %s'
-            % payment.p_id)
+        msg = _('Callback transaction id does not match.')
+        log = 'wrong callback for payment %s: %s' % (payment.p_id, sr)
         payment.p_state = 'failed'
-        return False
-    user.loggerInfo(ob_class,'successful callback: %s' % payment.p_id)
+        return False, msg, log
     payment.p_state = 'paid'
     payment.payment_date = datetime.now()
-    return True
+    msg = _('Successful callback received')
+    log = 'valid callback for payment %s: %s' % (payment.p_id, sr)
+    return True, msg, log
 
 class InterswitchActionButtonStudent(APABStudent):
     grok.order(1)
     grok.context(ICustomStudentOnlinePayment)
+    grok.require('waeup.payStudent')
     icon = 'actionicon_pay.png'
     text = _('CollegePAY')
@@ -144,4 +139,5 @@
     grok.order(1)
     grok.context(ICustomApplicantOnlinePayment)
+    grok.require('waeup.payApplicant')
     icon = 'actionicon_pay.png'
     text = _('CollegePAY')
@@ -175,4 +171,5 @@
     grok.order(2)
     grok.context(ICustomStudentOnlinePayment)
+    grok.require('waeup.payStudent')
     icon = 'actionicon_call.png'
     text = _('Requery CollegePAY')
@@ -182,4 +179,5 @@
     grok.order(2)
     grok.context(ICustomApplicantOnlinePayment)
+    grok.require('waeup.payApplicant')
     icon = 'actionicon_call.png'
     text = _('Requery CollegePAY')
@@ -404,10 +402,18 @@
 
     def update(self):
+        ob_class = self.__implemented__.__name__
         if self.context.p_state == 'paid':
             self.flash(_('This ticket has already been paid.'))
             return
         student = self.context.getStudent()
-        if query_interswitch(student, self.context, self):
-            actions_after_student_payment(student, self.context, self)
+        success, msg, log = query_interswitch(self.context)
+        student.loggerInfo(ob_class, log)
+        if not success:
+            self.flash(msg)
+            return
+        success, msg, log = self.context.doAfterStudentPayment()
+        if log is not None:
+            student.loggerInfo(ob_class, log)
+        self.flash(msg)
         return
 
@@ -424,10 +430,18 @@
 
     def update(self):
+        ob_class = self.__implemented__.__name__
         if self.context.p_state == 'paid':
             self.flash(_('This ticket has already been paid.'))
             return
         applicant = self.context.__parent__
-        if query_interswitch(applicant, self.context, self):
-            actions_after_applicant_payment(applicant, self)
+        success, msg, log = query_interswitch(self.context)
+        applicant.loggerInfo(ob_class, log)
+        if not success:
+            self.flash(msg)
+            return
+        success, msg, log = self.context.doAfterApplicantPayment()
+        if log is not None:
+            applicant.loggerInfo(ob_class, log)
+        self.flash(msg)
         return
 
Index: main/waeup.uniben/trunk/src/waeup/uniben/payments/interfaces.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/payments/interfaces.py	(revision 8424)
+++ main/waeup.uniben/trunk/src/waeup/uniben/payments/interfaces.py	(revision 8430)
@@ -40,4 +40,11 @@
         )
 
+    r_code = schema.TextLine(
+        title = _(u'Response Code'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
+
     r_desc = schema.TextLine(
         title = _(u'Response Description'),
@@ -47,13 +54,8 @@
         )
 
+    # Only defined in custom package
+
     r_pay_reference = schema.TextLine(
         title = _(u'Response Payment Reference'),
-        default = None,
-        required = False,
-        readonly = False,
-        )
-
-    r_code = schema.TextLine(
-        title = _(u'Response Code'),
         default = None,
         required = False,
Index: main/waeup.uniben/trunk/src/waeup/uniben/students/interfaces.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/students/interfaces.py	(revision 8424)
+++ main/waeup.uniben/trunk/src/waeup/uniben/students/interfaces.py	(revision 8430)
@@ -372,4 +372,15 @@
         readonly = True,
         )
+
+    def doAfterStudentPayment():
+        """Process student after payment was made.
+
+        """
+
+    def approveStudentPayment():
+        """Approve payment and process student.
+
+        """
+
 ICustomStudentOnlinePayment['p_level'].order = ICustomStudentOnlinePayment[
     'p_session'].order
Index: main/waeup.uniben/trunk/src/waeup/uniben/students/utils.py
===================================================================
--- main/waeup.uniben/trunk/src/waeup/uniben/students/utils.py	(revision 8424)
+++ main/waeup.uniben/trunk/src/waeup/uniben/students/utils.py	(revision 8430)
@@ -33,32 +33,4 @@
         return fee
     return 0.0
-
-def actions_after_student_payment(student, payment, view):
-    if payment.p_category == 'clearance':
-        # Create CLR access code
-        pin, error = create_accesscode('CLR',0,student.student_id)
-        if error:
-            view.flash(_('Valid callback received. ${a}',
-                mapping = {'a':error}))
-            return
-        payment.ac = pin
-    elif payment.p_category == 'schoolfee':
-        # Create SFE access code
-        pin, error = create_accesscode('SFE',0,student.student_id)
-        if error:
-            view.flash(_('Valid callback received. ${a}',
-                mapping = {'a':error}))
-            return
-        payment.ac = pin
-    elif payment.p_category == 'bed_allocation':
-        # Create HOS access code
-        pin, error = create_accesscode('HOS',0,student.student_id)
-        if error:
-            view.flash(_('Valid callback received. ${a}',
-                mapping = {'a':error}))
-            return
-        payment.ac = pin
-    view.flash(_('Valid callback received.'))
-    return
 
 class CustomStudentsUtils(StudentsUtils):
