diff --git a/src/multisafepay/util/webhook.py b/src/multisafepay/util/webhook.py index 333d631..c311f4d 100644 --- a/src/multisafepay/util/webhook.py +++ b/src/multisafepay/util/webhook.py @@ -57,6 +57,7 @@ def validate( transaction_compact_json = json.dumps( transaction_json, separators=(",", ":"), + ensure_ascii=False, ) except json.JSONDecodeError as e: raise InvalidArgumentException( diff --git a/tests/multisafepay/unit/util/test_unit_webhook.py b/tests/multisafepay/unit/util/test_unit_webhook.py index 95e4eaa..7bbd18e 100644 --- a/tests/multisafepay/unit/util/test_unit_webhook.py +++ b/tests/multisafepay/unit/util/test_unit_webhook.py @@ -10,6 +10,10 @@ import pytest import json +import base64 +import hashlib +import hmac +import time from multisafepay.exception.invalid_argument import InvalidArgumentException from multisafepay.util.webhook import Webhook @@ -157,3 +161,43 @@ def test_verify_with_empty_spaces_in_api_key(): " your-MultiSafepay-API-key ", 0, ) + + +def test_validate_with_unicode_characters(): + """Test Webhook validation with unicode characters in the payload.""" + api_key = "test-api-key" + timestamp = str(int(time.time())) + + # Payload with unicode characters + data = { + "city": "München", + "price": "€100", + "description": "Descripción con ñ", + } + json_request = json.dumps(data) + + # Manually calculate expected signature using ensure_ascii=False + transaction_compact_json = json.dumps( + data, + separators=(",", ":"), + ensure_ascii=False, + ) + payload = f"{timestamp}:{transaction_compact_json}" + + signature = hmac.new( + api_key.encode(), + payload.encode(), + hashlib.sha512, + ).hexdigest() + + auth_header = base64.b64encode( + f"{timestamp}:{signature}".encode(), + ).decode() + + # Validation should pass + assert Webhook.validate( + json_request, + auth_header, + api_key, + validation_time_in_seconds=600, + )