diff --git a/eopayment/tipi.py b/eopayment/tipi.py index ef20199..60583e4 100644 --- a/eopayment/tipi.py +++ b/eopayment/tipi.py @@ -2,7 +2,7 @@ from decimal import Decimal, ROUND_DOWN from .common import (PaymentCommon, PaymentResponse, URL, PAID, DENIED, - CANCELLED, ERROR, ResponseError) + CANCELLED, ERROR, ResponseError) from six.moves.urllib.parse import urlencode, parse_qs from gettext import gettext as _ @@ -13,10 +13,10 @@ from .systempayv2 import isonow __all__ = ['Payment'] -TIPI_URL = 'http://www.jepaiemesserviceslocaux.dgfip.finances.gouv.fr' \ - '/tpa/paiement.web' +TIPI_URL = 'http://www.jepaiemesserviceslocaux.dgfip.finances.gouv.fr/tpa/paiement.web' LOGGER = logging.getLogger(__name__) + class Payment(PaymentCommon): '''Produce requests for and verify response from the TIPI online payment processor from the French Finance Ministry. @@ -24,55 +24,56 @@ class Payment(PaymentCommon): ''' description = { - 'caption': 'TIPI, Titres Payables par Internet', - 'parameters': [ - { - 'name': 'numcli', - 'caption': _(u'Numéro client'), - 'help_text': _(u'un numéro à 6 chiffres communiqué par l’administrateur TIPI'), - 'validation': lambda s: str.isdigit(s) and (0 < int(s) < 1000000), - 'required': True, - }, - { - 'name': 'service_url', - 'default': TIPI_URL, - 'caption': _(u'URL du service TIPI'), - 'help_text': _(u'ne pas modifier si vous ne savez pas'), - 'validation': lambda x: x.startswith('http'), - 'required': True, - }, - { - 'name': 'normal_return_url', - 'caption': _('Normal return URL (unused by TIPI)'), - 'required': False, - }, - { - 'name': 'automatic_return_url', - 'caption': _('Automatic return URL'), - 'required': True, - }, - { - 'name': 'saisie', - 'caption': _('Payment type'), - 'required': True, - 'default': 'T', - }, - ], + 'caption': 'TIPI, Titres Payables par Internet', + 'parameters': [ + { + 'name': 'numcli', + 'caption': _(u'Numéro client'), + 'help_text': _(u'un numéro à 6 chiffres communiqué par l’administrateur TIPI'), + 'validation': lambda s: str.isdigit(s) and (0 < int(s) < 1000000), + 'required': True, + }, + { + 'name': 'service_url', + 'default': TIPI_URL, + 'caption': _(u'URL du service TIPI'), + 'help_text': _(u'ne pas modifier si vous ne savez pas'), + 'validation': lambda x: x.startswith('http'), + 'required': True, + }, + { + 'name': 'normal_return_url', + 'caption': _('Normal return URL (unused by TIPI)'), + 'required': False, + }, + { + 'name': 'automatic_return_url', + 'caption': _('Automatic return URL'), + 'required': True, + }, + { + 'name': 'saisie', + 'caption': _('Payment type'), + 'required': True, + 'default': 'T', + }, + ], } def request(self, amount, next_url=None, exer=None, orderid=None, - refdet=None, objet=None, email=None, saisie=None, **kwargs): + refdet=None, objet=None, email=None, saisie=None, **kwargs): try: montant = Decimal(amount) if Decimal('0') > montant > Decimal('9999.99'): raise ValueError('MONTANT > 9999.99 euros') - montant = montant*Decimal('100') + montant = montant * Decimal('100') montant = montant.to_integral_value(ROUND_DOWN) except ValueError: - raise ValueError('MONTANT invalid format, must be ' - 'a decimal integer with less than 4 digits ' - 'before and 2 digits after the decimal point ' - ', here it is %s' % repr(amount)) + raise ValueError( + 'MONTANT invalid format, must be ' + 'a decimal integer with less than 4 digits ' + 'before and 2 digits after the decimal point ' + ', here it is %s' % repr(amount)) automatic_return_url = self.automatic_return_url if next_url and not automatic_return_url: @@ -80,8 +81,8 @@ class Payment(PaymentCommon): "set automatic_return_url in options", DeprecationWarning) automatic_return_url = next_url if automatic_return_url is not None: - if not isinstance(automatic_return_url, str) or \ - not automatic_return_url.startswith('http'): + if (not isinstance(automatic_return_url, str) + or not automatic_return_url.startswith('http')): raise ValueError('URLCL invalid URL format') try: if exer is not None: @@ -102,9 +103,8 @@ class Payment(PaymentCommon): objet = str(objet) except Exception as e: raise ValueError('OBJET must be a string', e) - if not objet.replace(' ','').isalnum(): - raise ValueError('OBJECT must only contains ' - 'alphanumeric characters, %r' % objet) + if not objet.replace(' ', '').isalnum(): + raise ValueError('OBJECT must only contains alphanumeric characters, %r' % objet) if len(objet) > 99: raise ValueError('OBJET length must be less than 100') try: @@ -124,16 +124,16 @@ class Payment(PaymentCommon): iso_now = isonow() transaction_id = '%s_%s' % (iso_now, refdet) if objet: - objet = objet[:100-len(iso_now)-2] + ' ' + iso_now + objet = objet[:100 - len(iso_now) - 2] + ' ' + iso_now else: objet = iso_now params = { - 'numcli': self.numcli, - 'refdet': refdet, - 'montant': montant, - 'mel': mel, - 'saisie': saisie, - 'objet': objet, + 'numcli': self.numcli, + 'refdet': refdet, + 'montant': montant, + 'mel': mel, + 'saisie': saisie, + 'objet': objet, } if exer: params['exer'] = exer @@ -174,9 +174,9 @@ class Payment(PaymentCommon): test = fields.get('saisie') == 'T' return PaymentResponse( - result=result, - bank_status=bank_status, - signed=True, - bank_data=fields, - transaction_id=transaction_id, - test=test) + result=result, + bank_status=bank_status, + signed=True, + bank_data=fields, + transaction_id=transaction_id, + test=test) diff --git a/tests/test_tipi.py b/tests/test_tipi.py index f33bae5..63c3902 100644 --- a/tests/test_tipi.py +++ b/tests/test_tipi.py @@ -1,19 +1,22 @@ from decimal import Decimal from six.moves.urllib.parse import urlparse, parse_qs + import eopayment import pytest + def test_tipi(): p = eopayment.Payment('tipi', {'numcli': '12345'}) - payment_id, kind, url = p.request(amount=Decimal('123.12'), - exer=9999, - refdet=999900000000999999, - objet='tout a fait', - email='info@entrouvert.com', - urlcl='http://example.com/tipi/test', - saisie='T') + payment_id, kind, url = p.request( + amount=Decimal('123.12'), + exer=9999, + refdet=999900000000999999, + objet='tout a fait', + email='info@entrouvert.com', + urlcl='http://example.com/tipi/test', + saisie='T') parsed_qs = parse_qs(urlparse(url).query) - assert parsed_qs['objet'][0].startswith('tout a fait ') + assert parsed_qs['objet'][0].startswith('tout a fait') assert parsed_qs['montant'] == ['12312'] assert parsed_qs['saisie'] == ['T'] assert parsed_qs['mel'] == ['info@entrouvert.com'] @@ -21,7 +24,9 @@ def test_tipi(): assert parsed_qs['exer'] == ['9999'] assert parsed_qs['refdet'] == ['999900000000999999'] - response = p.response('objet=tout+a+fait&montant=12312&saisie=T&mel=info%40entrouvert.com&numcli=12345&exer=9999&refdet=999900000000999999&resultrans=P') + response = p.response( + 'objet=tout+a+fait&montant=12312&saisie=T&mel=info%40entrouvert.com' + '&numcli=12345&exer=9999&refdet=999900000000999999&resultrans=P') assert response.signed # ... assert response.result == eopayment.PAID