From 986b4e8e4152ced48d1b4eaf7c2e35d5a2206dda Mon Sep 17 00:00:00 2001 From: Matias Vasquez Date: Mon, 26 May 2025 17:31:53 -0400 Subject: [PATCH 1/7] feat: add bin info query request --- transbank/webpay/oneclick/request/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/transbank/webpay/oneclick/request/__init__.py b/transbank/webpay/oneclick/request/__init__.py index 1b9472b8..d50e3b82 100644 --- a/transbank/webpay/oneclick/request/__init__.py +++ b/transbank/webpay/oneclick/request/__init__.py @@ -97,3 +97,10 @@ def __init__(self, self.commerce_code = commerce_code self.detail_buy_order = detail_buy_order self.amount = amount + +class MallBinInfoQueryRequest(object): + def __init__(self, tbk_user: str): + self.tbk_user = tbk_user + + def __repr__(self): + return "MallBinInfoQueryRequest(tbk_user: {})".format(self.tbk_user) From 67f0f0e6a4a91095b6aa05019f06c00429d85e22 Mon Sep 17 00:00:00 2001 From: Matias Vasquez Date: Mon, 26 May 2025 17:32:08 -0400 Subject: [PATCH 2/7] feat: add bin info query request schema --- transbank/webpay/oneclick/schema.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/transbank/webpay/oneclick/schema.py b/transbank/webpay/oneclick/schema.py index d646aee5..42edb510 100644 --- a/transbank/webpay/oneclick/schema.py +++ b/transbank/webpay/oneclick/schema.py @@ -35,3 +35,6 @@ class MallTransactionRefundRequestSchema(Schema): commerce_code = fields.Str() detail_buy_order = fields.Str() amount = fields.Str() + +class MallBinInfoQueryRequestSchema(Schema): + tbk_user = fields.Str() From 5fcfe363b530415c363becb243ed9664fa3bd336 Mon Sep 17 00:00:00 2001 From: Matias Vasquez Date: Mon, 26 May 2025 17:32:29 -0400 Subject: [PATCH 3/7] feat: add exception for bin info --- transbank/error/mall_bin_info_query_error.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 transbank/error/mall_bin_info_query_error.py diff --git a/transbank/error/mall_bin_info_query_error.py b/transbank/error/mall_bin_info_query_error.py new file mode 100644 index 00000000..b9cc0975 --- /dev/null +++ b/transbank/error/mall_bin_info_query_error.py @@ -0,0 +1,5 @@ +from transbank.error.transbank_error import TransbankError + +class MallBinInfoQueryError(TransbankError): + def __init__(self, message="Mall bin info query could not be performed. Please verify given parameters", code=0): + super().__init__(message, code) From 2e1a4cda8e5a0d427803d360dbd584992ad48ec9 Mon Sep 17 00:00:00 2001 From: Matias Vasquez Date: Mon, 26 May 2025 17:32:54 -0400 Subject: [PATCH 4/7] feat: add bin info class --- transbank/webpay/oneclick/mall_bin_info.py | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 transbank/webpay/oneclick/mall_bin_info.py diff --git a/transbank/webpay/oneclick/mall_bin_info.py b/transbank/webpay/oneclick/mall_bin_info.py new file mode 100644 index 00000000..e5910a3f --- /dev/null +++ b/transbank/webpay/oneclick/mall_bin_info.py @@ -0,0 +1,36 @@ +from transbank.common.api_constants import ApiConstants +from transbank.common.webpay_transaction import WebpayTransaction +from transbank.common.validation_util import ValidationUtil +from transbank.common.api_constants import ApiConstants +from transbank.common.options import WebpayOptions +from transbank.common.request_service import RequestService +from transbank.error.transbank_error import TransbankError +from transbank.error.mall_bin_info_query_error import MallBinInfoQueryError +from transbank.webpay.oneclick.request import MallBinInfoQueryRequest +from transbank.webpay.oneclick.schema import MallBinInfoQueryRequestSchema + +class MallBinInfo(WebpayTransaction): + INFO_ENDPOINT = ApiConstants.ONECLICK_ENDPOINT + '/bin_info' + + def __init__(self, options: WebpayOptions): + super().__init__(options) + + def query_bin(self, tbk_user: str): + """ + Queries the BIN information for a given `tbk_user`. + + Args: + tbk_user (str): The `tbk_user` for which to query the BIN information. + Returns: + dict: The BIN information for the specified `tbk_user`. + Raises: + MallBinInfoQueryError: If there is an error querying the BIN information. + TransbankError: If `tbk_user` exceeds the max length + """ + ValidationUtil.has_text_with_max_length(tbk_user, ApiConstants.TBK_USER_LENGTH, "tbk_user") + try: + endpoint = MallBinInfo.INFO_ENDPOINT + request = MallBinInfoQueryRequest(tbk_user) + return RequestService.post(endpoint, MallBinInfoQueryRequestSchema().dumps(request), self.options) + except TransbankError as e: + raise MallBinInfoQueryError(e.message, e.code) From b3e728a5473e16f89f458302e4a9c04199666f02 Mon Sep 17 00:00:00 2001 From: Matias Vasquez Date: Mon, 26 May 2025 17:33:09 -0400 Subject: [PATCH 5/7] test: add tests for bin info --- tests/webpay/oneclick/test_mall_bin_info.py | 47 +++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tests/webpay/oneclick/test_mall_bin_info.py diff --git a/tests/webpay/oneclick/test_mall_bin_info.py b/tests/webpay/oneclick/test_mall_bin_info.py new file mode 100644 index 00000000..dddd2411 --- /dev/null +++ b/tests/webpay/oneclick/test_mall_bin_info.py @@ -0,0 +1,47 @@ +import unittest +import json +from unittest.mock import Mock +from unittest.mock import patch +from transbank.error.transbank_error import TransbankError +from transbank.error.mall_bin_info_query_error import MallBinInfoQueryError +from transbank.webpay.oneclick.mall_bin_info import MallBinInfo + + +class MallBinInfoTestCase(unittest.TestCase): + + def setUp(self) -> None: + self.mock_response = Mock() + + @patch('transbank.common.request_service.requests.post') + def test_query_bin(self, mock_post): + response = {'bin_issuer': 'TEST COMMERCE BANK', 'bin_payment_type': 'Credito', 'bin_brand': 'Visa'} + self.mock_response.status_code = 200 + self.mock_response.text = json.dumps(response) + mock_post.return_value = self.mock_response + + mall_bin_info = MallBinInfo.build_for_integration('commerce_code', 'api_key') + result = mall_bin_info.query_bin('tbkUser') + + args, kwargs = mock_post.call_args + body = json.loads(kwargs['data']) + + self.assertEqual(result['bin_issuer'], 'TEST COMMERCE BANK') + self.assertEqual(result['bin_payment_type'], 'Credito') + self.assertEqual(result['bin_brand'], 'Visa') + self.assertEqual(body['tbk_user'], 'tbkUser') + + def test_query_bin_invalid_tbk_user(self): + mall_bin_info = MallBinInfo.build_for_integration('commerce_code', 'api_key') + with self.assertRaises(TransbankError): + mall_bin_info.query_bin('b134e1c5e9eeb134e1c5e9eeb134e1c5e9eeb134e1c5e9eeb134e1c5e9eeb134e1c5e9eeb134e1c5e9eeb134e1c5e9ee') + + @patch('transbank.common.request_service.requests.post') + def test_query_bin_throws_api_exception(self, mock_post): + self.mock_response.status_code = 400 + self.mock_response.text = '{"error": "Bad Request"}' + mock_post.return_value = self.mock_response + mall_bin_info = MallBinInfo.build_for_integration('commerce_code', 'api_key') + + with self.assertRaises(MallBinInfoQueryError): + mall_bin_info.query_bin('tbkUser') + \ No newline at end of file From 124c9a2997c799dd42339609275fcb25be11e0f7 Mon Sep 17 00:00:00 2001 From: Matias Vasquez Date: Mon, 26 May 2025 17:36:41 -0400 Subject: [PATCH 6/7] style: add empty line --- tests/webpay/oneclick/test_mall_bin_info.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/webpay/oneclick/test_mall_bin_info.py b/tests/webpay/oneclick/test_mall_bin_info.py index dddd2411..d03291ae 100644 --- a/tests/webpay/oneclick/test_mall_bin_info.py +++ b/tests/webpay/oneclick/test_mall_bin_info.py @@ -44,4 +44,3 @@ def test_query_bin_throws_api_exception(self, mock_post): with self.assertRaises(MallBinInfoQueryError): mall_bin_info.query_bin('tbkUser') - \ No newline at end of file From 405a625fa4d509071304ee92a727944d4fedcd8b Mon Sep 17 00:00:00 2001 From: Matias Vasquez Date: Thu, 19 Jun 2025 17:36:57 -0400 Subject: [PATCH 7/7] test: rename unused variable --- tests/webpay/oneclick/test_mall_bin_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/webpay/oneclick/test_mall_bin_info.py b/tests/webpay/oneclick/test_mall_bin_info.py index d03291ae..c82839bb 100644 --- a/tests/webpay/oneclick/test_mall_bin_info.py +++ b/tests/webpay/oneclick/test_mall_bin_info.py @@ -22,7 +22,7 @@ def test_query_bin(self, mock_post): mall_bin_info = MallBinInfo.build_for_integration('commerce_code', 'api_key') result = mall_bin_info.query_bin('tbkUser') - args, kwargs = mock_post.call_args + _, kwargs = mock_post.call_args body = json.loads(kwargs['data']) self.assertEqual(result['bin_issuer'], 'TEST COMMERCE BANK')