general: check responses for required attributes as 1st processing step (#9729)

This commit is contained in:
Frédéric Péters 2016-03-09 22:31:40 +01:00
parent 297e9a8514
commit 60a71c626e
11 changed files with 41 additions and 12 deletions

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from common import URL, HTML, FORM, RECEIVED, ACCEPTED, PAID, DENIED, CANCELED, CANCELLED, ERROR from common import (URL, HTML, FORM, RECEIVED, ACCEPTED, PAID, DENIED,
CANCELED, CANCELLED, ERROR, ResponseError)
__all__ = ['Payment', 'URL', 'HTML', 'FORM', 'SIPS', __all__ = ['Payment', 'URL', 'HTML', 'FORM', 'SIPS',
'SYSTEMPAY', 'SPPLUS', 'TIPI', 'DUMMY', 'get_backend', 'RECEIVED', 'ACCEPTED', 'SYSTEMPAY', 'SPPLUS', 'TIPI', 'DUMMY', 'get_backend', 'RECEIVED', 'ACCEPTED',

View File

@ -27,6 +27,10 @@ ERROR = 99
ORDERID_TRANSACTION_SEPARATOR = '!' ORDERID_TRANSACTION_SEPARATOR = '!'
class ResponseError(Exception):
pass
class PaymentResponse(object): class PaymentResponse(object):
'''Holds a generic view on the result of payment transaction response. '''Holds a generic view on the result of payment transaction response.

View File

@ -10,7 +10,7 @@ try:
except ImportError: except ImportError:
from urlparse import parse_qs from urlparse import parse_qs
from common import PaymentCommon, URL, PaymentResponse, PAID, ERROR from common import PaymentCommon, URL, PaymentResponse, PAID, ERROR, ResponseError
__all__ = [ 'Payment' ] __all__ = [ 'Payment' ]
@ -122,6 +122,8 @@ class Payment(PaymentCommon):
def response(self, query_string, logger=LOGGER, **kwargs): def response(self, query_string, logger=LOGGER, **kwargs):
form = parse_qs(query_string) form = parse_qs(query_string)
if not 'transaction_id' in form:
raise ResponseError()
transaction_id = form.get('transaction_id',[''])[0] transaction_id = form.get('transaction_id',[''])[0]
form[self.BANK_ID] = transaction_id form[self.BANK_ID] = transaction_id

View File

@ -5,7 +5,8 @@ import urlparse
from decimal import Decimal, ROUND_HALF_UP from decimal import Decimal, ROUND_HALF_UP
from common import (PaymentCommon, PaymentResponse, FORM, CANCELLED, PAID, from common import (PaymentCommon, PaymentResponse, FORM, CANCELLED, PAID,
ERROR, Form, DENIED, ACCEPTED, ORDERID_TRANSACTION_SEPARATOR) ERROR, Form, DENIED, ACCEPTED, ORDERID_TRANSACTION_SEPARATOR,
ResponseError)
def N_(message): return message def N_(message): return message
ENVIRONMENT_TEST = 'TEST' ENVIRONMENT_TEST = 'TEST'
@ -528,6 +529,8 @@ class Payment(PaymentCommon):
def response(self, query_string, **kwargs): def response(self, query_string, **kwargs):
params = urlparse.parse_qs(query_string, True) params = urlparse.parse_qs(query_string, True)
params = dict((key.upper(), params[key][0]) for key in params) params = dict((key.upper(), params[key][0]) for key in params)
if not set(params) >= set(['ORDERID', 'PAYID', 'STATUS', 'NCERROR']):
raise ResponseError()
reference = params['ORDERID'] reference = params['ORDERID']
transaction_id = params['PAYID'] transaction_id = params['PAYID']
status = params['STATUS'] status = params['STATUS']

View File

@ -17,7 +17,7 @@ import string
import warnings import warnings
from common import (PaymentCommon, PaymentResponse, FORM, PAID, ERROR, Form, from common import (PaymentCommon, PaymentResponse, FORM, PAID, ERROR, Form,
ORDERID_TRANSACTION_SEPARATOR) ORDERID_TRANSACTION_SEPARATOR, ResponseError)
__all__ = ['sign', 'Payment'] __all__ = ['sign', 'Payment']
@ -253,6 +253,8 @@ class Payment(PaymentCommon):
def response(self, query_string, callback=False, **kwargs): def response(self, query_string, callback=False, **kwargs):
d = urlparse.parse_qs(query_string, True, False) d = urlparse.parse_qs(query_string, True, False)
if not set(d) >= set(['erreur', 'reference']):
raise ResponseError()
signed = False signed = False
if 'signature' in d: if 'signature' in d:
sig = d['signature'][0] sig = d['signature'][0]

View File

@ -9,7 +9,7 @@ import os.path
import uuid import uuid
import warnings import warnings
from common import PaymentCommon, HTML, PaymentResponse from common import PaymentCommon, HTML, PaymentResponse, ResponseError
from cb import CB_RESPONSE_CODES from cb import CB_RESPONSE_CODES
''' '''
@ -159,6 +159,8 @@ class Payment(PaymentCommon):
def response(self, query_string, **kwargs): def response(self, query_string, **kwargs):
form = urlparse.parse_qs(query_string) form = urlparse.parse_qs(query_string)
if not DATA in form:
raise ResponseError()
params = {'message': form[DATA][0]} params = {'message': form[DATA][0]}
result = self.execute('response', params) result = self.execute('response', params)
d = dict(zip(RESPONSE_PARAMS, result)) d = dict(zip(RESPONSE_PARAMS, result))

View File

@ -8,7 +8,8 @@ import hashlib
from gettext import gettext as _ from gettext import gettext as _
import warnings import warnings
from common import PaymentCommon, FORM, Form, PaymentResponse, PAID, ERROR, CANCELED from common import (PaymentCommon, FORM, Form, PaymentResponse, PAID, ERROR,
CANCELED, ResponseError)
__all__ = ['Payment'] __all__ = ['Payment']
@ -190,10 +191,9 @@ class Payment(PaymentCommon):
def response(self, query_string, **kwargs): def response(self, query_string, **kwargs):
form = urlparse.parse_qs(query_string) form = urlparse.parse_qs(query_string)
if not set(form) >= set(['Data', 'Seal', 'InterfaceVersion']):
raise ResponseError()
self.logger.debug('received query string %r', form) self.logger.debug('received query string %r', form)
assert 'Data' in form
assert 'Seal' in form
assert 'InterfaceVersion' in form
data = self.decode_data(form['Data'][0]) data = self.decode_data(form['Data'][0])
seal = form['Seal'][0] seal = form['Seal'][0]
self.logger.debug('parsed response %r seal %r', data, seal) self.logger.debug('parsed response %r seal %r', data, seal)

View File

@ -14,7 +14,7 @@ import warnings
import Crypto.Cipher.DES import Crypto.Cipher.DES
from common import (PaymentCommon, URL, PaymentResponse, RECEIVED, ACCEPTED, from common import (PaymentCommon, URL, PaymentResponse, RECEIVED, ACCEPTED,
PAID, ERROR) PAID, ERROR, ResponseError)
def N_(message): return message def N_(message): return message
@ -176,6 +176,8 @@ class Payment(PaymentCommon):
def response(self, query_string, logger=LOGGER, **kwargs): def response(self, query_string, logger=LOGGER, **kwargs):
form = urlparse.parse_qs(query_string) form = urlparse.parse_qs(query_string)
if not set(form) >= set([REFERENCE, ETAT, REFSFP]):
raise ResponseError()
for key, value in form.iteritems(): for key, value in form.iteritems():
form[key] = value[0] form[key] = value[0]
logger.debug('received query_string %s' % query_string) logger.debug('received query_string %s' % query_string)

View File

@ -8,7 +8,8 @@ import urlparse
import warnings import warnings
from gettext import gettext as _ from gettext import gettext as _
from common import PaymentCommon, PaymentResponse, PAID, ERROR, FORM, Form from common import (PaymentCommon, PaymentResponse, PAID, ERROR, FORM, Form,
ResponseError)
from cb import CB_RESPONSE_CODES from cb import CB_RESPONSE_CODES
__all__ = ['Payment'] __all__ = ['Payment']
@ -338,6 +339,8 @@ class Payment(PaymentCommon):
def response(self, query_string, **kwargs): def response(self, query_string, **kwargs):
fields = urlparse.parse_qs(query_string, True) fields = urlparse.parse_qs(query_string, True)
if not set(fields) >= set([SIGNATURE, VADS_CTX_MODE, VADS_AUTH_RESULT]):
raise ResponseError()
for key, value in fields.iteritems(): for key, value in fields.iteritems():
fields[key] = value[0] fields[key] = value[0]
copy = fields.copy() copy = fields.copy()

View File

@ -2,7 +2,7 @@
from decimal import Decimal, ROUND_DOWN from decimal import Decimal, ROUND_DOWN
from common import (PaymentCommon, PaymentResponse, URL, PAID, DENIED, from common import (PaymentCommon, PaymentResponse, URL, PAID, DENIED,
CANCELLED, ERROR) CANCELLED, ERROR, ResponseError)
from urllib import urlencode from urllib import urlencode
from urlparse import parse_qs from urlparse import parse_qs
from gettext import gettext as _ from gettext import gettext as _
@ -136,6 +136,8 @@ class Payment(PaymentCommon):
def response(self, query_string, **kwargs): def response(self, query_string, **kwargs):
fields = parse_qs(query_string, True) fields = parse_qs(query_string, True)
if not set(fields) >= set(['refdet', 'resultrans']):
raise ResponseError()
for key, value in fields.iteritems(): for key, value in fields.iteritems():
fields[key] = value[0] fields[key] = value[0]
refdet = fields.get('refdet') refdet = fields.get('refdet')

View File

@ -3,6 +3,7 @@ import urllib
import eopayment import eopayment
import eopayment.ogone as ogone import eopayment.ogone as ogone
from eopayment import ResponseError
PSPID = '2352566' PSPID = '2352566'
@ -52,3 +53,10 @@ class OgoneTests(TestCase):
'payid': '32100123', 'status': 9, 'ncerror': 0} 'payid': '32100123', 'status': 9, 'ncerror': 0}
response = ogone_backend.response(urllib.urlencode(data)) response = ogone_backend.response(urllib.urlencode(data))
self.assertEqual(response.order_id, order_id) self.assertEqual(response.order_id, order_id)
def test_bad_response(self):
ogone_backend = eopayment.Payment('ogone', BACKEND_PARAMS)
order_id = 'myorder'
data = {'payid': '32100123', 'status': 9, 'ncerror': 0}
with self.assertRaises(ResponseError):
response = ogone_backend.response(urllib.urlencode(data))