tipi: implement automatic generation of REFDET (fixes #30272)
This commit is contained in:
parent
51a51d1201
commit
7ac96b4f1e
|
@ -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))
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue