From e63cf3c13cedb735627792ea21e4f28edb0591fc Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Fri, 1 Jan 2016 00:00:00 +0100 Subject: [PATCH] [FIX] payment_buckaroo: handle return data Fixing several issues in the computation of the sha1 signature: - Removing BRQ_SIGNATURE parameter was only tested in uppercase. The parameters returned by Buckaroo are case insensitive and we can not ensure it will be uppercase. Check all keys instead. - Sorting should be done case insensitive (e.g. 'AA' before 'bb') but the case must be preserved in the final string to sign. - The values returned should be URL decoded before being signed. The value "J.+de+Tester" should be decoded to "J. de Tester" - The final string may contain unicode and fail to be used by sha1() method. Based on Buckaroo Payment Engine 3.0 http://pronamic.nl/wp-content/uploads/2013/04/BPE-3.0-Gateway-HTML.1.02.pdf Happy New Year Odoo! :tada: :fireworks: :postal_horn: --- addons/payment_buckaroo/models/buckaroo.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/addons/payment_buckaroo/models/buckaroo.py b/addons/payment_buckaroo/models/buckaroo.py index 0e22cd74fcc..87ad7605c7d 100644 --- a/addons/payment_buckaroo/models/buckaroo.py +++ b/addons/payment_buckaroo/models/buckaroo.py @@ -1,6 +1,7 @@ # -*- coding: utf-'8' "-*-" from hashlib import sha1 import logging +import urllib import urlparse from openerp.addons.payment.models.payment_acquirer import ValidationError @@ -70,17 +71,22 @@ class AcquirerBuckaroo(osv.Model): values = dict(values or {}) if inout == 'out': - if 'BRQ_SIGNATURE' in values: - del values['BRQ_SIGNATURE'] - items = sorted((k.upper(), v) for k, v in values.items()) - sign = ''.join('%s=%s' % (k, v) for k, v in items) + for key in values.keys(): + # case insensitive keys + if key.upper() == 'BRQ_SIGNATURE': + del values[key] + break + + items = sorted(values.items(), key=lambda (x, y): x.lower()) + sign = ''.join('%s=%s' % (k, urllib.unquote_plus(v)) for k, v in items) else: sign = ''.join('%s=%s' % (k,get_value(k)) for k in keys) #Add the pre-shared secret key at the end of the signature sign = sign + acquirer.brq_secretkey if isinstance(sign, str): + # TODO: remove me? should not be used sign = urlparse.parse_qsl(sign) - shasign = sha1(sign).hexdigest() + shasign = sha1(sign.encode('utf-8')).hexdigest() return shasign @@ -133,6 +139,7 @@ class TxBuckaroo(osv.Model): def _buckaroo_form_get_tx_from_data(self, cr, uid, data, context=None): """ Given a data dict coming from buckaroo, verify it and find the related transaction record. """ + origin_data = dict(data) data = normalize_keys_upper(data) reference, pay_id, shasign = data.get('BRQ_INVOICENUMBER'), data.get('BRQ_PAYMENT'), data.get('BRQ_SIGNATURE') if not reference or not pay_id or not shasign: @@ -152,7 +159,7 @@ class TxBuckaroo(osv.Model): tx = self.pool['payment.transaction'].browse(cr, uid, tx_ids[0], context=context) #verify shasign - shasign_check = self.pool['payment.acquirer']._buckaroo_generate_digital_sign(tx.acquirer_id, 'out' ,data) + shasign_check = self.pool['payment.acquirer']._buckaroo_generate_digital_sign(tx.acquirer_id, 'out', origin_data) if shasign_check.upper() != shasign.upper(): error_msg = 'Buckaroo: invalid shasign, received %s, computed %s, for data %s' % (shasign, shasign_check, data) _logger.error(error_msg)