summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eopayment/tipi.py53
-rw-r--r--tests/test_tipi.py59
2 files changed, 91 insertions, 21 deletions
diff --git a/eopayment/tipi.py b/eopayment/tipi.py
index c53101e..015e939 100644
--- a/eopayment/tipi.py
+++ b/eopayment/tipi.py
@@ -1,4 +1,7 @@
+import re
+import random
from decimal import Decimal, ROUND_DOWN
+
from .common import (PaymentCommon, PaymentResponse, URL, PAID, DENIED,
CANCELLED, ERROR, ResponseError)
from six.moves.urllib.parse import urlencode, parse_qs
@@ -64,6 +67,11 @@ class Payment(PaymentCommon):
],
}
+ REFDET_RE = re.compile('^[a-zA-Z0-9]{6,30}$')
+
+ def _generate_refdet(self):
+ return '%s%10d' % (isonow(), random.randint(1, 1000000000))
+
def request(self, amount, next_url=None, exer=None, orderid=None,
refdet=None, objet=None, email=None, saisie=None, **kwargs):
try:
@@ -95,22 +103,30 @@ class Payment(PaymentCommon):
raise ValueError()
except ValueError:
raise ValueError('EXER format invalide')
- try:
- refdet = orderid or refdet
- refdet = str(refdet)
- if 6 > len(refdet) > 30:
- raise ValueError('len(REFDET) < 6 or > 30')
- except Exception as e:
- raise ValueError('REFDET format invalide, %r' % refdet, e)
+ assert not (orderid and refdet), 'orderid and refdet cannot be used together'
+ # check or generate refdet
+ if refdet:
+ try:
+ if not self.REFDET_RE.match(refdet):
+ raise ValueError
+ except (TypeError, ValueError):
+ raise ValueError('refdet must be 6 to 30 alphanumeric characters string')
+ if orderid:
+ if self.REFDET_RE.match(orderid):
+ refdet = orderid
+ else:
+ objet = orderid + (' ' + objet) if objet else ''
+ if not refdet:
+ refdet = self._generate_refdet()
+ transaction_id = refdet
+ else:
+ transaction_id = '%s_%s' % (refdet, random.randint(1, 1000000000))
+ # check objet or fix objet
if objet is not None:
try:
- objet = str(objet)
+ objet = objet.encode('ascii')
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 len(objet) > 99:
- raise ValueError('OBJET length must be less than 100')
+ raise ValueError('OBJET must be an alphanumeric string', e)
try:
mel = str(email)
if '@' not in mel:
@@ -120,27 +136,22 @@ class Payment(PaymentCommon):
except Exception as e:
raise ValueError('MEL is not a valid email, %r' % mel, e)
+ # check saisie
saisie = saisie or self.saisie
-
if saisie not in ('M', 'T', 'X', 'A'):
raise ValueError('SAISIE invalid format, %r, must be M, T, X or A' % saisie)
- iso_now = isonow()
- transaction_id = '%s_%s' % (iso_now, refdet)
- if objet:
- 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,
}
if exer:
params['exer'] = exer
+ if objet:
+ params['objet'] = objet
if automatic_return_url:
params['urlcl'] = automatic_return_url
url = '%s?%s' % (self.service_url, urlencode(params))
diff --git a/tests/test_tipi.py b/tests/test_tipi.py
index 63c3902..cf30540 100644
--- a/tests/test_tipi.py
+++ b/tests/test_tipi.py
@@ -1,7 +1,9 @@
+import datetime
from decimal import Decimal
from six.moves.urllib.parse import urlparse, parse_qs
import eopayment
+import eopayment.tipi
import pytest
@@ -32,3 +34,60 @@ def test_tipi():
with pytest.raises(eopayment.ResponseError, match='missing refdet or resultrans'):
p.response('foo=bar')
+
+
+def test_tipi_no_orderid_no_refdet():
+ p = eopayment.Payment('tipi', {'numcli': '12345'})
+ payment_id, kind, url = p.request(
+ amount=Decimal('123.12'),
+ exer=9999,
+ email='info@entrouvert.com',
+ saisie='T')
+ parsed_qs = parse_qs(urlparse(url).query)
+ assert 'objet' not in parsed_qs
+ assert parsed_qs['montant'] == ['12312']
+ assert parsed_qs['saisie'] == ['T']
+ assert parsed_qs['mel'] == ['info@entrouvert.com']
+ assert parsed_qs['numcli'] == ['12345']
+ assert parsed_qs['exer'] == ['9999']
+ assert parsed_qs['refdet'][0].startswith(datetime.datetime.now().strftime('%Y%m%d'))
+
+
+def test_tipi_orderid_refdef_compatible():
+ p = eopayment.Payment('tipi', {'numcli': '12345', 'saisie': 'A'})
+ payment_id, kind, url = p.request(
+ amount=Decimal('123.12'),
+ email='info@entrouvert.com',
+ orderid='F121212')
+ expected_url = urlparse(eopayment.tipi.TIPI_URL)
+ parsed_url = urlparse(url)
+ assert parsed_url[:3] == expected_url[:3]
+ parsed_qs = parse_qs(parsed_url.query)
+ assert 'objet' not in parsed_qs
+ assert 'exer' not in parsed_qs
+ assert parsed_qs['montant'] == ['12312']
+ assert parsed_qs['saisie'] == ['A']
+ assert parsed_qs['mel'] == ['info@entrouvert.com']
+ assert parsed_qs['numcli'] == ['12345']
+ assert parsed_qs['refdet'] == ['F121212']
+
+
+def test_tipi_orderid_not_refdef_compatible():
+ p = eopayment.Payment('tipi', {'numcli': '12345', 'saisie': 'A'})
+ payment_id, kind, url = p.request(
+ amount=Decimal('123.12'),
+ email='info@entrouvert.com',
+ objet='coucou',
+ orderid='F12-12-12')
+ expected_url = urlparse(eopayment.tipi.TIPI_URL)
+ parsed_url = urlparse(url)
+ assert parsed_url[:3] == expected_url[:3]
+ parsed_qs = parse_qs(parsed_url.query)
+ assert 'exer' not in parsed_qs
+ assert parsed_qs['montant'] == ['12312']
+ assert parsed_qs['saisie'] == ['A']
+ assert parsed_qs['mel'] == ['info@entrouvert.com']
+ assert parsed_qs['numcli'] == ['12345']
+ assert parsed_qs['refdet'][0].startswith(datetime.datetime.now().strftime('%Y%m%d'))
+ assert 'coucou' in parsed_qs['objet'][0]
+ assert 'F12-12-12' in parsed_qs['objet'][0]