From bf4f0e237aac106d689ea21eff91eb9413eec8e7 Mon Sep 17 00:00:00 2001 From: Shadi Naif Date: Tue, 4 Jun 2024 15:48:16 +0300 Subject: [PATCH] fix --- ecommerce_payfort/processors.py | 1 + ecommerce_payfort/tests/test_processors.py | 5 ++++- ecommerce_payfort/tests/test_utils.py | 22 ++++++++++++++++++++++ ecommerce_payfort/utils.py | 19 +++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/ecommerce_payfort/processors.py b/ecommerce_payfort/processors.py index cd3dca0..1bd339b 100644 --- a/ecommerce_payfort/processors.py +++ b/ecommerce_payfort/processors.py @@ -45,6 +45,7 @@ def get_transaction_parameters(self, basket, request=None, use_client_side_check "amount": utils.get_amount(basket), "currency": utils.get_currency(basket), "customer_email": utils.get_customer_email(basket), + "customer_ip": utils.get_ip_address(request), "order_description": utils.get_order_description(basket), "customer_name": utils.get_customer_name(basket), "return_url": urljoin( diff --git a/ecommerce_payfort/tests/test_processors.py b/ecommerce_payfort/tests/test_processors.py index 26e5774..02eb07f 100644 --- a/ecommerce_payfort/tests/test_processors.py +++ b/ecommerce_payfort/tests/test_processors.py @@ -62,6 +62,7 @@ def test_handle_processor_response(self): def test_get_transaction_parameters(self): """ Verify the processor returns the appropriate parameters required to complete a transaction. """ + customer_ip = "199.199.199.199" expected_result = { "command": "PURCHASE", "access_code": "123123123", @@ -71,11 +72,13 @@ def test_get_transaction_parameters(self): "amount": 2000, "currency": "SAR", "customer_email": self.basket.owner.email, + "customer_ip": customer_ip, "order_description": f"1 X {self.basket.all_lines()[0].product.course.id}", "customer_name": "Ecommerce User", "return_url": "http://myecommerce.mydomain.com/payfort/response/", } - actual_result = self.processor.get_transaction_parameters(self.basket, request=self.request) + with patch("ecommerce_payfort.utils.get_ip_address", return_value=customer_ip): + actual_result = self.processor.get_transaction_parameters(self.basket, request=self.request) actual_result.pop("csrfmiddlewaretoken") actual_result.pop("payment_page_url") expected_result["signature"] = utils.get_signature( diff --git a/ecommerce_payfort/tests/test_utils.py b/ecommerce_payfort/tests/test_utils.py index c74bd78..9010538 100644 --- a/ecommerce_payfort/tests/test_utils.py +++ b/ecommerce_payfort/tests/test_utils.py @@ -399,3 +399,25 @@ def test_verify_signature_bad_method(valid_response_data): # pylint: disable=re with pytest.raises(utils.PayFortException) as exc: utils.verify_signature("secret@res", "bad_method", valid_response_data) assert "Unsupported SHA method: bad_method" in str(exc) + + +def test_get_ip_address_no_request(): + """Verify that get_ip_address returns a valid IP address when the request is None.""" + assert utils.get_ip_address(None) == "" + + +def test_get_ip_address_with_proxy(): + """Verify that get_ip_address returns a valid IP address when a proxy is used.""" + request = Mock(META={ + "HTTP_X_FORWARDED_FOR": "1.1.1.1, 2.2.2.2, 3.3.3.3", + "REMOTE_ADDR": "should be ignored", + }) + assert utils.get_ip_address(request) == "1.1.1.1" + + +def test_get_ip_address_no_proxy(): + """Verify that get_ip_address returns a valid IP address when no proxy is used.""" + request = Mock(META={ + "REMOTE_ADDR": " 4.4.4.4 ", + }) + assert utils.get_ip_address(request) == "4.4.4.4" diff --git a/ecommerce_payfort/utils.py b/ecommerce_payfort/utils.py index 815983b..0c1f85d 100644 --- a/ecommerce_payfort/utils.py +++ b/ecommerce_payfort/utils.py @@ -320,3 +320,22 @@ def verify_signature(sha_phrase: str, sha_method: str, data: dict): raise PayFortBadSignatureException( f"Response signature mismatch. merchant_reference: {data.get('merchant_reference', 'none')}" ) + + +def get_ip_address(request: Any) -> str: + """ + Return the customer IP address from the request. + + @param request: The request + @return: The customer IP address + """ + if request is None: + return "" + + x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR") + if x_forwarded_for: + ip_address = x_forwarded_for.split(",")[0] + else: + ip_address = request.META.get("REMOTE_ADDR") + + return (ip_address or "").strip()