systempayv2: implement HMAC SHA256 signature (#46658)
This commit is contained in:
parent
f7d698c71f
commit
cae250d132
|
@ -15,9 +15,11 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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)
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue