diff --git a/redsys/client.py b/redsys/client.py index 4131e79..4b2f51f 100644 --- a/redsys/client.py +++ b/redsys/client.py @@ -57,7 +57,7 @@ def encrypt_3DES(self, order): 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() 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 9ee532a..59c0bed 100644 --- a/redsys/response.py +++ b/redsys/response.py @@ -17,28 +17,30 @@ CARD_BRAND = 'Ds_Card_Brand' 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 = { '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', @@ -77,7 +79,9 @@ 'card_brand': CARD_BRAND, 'secure_payment': SECURE_PAYMENT, 'authorization_code': AUTHORIZATION_CODE, + 'cof_txnid': COF_TXNID, 'error_code': ERROR_CODE, + 'processed_payment_method': PROCESSED_PAY_METHOD, } @@ -122,4 +126,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:])) diff --git a/setup.py b/setup.py index 5a9c8ce..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', @@ -27,5 +27,4 @@ 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', ], - install_requires=['pycrypto>=2.6,<2.7'] )