source: main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/remita/helpers.py @ 14820

Last change on this file since 14820 was 14820, checked in by Henrik Bettermann, 7 years ago

It seems that some banks add a small transaction fee < 10 Naira which we don't know in advance.

  • Property svn:keywords set to Id
File size: 5.7 KB
Line 
1## $Id: helpers.py 14820 2017-08-30 06:02:46Z henrik $
2##
3## Copyright (C) 2017 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""General helper functions for the remita module in custom packages.
19"""
20import grok
21from datetime import datetime
22import httplib
23import hashlib
24import json
25
26from zope.event import notify
27from kofacustom.nigeria.interfaces import MessageFactory as _
28
29def get_JSON_POST_response(
30        merchantId, serviceTypeId, api_key, orderId,
31        amount, responseurl, host, url, https, fullname, email, lineitems):
32    hashargs =  merchantId + serviceTypeId + orderId + str(amount) + responseurl + api_key
33    hashvalue = hashlib.sha512(hashargs).hexdigest()
34    headers={
35        'Content-Type':'application/json; charset=utf-8',
36    }
37    if https:
38        h = httplib.HTTPSConnection(host)
39    else:
40        h = httplib.HTTPConnection(host)
41    data = {
42            "merchantId":merchantId,
43            "serviceTypeId":serviceTypeId,
44            "totalAmount":amount,
45            "hash":hashvalue,
46            "payerName":fullname,
47            "payerEmail":email,
48            "orderId":orderId,
49            "responseurl":responseurl,
50            "lineItems":lineitems
51            }
52    try:
53        h.request("POST", url, body=json.dumps(data), headers=headers)
54    except:
55        return {'error': 'Socket Error: Connection to Remita gateway refused.'}
56    resp = h.getresponse()
57    if resp.status!=200:
58        return {'error': 'Connection error (%s, %s)' % (resp.status, resp.reason)}
59    jsonout = resp.read()
60    try:
61        parsed_json = json.loads(jsonout[6:-1])
62    except ValueError:
63        return {'error': 'No JSON response'}
64    return parsed_json
65
66def get_payment_status_via_rrr(merchantId, api_key, RRR, host, https):
67    RRR = RRR.rstrip()
68    hashargs =  RRR + api_key + merchantId
69    hashvalue = hashlib.sha512(hashargs).hexdigest()
70    headers={
71        'Content-Type':'application/json; charset=utf-8',
72    }
73    url = '/remita/ecomm/%s/%s/%s/status.reg' % (merchantId, RRR, hashvalue)
74    if https:
75        h = httplib.HTTPSConnection(host)
76    else:
77        h = httplib.HTTPConnection(host)
78    try:
79        h.request("GET", url, headers=headers)
80    except:
81        return {'error': 'Socket Error: Connection to Remita gateway refused.'}
82    resp = h.getresponse()
83    if resp.status!=200:
84        return {'error': 'Connection error (%s, %s)' % (resp.status, resp.reason)}
85    jsonout = resp.read()
86    try:
87        parsed_json = json.loads(jsonout)
88    except ValueError:
89        return {'error': 'No JSON response'}
90    return parsed_json
91
92def query_remita(payment, merchantId, api_key, RRR, host, https, verify):
93
94    jr = get_payment_status_via_rrr(merchantId, api_key, RRR, host, https)
95    error = jr.get('error')
96    if error:
97        msg = log = error
98        return False, msg, log
99
100    # A typical JSON response
101    # {
102    # u'orderId': u'3456346346',
103    # u'status': u'021',
104    # u'amount': 1000.0,
105    # u'transactiontime': u'2017-07-31 11:17:24 AM',
106    # u'message': u'Transaction Pending',
107    # u'lineitems': [{u'status': u'021', u'lineItemsId': u'itemid1'},
108    #                {u'status': u'021', u'lineItemsId': u'itemid2'}
109    #               ],
110    # u'RRR': u'280007640804'}
111
112    payment.r_code = jr['status']
113    payment.r_desc = jr['message']
114    payment.r_amount_approved = jr['amount']
115    payment.r_pay_reference = jr['RRR']
116    payment.r_company = u'remita'
117    if payment.r_code not in ('00', '01'):
118        msg = _('Unsuccessful response: ${a}', mapping = {'a': payment.r_desc})
119        log = 'unsuccessful response for %s payment %s: %s' % (
120            payment.p_category, payment.p_id, payment.r_desc)
121        payment.p_state = 'failed'
122        notify(grok.ObjectModifiedEvent(payment))
123        return False, msg, log
124    if round(payment.r_amount_approved/10.0, 0) != round(
125        payment.amount_auth/10.0, 0):
126        msg = _('Response amount does not match.')
127        log = 'wrong response for %s payment %s: %s' % (
128            payment.p_category, payment.p_id, str(jr))
129        payment.p_state = 'failed'
130        notify(grok.ObjectModifiedEvent(payment))
131        return False, msg, log
132    orderId = jr.get('orderId', None)
133    if orderId and orderId != payment.p_id:
134        msg = _('Response order id does not match.')
135        log = 'wrong response for %s payment %s: %s' % (
136            payment.p_category, payment.p_id, str(jr))
137        payment.p_state = 'failed'
138        notify(grok.ObjectModifiedEvent(payment))
139        return False, msg, log
140    payment.p_state = 'paid'
141    if not verify:
142        payment.payment_date = datetime.utcnow()
143    msg = _('Successful response received')
144    log = 'valid response for %s payment %s: %s' % (
145        payment.p_category, payment.p_id, str(jr))
146    notify(grok.ObjectModifiedEvent(payment))
147    return True, msg, log
148
149def write_payments_log(id, payment):
150    payment.logger.info(
151        '%s,%s,%s,%s,%s,%s,%s,%s,,,' % (
152        id, payment.p_id, payment.p_category,
153        payment.amount_auth, payment.r_code,
154        payment.provider_amt, payment.gateway_amt,
155        payment.thirdparty_amt))
Note: See TracBrowser for help on using the repository browser.