From 3e0b560d0ecf74e291959c7a216db45f10212b26 Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Fri, 30 Nov 2018 00:30:06 +0100 Subject: [PATCH 1/9] remove requirements with pycrypto --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 5a9c8ce..325b77d 100755 --- a/setup.py +++ b/setup.py @@ -27,5 +27,4 @@ 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', ], - install_requires=['pycrypto>=2.6,<2.7'] ) From f1fd44a1e4275ccc938e0f9507e0b0ffc529011a Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Fri, 30 Nov 2018 00:51:32 +0100 Subject: [PATCH 2/9] encode utf-8 --- redsys/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redsys/client.py b/redsys/client.py index 4131e79..3a2599f 100644 --- a/redsys/client.py +++ b/redsys/client.py @@ -51,7 +51,7 @@ def decode_parameters(self, parameters): return json.loads(base64.b64decode(parameters).decode('utf-8')) def encrypt_3DES(self, order): - pycrypto = DES3.new(base64.b64decode(self.secret_key), DES3.MODE_CBC, IV=b'\0\0\0\0\0\0\0\0') + pycrypto = DES3.new(base64.b64decode(self.secret_key).encode('utf-8'), DES3.MODE_CBC, IV=b'\0\0\0\0\0\0\0\0'.encode('utf-8')) if (sys.version_info > (3,0)): order_padded = order.ljust(16, u'\x00') else: From fd7ee62dbb0a6313ddb626ef65c19a340b278783 Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Fri, 30 Nov 2018 01:55:10 +0100 Subject: [PATCH 3/9] Order encode to utf-8 --- redsys/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/redsys/client.py b/redsys/client.py index 3a2599f..4b2f51f 100644 --- a/redsys/client.py +++ b/redsys/client.py @@ -51,13 +51,13 @@ def decode_parameters(self, parameters): return json.loads(base64.b64decode(parameters).decode('utf-8')) def encrypt_3DES(self, order): - pycrypto = DES3.new(base64.b64decode(self.secret_key).encode('utf-8'), DES3.MODE_CBC, IV=b'\0\0\0\0\0\0\0\0'.encode('utf-8')) + pycrypto = DES3.new(base64.b64decode(self.secret_key), DES3.MODE_CBC, IV=b'\0\0\0\0\0\0\0\0') if (sys.version_info > (3,0)): order_padded = order.ljust(16, u'\x00') else: order_padded = order.ljust(16, b'\0') - return pycrypto.encrypt(order_padded) + return pycrypto.encrypt(order_padded.encode('utf-8')) def sign_hmac256(self, encrypted_order, merchant_parameters): signature = hmac.new(encrypted_order, merchant_parameters, hashlib.sha256).digest() From eca368bf0af345448f43dd3aee68965734b8bc92 Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Fri, 30 Nov 2018 01:55:47 +0100 Subject: [PATCH 4/9] BUMP new version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 325b77d..eab4aae 100755 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name='redsys', - version='0.2.6', + version='0.2.7', packages=find_packages(), include_package_data=True, license='MIT License', From f916d91217fa497d9ee48bdbb680b63d9a219994 Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Tue, 5 Mar 2019 11:42:28 +0100 Subject: [PATCH 5/9] add first 0 on code error --- redsys/response.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/redsys/response.py b/redsys/response.py index 9ee532a..c05c740 100644 --- a/redsys/response.py +++ b/redsys/response.py @@ -21,24 +21,24 @@ RESPONSE_MAP = { '0000': 'Transacción autorizada para pagos y preautorizaciones', - '900': 'Transacción autorizada para devoluciones y confirmaciones', - '400': 'Transacción autorizada para anulaciones', - '101': 'Tarjeta caducada', - '102': 'Tarjeta en excepción transitoria o bajo sospecha de fraude', - '106': 'Intentos de PIN excedidos', - '125': 'Tarjeta no efectiva', - '129': 'Código de seguridad (CVV2/CVC2) incorrecto', - '180': 'Tarjeta ajena al servicio', - '184': 'Error en la autenticación del titular', - '190': 'Denegación del emisor sin especificar motivo', - '191': 'Fecha de caducidad errónea', - '202': 'Tarjeta en excepción transitoria o bajo sospecha de fraude con retirada de tarjeta', - '904': 'Comercio no registrado en FUC', - '909': 'Error de sistema', - '912': 'Emisor no disponible', - '913': 'Pedido repetido', - '944': 'Sesión Incorrecta', - '950': 'Operación de devolución no permitida', + '0900': 'Transacción autorizada para devoluciones y confirmaciones', + '0400': 'Transacción autorizada para anulaciones', + '0101': 'Tarjeta caducada', + '0102': 'Tarjeta en excepción transitoria o bajo sospecha de fraude', + '0106': 'Intentos de PIN excedidos', + '0125': 'Tarjeta no efectiva', + '0129': 'Código de seguridad (CVV2/CVC2) incorrecto', + '0180': 'Tarjeta ajena al servicio', + '0184': 'Error en la autenticación del titular', + '0190': 'Denegación del emisor sin especificar motivo', + '0191': 'Fecha de caducidad errónea', + '0202': 'Tarjeta en excepción transitoria o bajo sospecha de fraude con retirada de tarjeta', + '0904': 'Comercio no registrado en FUC', + '0909': 'Error de sistema', + '0912': 'Emisor no disponible', + '0913': 'Pedido repetido', + '0944': 'Sesión Incorrecta', + '0950': 'Operación de devolución no permitida', '9912': 'Emisor no disponible', '9064': 'Número de posiciones de la tarjeta incorrecto', '9078': 'Tipo de operación no permitida para esa tarjeta', @@ -122,4 +122,4 @@ def response_message(self): return RESPONSE_MAP['0000'] if self.is_paid() else RESPONSE_MAP[self.response] def clean_amount(self, value): - return Decimal("%s.%s" % (str(value)[:-2], str(value)[-2:])) \ No newline at end of file + return Decimal("%s.%s" % (str(value)[:-2], str(value)[-2:])) From 5b3b4a2b45a77325217fd5a013dba52f235ce4c0 Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Tue, 26 Mar 2019 18:53:10 +0100 Subject: [PATCH 6/9] WIP MerchantCode --- redsys/response.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/redsys/response.py b/redsys/response.py index c05c740..ecd1167 100644 --- a/redsys/response.py +++ b/redsys/response.py @@ -5,6 +5,7 @@ DATE = 'Ds_Date' HOUR = 'Ds_Hour' MERCHANT_CODE = 'Ds_MerchantCode' +MERCHANT_MERCHANTCODE = 'Ds_Merchant_MerchantCode' TERMINAL = 'Ds_Terminal' TRANSACTION_TYPE = 'Ds_TransactionType' ORDER = 'Ds_Order' @@ -65,6 +66,7 @@ 'date': DATE, 'hour': HOUR, 'merchant_code': MERCHANT_CODE, + 'merchant_merchantcode': MERCHANT_MERCHANTCODE, 'terminal': TERMINAL, 'transaction_type': TRANSACTION_TYPE, 'order': ORDER, From c076d5cc566e4639af90071948938c6d95addb8a Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Wed, 27 Mar 2019 13:13:12 +0100 Subject: [PATCH 7/9] Remove merchantcode --- redsys/response.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/redsys/response.py b/redsys/response.py index ecd1167..c05c740 100644 --- a/redsys/response.py +++ b/redsys/response.py @@ -5,7 +5,6 @@ DATE = 'Ds_Date' HOUR = 'Ds_Hour' MERCHANT_CODE = 'Ds_MerchantCode' -MERCHANT_MERCHANTCODE = 'Ds_Merchant_MerchantCode' TERMINAL = 'Ds_Terminal' TRANSACTION_TYPE = 'Ds_TransactionType' ORDER = 'Ds_Order' @@ -66,7 +65,6 @@ 'date': DATE, 'hour': HOUR, 'merchant_code': MERCHANT_CODE, - 'merchant_merchantcode': MERCHANT_MERCHANTCODE, 'terminal': TERMINAL, 'transaction_type': TRANSACTION_TYPE, 'order': ORDER, From 1ab73bb3d8c980417a1cc05f42af073874d01fa0 Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Mon, 23 Mar 2020 19:36:31 +0100 Subject: [PATCH 8/9] fix: add Credential On File or COF functionality necessary on Redsys v1.1. (https://pagosonline.redsys.es/documents/Especificaciones-COF-ECom-v1.1.pdf) --- redsys/cof.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++ redsys/request.py | 23 +++++++++++++++++++++- redsys/response.py | 2 ++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 redsys/cof.py diff --git a/redsys/cof.py b/redsys/cof.py new file mode 100644 index 0000000..091f278 --- /dev/null +++ b/redsys/cof.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +""" Installments """ +INSTALLMENTS = 'I' + +""" Recurring """ +RECURRING = 'R' + +""" Reauthorization """ +REAUTHORIZATION = 'H' + +""" Resubmission """ +RESUBMISSION = 'E' + +""" Delayed """ +DELAYED = 'D' + +""" Incremental """ +INCREMENTAL = 'M' + +""" No Show """ +NO_SHOW = 'N' + +""" Others """ +OTHERS = 'C' + +COF_TYPES = [ + INSTALLMENTS, + RECURRING, + REAUTHORIZATION, + RESUBMISSION, + DELAYED, + INCREMENTAL, + NO_SHOW, + OTHERS +] + +""" First COF yes """ +SI = 'S' + +""" First COF no """ +NO = 'N' + +""" First Boolean """ +COF_FIRST_BOOLEAN = [ + SI, + NO +] diff --git a/redsys/request.py b/redsys/request.py index f667f02..9713d9c 100644 --- a/redsys/request.py +++ b/redsys/request.py @@ -3,6 +3,7 @@ from .transactions import TRANSACTION_TYPES from .currencies import CURRENCIES from .languages import LANGUAGES +from .cof import COF_FIRST_BOOLEAN, COF_TYPES # General parameters MERCHANT_CODE = 'Ds_Merchant_MerchantCode' @@ -36,6 +37,11 @@ EXPIRY_DATE = 'Ds_Merchant_ExpiryDate' CVV2 = 'Ds_Merchant_Cvv2' +# Credential-On-File +COF_INI = 'Ds_Merchant_Cof_Ini' +COF_TYPE = 'Ds_Merchant_Cof_Type' +COF_TXNID = 'Ds_Merchant_Cof_Txnid' + MERCHANT_PARAMETERS_MAP = { 'merchant_code': MERCHANT_CODE, 'terminal': TERMINAL, @@ -58,7 +64,10 @@ 'consumer_language': CONSUMER_LANGUAGE, 'pan': PAN, 'expiry_date': EXPIRY_DATE, - 'cvv2': CVV2 + 'cvv2': CVV2, + 'cof_ini': COF_INI, + 'cof_type': COF_TYPE, + 'cof_txnid': COF_TXNID } @@ -132,3 +141,15 @@ def check_url_ko(self, value): def check_consumer_language(self, value): if value not in LANGUAGES: raise ValueError("consumer_language is not valid.") + + def check_cof_ini(self, value): + if value not in COF_FIRST_BOOLEAN: + raise ValueError("cof_ini is not valid.") + + def check_cof_type(self, value): + if value not in COF_TYPES: + raise ValueError("cof_type is not valid.") + + def check_cof_txnid(self, value): + if len(value) > 15: + raise ValueError("cof_txnid is bigger than 15 characters.") diff --git a/redsys/response.py b/redsys/response.py index c05c740..3315419 100644 --- a/redsys/response.py +++ b/redsys/response.py @@ -17,6 +17,7 @@ CARD_BRAND = 'Ds_Card_Brand' SECURE_PAYMENT = 'Ds_SecurePayment' AUTHORIZATION_CODE = 'Ds_AuthorisationCode' +COF_TXNID = 'Ds_Merchant_Cof_Txnid' ERROR_CODE = 'Ds_ErrorCode' RESPONSE_MAP = { @@ -77,6 +78,7 @@ 'card_brand': CARD_BRAND, 'secure_payment': SECURE_PAYMENT, 'authorization_code': AUTHORIZATION_CODE, + 'cof_txnid': COF_TXNID, 'error_code': ERROR_CODE, } From 9460821bbb03e0ec6faa61d42644718ada6b9520 Mon Sep 17 00:00:00 2001 From: mUniKeS Date: Wed, 24 Mar 2021 11:52:42 +0100 Subject: [PATCH 9/9] Add reponse param Ds_ProcessedPayMethod --- redsys/response.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/redsys/response.py b/redsys/response.py index 3315419..59c0bed 100644 --- a/redsys/response.py +++ b/redsys/response.py @@ -18,6 +18,7 @@ SECURE_PAYMENT = 'Ds_SecurePayment' AUTHORIZATION_CODE = 'Ds_AuthorisationCode' COF_TXNID = 'Ds_Merchant_Cof_Txnid' +PROCESSED_PAY_METHOD = 'Ds_ProcessedPayMethod' ERROR_CODE = 'Ds_ErrorCode' RESPONSE_MAP = { @@ -80,6 +81,7 @@ 'authorization_code': AUTHORIZATION_CODE, 'cof_txnid': COF_TXNID, 'error_code': ERROR_CODE, + 'processed_payment_method': PROCESSED_PAY_METHOD, }