Ignore:
Timestamp:
4 Nov 2015, 09:16:13 (9 years ago)
Author:
Henrik Bettermann
Message:

Implement Interswitch JSON transaction query. This webservice is
automatically used if a mac key is set in the request webservice
view.

Location:
main/kofacustom.nigeria/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • main/kofacustom.nigeria/trunk/CHANGES.txt

    r13260 r13387  
    55=====================
    66
    7 - no changes yet
     7- Implement Interswitch JSON transaction query. This webservice is
     8  automatically used if a mac key is set in the request webservice
     9  view.
    810
    9111.2 (2015-09-14)
  • main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/interswitch/browser.py

    r13197 r13387  
    8383    gateway_url = None
    8484    https = True
     85    mac = None
    8586
    8687    def update(self):
     
    9293            self.context, self.product_id,
    9394            self.gateway_host, self.gateway_url,
    94             self.https)
     95            self.https, self.mac)
    9596        student.writeLogMessage(self, log)
    9697        if not success:
     
    119120    gateway_url = None
    120121    https = True
     122    mac = None
    121123
    122124    def update(self):
     
    128130            self.context, self.product_id,
    129131            self.gateway_host, self.gateway_url,
    130             self.https)
     132            self.https, self.mac)
    131133        applicant.writeLogMessage(self, log)
    132134        if not success:
  • main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/interswitch/helpers.py

    r11914 r13387  
    2020from datetime import datetime
    2121import httplib
     22import hashlib
     23import json
     24from urllib import urlencode
    2225import grok
    2326from xml.dom.minidom import parseString
     
    4447    response = h.getresponse()
    4548    return response
     49
    4650
    4751def get_SOAP_response(product_id, transref, host, url, https):
     
    6468    return response
    6569
    66 def query_interswitch(payment, product_id, host, url, https=False):
     70
     71def get_JSON_response(product_id, transref, host, url, https, mac, amount):
     72    hashargs = product_id + transref + mac
     73    hashvalue = hashlib.sha512(hashargs).hexdigest()
     74    headers={
     75        'Content-Type':'text/xml; charset=utf-8',
     76        'Hash':hashvalue,
     77    }
     78    if https:
     79        h = httplib.HTTPSConnection(host)
     80    else:
     81        h = httplib.HTTPConnection(host)
     82    amount = int(100 * amount)
     83    args = {'productid': product_id,
     84            'transactionreference': transref,
     85            'amount': amount}
     86    url = '%s?' % url + urlencode(args)
     87    h.request("GET", url, headers=headers)
     88    response = h.getresponse()
     89    if response.status!=200:
     90        return {'error': 'Connection error (%s, %s)' % (response.status, response.reason)}
     91    jsonout = response.read()
     92    parsed_json = json.loads(jsonout)
     93    return parsed_json
     94
     95def query_interswitch_SOAP(payment, product_id, host, url, https):
    6796    sr = get_SOAP_response(product_id, payment.p_id, host, url, https)
    6897    if sr.startswith('Connection error'):
     
    110139    return True, msg, log
    111140
     141def query_interswitch(payment, product_id, host, url, https, mac):
     142    # If no mac mac key is given, fall back to deprecated SOAP method
     143    # (Uniben, AAUA, FCEOkene).
     144    if mac == None:
     145        return query_interswitch_SOAP(payment, product_id, host, url, https)
     146    jr = get_JSON_response(product_id, payment.p_id, host, url,
     147                           https, mac, payment.amount_auth)
     148    error = jr.get('error')
     149    if error:
     150        msg = log = error
     151        return False, msg, log
     152
     153    # A typical JSON response
     154    #  {u'SplitAccounts': [],
     155    #   u'MerchantReference':u'p4210665523377',
     156    #   u'PaymentReference':u'GTB|WEB|KPOLY|12-01-2015|013138',
     157    #   u'TransactionDate':u'2015-01-12T13:43:39.27',
     158    #   u'RetrievalReferenceNumber':u'000170548791',
     159    #   u'ResponseDescription': u'Approved Successful',
     160    #   u'Amount': 2940000,
     161    #   u'CardNumber': u'2507',
     162    #   u'ResponseCode': u'00',
     163    #   u'LeadBankCbnCode': None,
     164    #   u'LeadBankName': None}
     165
     166    if len(jr) != 11:
     167        msg = _('Invalid callback: ${a}', mapping = {'a': str(jr)})
     168        log = 'invalid callback for payment %s: %s' % (payment.p_id, str(jr))
     169        return False, msg, log
     170    payment.r_code = jr['ResponseCode']
     171    payment.r_desc = jr['ResponseDescription']
     172    payment.r_amount_approved = jr['Amount'] / 100.0
     173    payment.r_card_num = jr['CardNumber']
     174    payment.r_pay_reference = jr['PaymentReference']
     175    payment.r_company = u'interswitch'
     176    if payment.r_code != '00':
     177        msg = _('Unsuccessful callback: ${a}', mapping = {'a': payment.r_desc})
     178        log = 'unsuccessful callback for %s payment %s: %s' % (
     179            payment.p_category, payment.p_id, payment.r_desc)
     180        payment.p_state = 'failed'
     181        notify(grok.ObjectModifiedEvent(payment))
     182        return False, msg, log
     183    if round(payment.r_amount_approved, 2) != round(payment.amount_auth, 2):
     184        msg = _('Callback amount does not match.')
     185        log = 'wrong callback for %s payment %s: %s' % (
     186            payment.p_category, payment.p_id, str(jr))
     187        payment.p_state = 'failed'
     188        notify(grok.ObjectModifiedEvent(payment))
     189        return False, msg, log
     190    if jr['MerchantReference'] != payment.p_id:
     191        msg = _('Callback transaction id does not match.')
     192        log = 'wrong callback for %s payment %s: %s' % (
     193            payment.p_category, payment.p_id, str(jr))
     194        payment.p_state = 'failed'
     195        notify(grok.ObjectModifiedEvent(payment))
     196        return False, msg, log
     197    payment.p_state = 'paid'
     198    payment.payment_date = datetime.utcnow()
     199    msg = _('Successful callback received')
     200    log = 'valid callback for %s payment %s: %s' % (
     201        payment.p_category, payment.p_id, str(jr))
     202    notify(grok.ObjectModifiedEvent(payment))
     203    return True, msg, log
     204
    112205def write_payments_log(id, payment):
    113206    payment.logger.info(
  • main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/interswitch/tests.py

    r13386 r13387  
    3131#   If you enable this, please make sure the external services
    3232#   do exist really and are not bothered by being spammed by a test programme.
    33 EXTERNAL_TESTS = True
     33EXTERNAL_TESTS = False
    3434
    3535def external_test(func):
     
    136136
    137137    @external_test
    138     def test_query_interswitch(self):
     138    def test_query_interswitch_SOAP(self):
    139139        host = 'webpay.interswitchng.com'
    140140        url = '/paydirect/services/TransactionQueryWs.asmx'
    141141        https = True
     142        mac = None
    142143        product_id = '5845' # AAUE regular
    143144        payment = StudentOnlinePayment()
     
    145146        payment.amount_auth = 60250.0
    146147        success, msg, log = query_interswitch(
    147             payment, product_id, host, url, https)
     148            payment, product_id, host, url, https, mac)
    148149        self.assertEqual('Successful callback received', msg)
    149150        self.assertTrue(success)
     
    151152            '00:Approved Successful:6025000:3154:p4465649308559:'
    152153            'ZIB|WEB|ABAL|3-11-2015|021336:000457580882' in log)
     154
     155    @external_test
     156    def test_query_interswitch_JSON(self):
     157        host = 'webpay.interswitchng.com'
     158        url = '/paydirect/api/v1/gettransaction.json'
     159        mac = '9718FA00B0F5070B388A9896ADCED9B2FB02D30F71E12E68BDADC63F6852A3496FF97D8A0F9DA9F753B911A49BB09BB87B55FD02046BD325C74C46C0123CF023'
     160        https = True
     161        product_id = '5845' # AAUE regular
     162        payment = StudentOnlinePayment()
     163        payment.p_id ='p4465649308559'
     164        payment.amount_auth = 1.0
     165        success, msg, log = query_interswitch(
     166            payment, product_id, host, url, https, mac)
     167        self.assertFalse(success)
     168        self.assertTrue('Unsuccessful callback:' in msg)
     169        self.assertTrue('Amount Inconsistency' in log)
     170        payment.amount_auth = 60250.0
     171        success, msg, log = query_interswitch(
     172            payment, product_id, host, url, https, mac)
     173        self.assertEqual('Successful callback received', msg)
     174        self.assertTrue(success)
     175        self.assertTrue(
     176            "{u'SplitAccounts': [], "
     177            "u'MerchantReference': u'p4465649308559', "
     178            "u'PaymentReference': u'ZIB|WEB|ABAL|3-11-2015|021336', "
     179            "u'TransactionDate': u'2015-11-03T16:40:54.487', "
     180            "u'RetrievalReferenceNumber': u'000457580882', "
     181            "u'ResponseDescription': u'Approved Successful', "
     182            "u'Amount': 6025000, "
     183            "u'CardNumber': u'3154', "
     184            "u'ResponseCode': u'00', "
     185            "u'LeadBankCbnCode': None, "
     186            "u'LeadBankName': None}" in log)
    153187
    154188class InterswitchTestsApplicants(ApplicantsFullSetup):
Note: See TracChangeset for help on using the changeset viewer.