diff --git a/eopayment/systempayv2.py b/eopayment/systempayv2.py index 6ff2b1a..99f1cb4 100644 --- a/eopayment/systempayv2.py +++ b/eopayment/systempayv2.py @@ -15,9 +15,11 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import base64 import pytz import datetime as dt import hashlib +import hmac import string from six.moves.urllib import parse as urlparse import warnings @@ -270,6 +272,13 @@ class Payment(PaymentCommon): {'name': 'secret_production', 'caption': _(u'Secret pour la configuration de PRODUCTION'), 'validation': lambda value: str.isalnum(value), }, + {'name': 'signature_algo', + 'caption': _(u'Algorithme de signature'), + 'default': 'hmac_sha256', + 'choices': ( + ('sha1', 'SHA-1'), + ('hmac_sha256', 'HMAC-SHA-256'), + )}, { 'name': 'manual_validation', 'caption': 'Validation manuelle', @@ -462,16 +471,24 @@ class Payment(PaymentCommon): test=test) return response + def sha1_sign(self, secret, signed_data): + return hashlib.sha1(signed_data).hexdigest() + + def hmac_sha256_sign(self, secret, signed_data): + digest = hmac.HMAC(secret, digestmod=hashlib.sha256, msg=signed_data).digest() + return base64.b64encode(digest) + def signature(self, fields): self.logger.debug('got fields %s to sign' % fields) ordered_keys = sorted( [key for key in fields.keys() if key.startswith('vads_')]) self.logger.debug('ordered keys %s' % ordered_keys) ordered_fields = [force_byte(fields[key]) for key in ordered_keys] - secret = getattr(self, 'secret_%s' % fields['vads_ctx_mode'].lower()) + secret = force_byte(getattr(self, 'secret_%s' % fields['vads_ctx_mode'].lower())) signed_data = b'+'.join(ordered_fields) - signed_data = b'%s+%s' % (signed_data, force_byte(secret)) + signed_data = b'%s+%s' % (signed_data, secret) self.logger.debug(u'generating signature on «%s»', signed_data) - sign = hashlib.sha1(signed_data).hexdigest() + sign_method = getattr(self, '%s_sign' % self.signature_algo) + sign = sign_method(secret, signed_data) self.logger.debug(u'signature «%s»', sign) - return sign + return force_text(sign) diff --git a/tests/test_systempayv2.py b/tests/test_systempayv2.py index 240f936..e796360 100644 --- a/tests/test_systempayv2.py +++ b/tests/test_systempayv2.py @@ -31,6 +31,7 @@ PARAMS = { 'vads_site_id': u'12345678', 'vads_ctx_mode': u'TEST', 'vads_trans_date': u'20090501193530', + 'signature_algo': 'sha1' } @@ -80,6 +81,21 @@ def test_systempayv2(): assert response.transaction_date assert response.transaction_date.isoformat() == '2020-03-30T16:25:30+00:00' + PARAMS['signature_algo'] = 'hmac_sha256' + p = Payment(PARAMS) + assert p.signature(qs) == 'aHrJ7IzSGFa4pcYA8kh99+M/xBzoQ4Odnu3f4BUrpIA=' + response_qs = 'vads_amount=1042&vads_auth_mode=FULL&vads_auth_number=3feadf' \ + '&vads_auth_result=00&vads_capture_delay=0&vads_card_brand=CB' \ + '&vads_card_number=497010XXXXXX0000' \ + '&vads_payment_certificate=582ba2b725057618706d7a06e9e59acdbf69ff53' \ + '&vads_ctx_mode=TEST&vads_currency=978&vads_effective_amount=1042' \ + '&vads_site_id=70168983&vads_trans_date=20161013101355' \ + '&vads_trans_id=226787&vads_trans_uuid=4b5053b3b1fe4b02a07753e7a' \ + '&vads_effective_creation_date=20200330162530' \ + '&signature=PeU30M6ilqwhligBAIMQIR3yqxWFGZHJ8Hwtb%2B3IrOM%3D' + response = p.response(response_qs) + assert response.signed + # bad response with pytest.raises(ResponseError, match='missing signature, vads_ctx_mode or vads_auth_result'): p.response('foo=bar')