pass order id to all backends (#9941)
This commit is contained in:
parent
33ba732c91
commit
8cd625e465
|
@ -29,6 +29,15 @@ reported for logging purpose.
|
||||||
The spplus and paybox module also depend upon the python Crypto library for DES
|
The spplus and paybox module also depend upon the python Crypto library for DES
|
||||||
decoding of the merchant key and RSA signature validation on the responses.
|
decoding of the merchant key and RSA signature validation on the responses.
|
||||||
|
|
||||||
|
Some backends allow to specify the order and transaction ids in different
|
||||||
|
fields, in order to allow to match them in payment system backoffice. They are:
|
||||||
|
- Payzen
|
||||||
|
- SIPS
|
||||||
|
- SystemPay
|
||||||
|
|
||||||
|
For other backends, the order and transaction ids, separated by '!' are sent in
|
||||||
|
order id field, so they can be matched in backoffice.
|
||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,9 @@ CANCELLED = 5
|
||||||
CANCELED = 5 # typo for backward compatibility
|
CANCELED = 5 # typo for backward compatibility
|
||||||
ERROR = 99
|
ERROR = 99
|
||||||
|
|
||||||
|
# separator between order and transaction ids
|
||||||
|
ORDERID_TRANSACTION_SEPARATOR = '!'
|
||||||
|
|
||||||
|
|
||||||
class PaymentResponse(object):
|
class PaymentResponse(object):
|
||||||
'''Holds a generic view on the result of payment transaction response.
|
'''Holds a generic view on the result of payment transaction response.
|
||||||
|
|
|
@ -72,7 +72,7 @@ class Payment(PaymentCommon):
|
||||||
}
|
}
|
||||||
|
|
||||||
def request(self, amount, name=None, address=None, email=None, phone=None,
|
def request(self, amount, name=None, address=None, email=None, phone=None,
|
||||||
info1=None, info2=None, info3=None, next_url=None, **kwargs):
|
orderid=None, info1=None, info2=None, info3=None, next_url=None, **kwargs):
|
||||||
self.logger.debug('%s amount %s name %s address %s email %s phone %s'
|
self.logger.debug('%s amount %s name %s address %s email %s phone %s'
|
||||||
' next_url %s info1 %s info2 %s info3 %s kwargs: %s',
|
' next_url %s info1 %s info2 %s info3 %s kwargs: %s',
|
||||||
__name__, amount, name, address, email, phone, info1, info2, info3, next_url, kwargs)
|
__name__, amount, name, address, email, phone, info1, info2, info3, next_url, kwargs)
|
||||||
|
@ -89,7 +89,7 @@ class Payment(PaymentCommon):
|
||||||
'origin': self.origin
|
'origin': self.origin
|
||||||
}
|
}
|
||||||
query.update(dict(name=name, address=address, email=email, phone=phone,
|
query.update(dict(name=name, address=address, email=email, phone=phone,
|
||||||
info1=info1, info2=info2, info3=info3))
|
orderid=orderid, info1=info1, info2=info2, info3=info3))
|
||||||
for key in query.keys():
|
for key in query.keys():
|
||||||
if query[key] is None:
|
if query[key] is None:
|
||||||
del query[key]
|
del query[key]
|
||||||
|
@ -128,13 +128,11 @@ if __name__ == '__main__':
|
||||||
p = Payment(options)
|
p = Payment(options)
|
||||||
retour = 'http://example.com/retour?amount=10.0&direct_notification_url=http%3A%2F%2Fexample.com%2Fdirect_notification_url&email=toto%40example.com&transaction_id=6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T&return_url=http%3A%2F%2Fexample.com%2Fretour&nok=1'
|
retour = 'http://example.com/retour?amount=10.0&direct_notification_url=http%3A%2F%2Fexample.com%2Fdirect_notification_url&email=toto%40example.com&transaction_id=6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T&return_url=http%3A%2F%2Fexample.com%2Fretour&nok=1'
|
||||||
r = p.response(retour.split('?',1)[1])
|
r = p.response(retour.split('?',1)[1])
|
||||||
assert not r[0]
|
assert not r[0]
|
||||||
assert r[1] == '6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T'
|
assert r[1] == '6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T'
|
||||||
assert r[3] is None
|
assert r[3] is None
|
||||||
retour = 'http://example.com/retour?amount=10.0&direct_notification_url=http%3A%2F%2Fexample.com%2Fdirect_notification_url&email=toto%40example.com&transaction_id=6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T&return_url=http%3A%2F%2Fexample.com%2Fretour&ok=1&signed=1'
|
retour = 'http://example.com/retour?amount=10.0&direct_notification_url=http%3A%2F%2Fexample.com%2Fdirect_notification_url&email=toto%40example.com&transaction_id=6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T&return_url=http%3A%2F%2Fexample.com%2Fretour&ok=1&signed=1'
|
||||||
r = p.response(retour.split('?',1)[1])
|
r = p.response(retour.split('?',1)[1])
|
||||||
assert r[0]
|
assert r[0]
|
||||||
assert r[1] == '6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T'
|
assert r[1] == '6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T'
|
||||||
assert r[3] == 'signature ok'
|
assert r[3] == 'signature ok'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import urlparse
|
||||||
from decimal import Decimal, ROUND_HALF_UP
|
from decimal import Decimal, ROUND_HALF_UP
|
||||||
|
|
||||||
from common import (PaymentCommon, PaymentResponse, FORM, CANCELLED, PAID,
|
from common import (PaymentCommon, PaymentResponse, FORM, CANCELLED, PAID,
|
||||||
ERROR, Form, DENIED, ACCEPTED)
|
ERROR, Form, DENIED, ACCEPTED, ORDERID_TRANSACTION_SEPARATOR)
|
||||||
def N_(message): return message
|
def N_(message): return message
|
||||||
|
|
||||||
ENVIRONMENT_TEST = 'TEST'
|
ENVIRONMENT_TEST = 'TEST'
|
||||||
|
@ -467,7 +467,14 @@ class Payment(PaymentCommon):
|
||||||
|
|
||||||
def request(self, amount, orderid=None, name=None, email=None,
|
def request(self, amount, orderid=None, name=None, email=None,
|
||||||
language=None, description=None, **kwargs):
|
language=None, description=None, **kwargs):
|
||||||
reference = orderid or self.transaction_id(20, string.digits + string.ascii_letters)
|
|
||||||
|
reference = self.transaction_id(20, string.digits + string.ascii_letters)
|
||||||
|
|
||||||
|
# prepend order id in payment reference
|
||||||
|
if orderid:
|
||||||
|
if len(orderid) > 24:
|
||||||
|
raise ValueError('orderid length exceeds 25 characters')
|
||||||
|
reference = orderid + ORDERID_TRANSACTION_SEPARATOR + self.transaction_id(29-len(orderid), string.digits + string.ascii_letters)
|
||||||
language = language or self.language
|
language = language or self.language
|
||||||
# convertir en centimes
|
# convertir en centimes
|
||||||
amount = Decimal(amount) * 100
|
amount = Decimal(amount) * 100
|
||||||
|
@ -527,6 +534,9 @@ class Payment(PaymentCommon):
|
||||||
self.logger.error('response STATUS=%s NCERROR=%s NCERRORPLUS=%s',
|
self.logger.error('response STATUS=%s NCERROR=%s NCERRORPLUS=%s',
|
||||||
status, error, params.get('NCERRORPLUS', ''))
|
status, error, params.get('NCERRORPLUS', ''))
|
||||||
result = ERROR
|
result = ERROR
|
||||||
|
# extract reference from received order id
|
||||||
|
if ORDERID_TRANSACTION_SEPARATOR in reference:
|
||||||
|
reference, transaction_id = reference.split(ORDERID_TRANSACTION_SEPARATOR, 1)
|
||||||
return PaymentResponse(
|
return PaymentResponse(
|
||||||
result=result,
|
result=result,
|
||||||
signed=signed,
|
signed=signed,
|
||||||
|
|
|
@ -15,7 +15,8 @@ import base64
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
import string
|
import string
|
||||||
|
|
||||||
from common import PaymentCommon, PaymentResponse, FORM, PAID, ERROR, Form
|
from common import (PaymentCommon, PaymentResponse, FORM, PAID, ERROR, Form,
|
||||||
|
ORDERID_TRANSACTION_SEPARATOR)
|
||||||
|
|
||||||
__all__ = ['sign', 'Payment']
|
__all__ = ['sign', 'Payment']
|
||||||
|
|
||||||
|
@ -192,7 +193,7 @@ class Payment(PaymentCommon):
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
def request(self, amount, email, name=None, **kwargs):
|
def request(self, amount, email, name=None, orderid=None, **kwargs):
|
||||||
d = OrderedDict()
|
d = OrderedDict()
|
||||||
d['PBX_SITE'] = unicode(self.site)
|
d['PBX_SITE'] = unicode(self.site)
|
||||||
d['PBX_RANG'] = unicode(self.rang).strip()[-2:]
|
d['PBX_RANG'] = unicode(self.rang).strip()[-2:]
|
||||||
|
@ -203,6 +204,9 @@ class Payment(PaymentCommon):
|
||||||
self.transaction_id(12, string.digits, 'paybox', self.site,
|
self.transaction_id(12, string.digits, 'paybox', self.site,
|
||||||
self.rang, self.identifiant)
|
self.rang, self.identifiant)
|
||||||
d['PBX_CMD'] = unicode(transaction_id)
|
d['PBX_CMD'] = unicode(transaction_id)
|
||||||
|
# prepend order id command reference
|
||||||
|
if orderid:
|
||||||
|
d['PBX_CMD'] = orderid + ORDERID_TRANSACTION_SEPARATOR + d['PBX_CMD']
|
||||||
d['PBX_PORTEUR'] = unicode(email)
|
d['PBX_PORTEUR'] = unicode(email)
|
||||||
d['PBX_RETOUR'] = 'montant:M;reference:R;code_autorisation:A;erreur:E;signature:K'
|
d['PBX_RETOUR'] = 'montant:M;reference:R;code_autorisation:A;erreur:E;signature:K'
|
||||||
d['PBX_HASH'] = 'SHA512'
|
d['PBX_HASH'] = 'SHA512'
|
||||||
|
@ -252,9 +256,12 @@ class Payment(PaymentCommon):
|
||||||
bank_status = PAYBOX_ERROR_CODES.get(prefix + suffix)
|
bank_status = PAYBOX_ERROR_CODES.get(prefix + suffix)
|
||||||
if bank_status is not None:
|
if bank_status is not None:
|
||||||
break
|
break
|
||||||
|
orderid = d['reference'][0]
|
||||||
|
# decode order id from returned reference
|
||||||
|
if ORDERID_TRANSACTION_SEPARATOR in orderid:
|
||||||
|
orderid, transaction_id = orderid.split(ORDERID_TRANSACTION_SEPARATOR, 1)
|
||||||
return PaymentResponse(
|
return PaymentResponse(
|
||||||
order_id=d['reference'][0],
|
order_id=orderid,
|
||||||
signed=signed,
|
signed=signed,
|
||||||
bank_data=d,
|
bank_data=d,
|
||||||
result=result,
|
result=result,
|
||||||
|
|
|
@ -132,13 +132,14 @@ class Payment(PaymentCommon):
|
||||||
params.update(self.options)
|
params.update(self.options)
|
||||||
return params
|
return params
|
||||||
|
|
||||||
def request(self, amount, name=None, address=None, email=None, phone=None, info1=None,
|
def request(self, amount, name=None, address=None, email=None, phone=None, orderid=None,
|
||||||
info2=None, info3=None, next_url=None, **kwargs):
|
info1=None, info2=None, info3=None, next_url=None, **kwargs):
|
||||||
params = self.get_request_params()
|
params = self.get_request_params()
|
||||||
transaction_id = self.transaction_id(6, string.digits, 'sips',
|
transaction_id = self.transaction_id(6, string.digits, 'sips',
|
||||||
params[MERCHANT_ID])
|
params[MERCHANT_ID])
|
||||||
params[TRANSACTION_ID] = transaction_id
|
params[TRANSACTION_ID] = transaction_id
|
||||||
params[ORDER_ID] = str(uuid.uuid4()).replace('-', '')
|
params[ORDER_ID] = orderid or str(uuid.uuid4())
|
||||||
|
params[ORDER_ID] = params[ORDER_ID].replace('-', '')
|
||||||
params['amount'] = str(int(Decimal(amount) * 100))
|
params['amount'] = str(int(Decimal(amount) * 100))
|
||||||
if email:
|
if email:
|
||||||
params['customer_email'] = email
|
params['customer_email'] = email
|
||||||
|
|
|
@ -135,12 +135,12 @@ class Payment(PaymentCommon):
|
||||||
def get_url(self):
|
def get_url(self):
|
||||||
return self.URL[self.platform]
|
return self.URL[self.platform]
|
||||||
|
|
||||||
def request(self, amount, name=None, address=None, email=None, phone=None, info1=None,
|
def request(self, amount, name=None, address=None, email=None, phone=None,
|
||||||
info2=None, info3=None, next_url=None, **kwargs):
|
orderid=None, info1=None, info2=None, info3=None, next_url=None, **kwargs):
|
||||||
data = self.get_data()
|
data = self.get_data()
|
||||||
transaction_id = self.transaction_id(6, string.digits, 'sips2', data['merchantId'])
|
transaction_id = self.transaction_id(6, string.digits, 'sips2', data['merchantId'])
|
||||||
data['transactionReference'] = unicode(transaction_id)
|
data['transactionReference'] = unicode(transaction_id)
|
||||||
data['orderId'] = unicode(uuid.uuid4()).replace('-', '')
|
data['orderId'] = orderid or unicode(uuid.uuid4()).replace('-', '')
|
||||||
data['amount'] = unicode(int(Decimal(amount) * 100))
|
data['amount'] = unicode(int(Decimal(amount) * 100))
|
||||||
if email:
|
if email:
|
||||||
data['billingContact.email'] = email
|
data['billingContact.email'] = email
|
||||||
|
|
|
@ -122,8 +122,9 @@ class Payment(PaymentCommon):
|
||||||
}
|
}
|
||||||
devise = '978'
|
devise = '978'
|
||||||
|
|
||||||
def request(self, amount, name=None, address=None, email=None, phone=None, info1=None,
|
def request(self, amount, name=None, address=None, email=None, phone=None,
|
||||||
info2=None, info3=None, next_url=None, logger=LOGGER, **kwargs):
|
orderid=None, info1=None, info2=None, info3=None, next_url=None,
|
||||||
|
logger=LOGGER, **kwargs):
|
||||||
logger.debug('requesting spplus payment with montant %s email=%s and \
|
logger.debug('requesting spplus payment with montant %s email=%s and \
|
||||||
next_url=%s' % (amount, email, next_url))
|
next_url=%s' % (amount, email, next_url))
|
||||||
reference = self.transaction_id(20, ALPHANUM, 'spplus', self.siret)
|
reference = self.transaction_id(20, ALPHANUM, 'spplus', self.siret)
|
||||||
|
@ -134,7 +135,7 @@ next_url=%s' % (amount, email, next_url))
|
||||||
'langue': self.langue,
|
'langue': self.langue,
|
||||||
'taxe': self.taxe,
|
'taxe': self.taxe,
|
||||||
'montant': str(Decimal(amount)),
|
'montant': str(Decimal(amount)),
|
||||||
REFERENCE: reference,
|
REFERENCE: orderid or reference,
|
||||||
'validite': validite,
|
'validite': validite,
|
||||||
'version': '1',
|
'version': '1',
|
||||||
'modalite': self.modalite,
|
'modalite': self.modalite,
|
||||||
|
|
|
@ -252,7 +252,8 @@ class Payment(PaymentCommon):
|
||||||
self.logger = logger or logging.getLogger(__name__)
|
self.logger = logger or logging.getLogger(__name__)
|
||||||
|
|
||||||
def request(self, amount, name=None, address=None, email=None, phone=None,
|
def request(self, amount, name=None, address=None, email=None, phone=None,
|
||||||
info1=None, info2=None, info3=None, next_url=None, **kwargs):
|
orderid=None, info1=None, info2=None, info3=None,
|
||||||
|
next_url=None, **kwargs):
|
||||||
'''
|
'''
|
||||||
Create the URL string to send a request to SystemPay
|
Create the URL string to send a request to SystemPay
|
||||||
'''
|
'''
|
||||||
|
@ -281,6 +282,16 @@ class Payment(PaymentCommon):
|
||||||
kwargs['vads_order_info2'] = unicode(info2)
|
kwargs['vads_order_info2'] = unicode(info2)
|
||||||
if info3 is not None:
|
if info3 is not None:
|
||||||
kwargs['vads_order_info3'] = unicode(info3)
|
kwargs['vads_order_info3'] = unicode(info3)
|
||||||
|
if orderid is not None:
|
||||||
|
# check orderid format first
|
||||||
|
name = 'vads_order_id'
|
||||||
|
orderid = unicode(orderid)
|
||||||
|
ptype = 'an-'
|
||||||
|
p = Parameter(name, ptype, 13, max_length=32)
|
||||||
|
if not p.check_value(orderid):
|
||||||
|
raise ValueError('%s value %s is not of the type %s' % (name,
|
||||||
|
orderid, ptype))
|
||||||
|
kwargs[name] = orderid
|
||||||
|
|
||||||
transaction_id = self.transaction_id(6, string.digits, 'systempay',
|
transaction_id = self.transaction_id(6, string.digits, 'systempay',
|
||||||
self.options[VADS_SITE_ID])
|
self.options[VADS_SITE_ID])
|
||||||
|
|
|
@ -48,8 +48,8 @@ class Payment(PaymentCommon):
|
||||||
self.numcli = options.pop('numcli', '')
|
self.numcli = options.pop('numcli', '')
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
|
|
||||||
def request(self, amount, next_url=None, exer=None, refdet=None,
|
def request(self, amount, next_url=None, exer=None, orderid=None,
|
||||||
objet=None, email=None, saisie=None, **kwargs):
|
refdet=None, objet=None, email=None, saisie=None, **kwargs):
|
||||||
try:
|
try:
|
||||||
montant = Decimal(amount)
|
montant = Decimal(amount)
|
||||||
if Decimal('0') > montant > Decimal('9999.99'):
|
if Decimal('0') > montant > Decimal('9999.99'):
|
||||||
|
@ -73,6 +73,7 @@ class Payment(PaymentCommon):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError('EXER format invalide')
|
raise ValueError('EXER format invalide')
|
||||||
try:
|
try:
|
||||||
|
refdet = orderid or refdet
|
||||||
refdet = str(refdet)
|
refdet = str(refdet)
|
||||||
if 6 > len(refdet) > 30:
|
if 6 > len(refdet) > 30:
|
||||||
raise ValueError('len(REFDET) < 6 or > 30')
|
raise ValueError('len(REFDET) < 6 or > 30')
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
from unittest import TestCase
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
import eopayment
|
||||||
|
import eopayment.ogone as ogone
|
||||||
|
|
||||||
|
PSPID = '2352566'
|
||||||
|
|
||||||
|
BACKEND_PARAMS = {
|
||||||
|
'environment': ogone.ENVIRONMENT_TEST,
|
||||||
|
'pspid': PSPID,
|
||||||
|
'sha_in': 'secret',
|
||||||
|
'sha_out': 'secret'
|
||||||
|
}
|
||||||
|
|
||||||
|
class OgoneTests(TestCase):
|
||||||
|
|
||||||
|
def test_request(self):
|
||||||
|
ogone_backend = eopayment.Payment('ogone', BACKEND_PARAMS)
|
||||||
|
amount = '42.42'
|
||||||
|
order_id = 'myorder'
|
||||||
|
reference, kind, what = ogone_backend.request(amount=amount,
|
||||||
|
orderid=order_id, email='foo@example.com')
|
||||||
|
self.assertEqual(len(reference), 30)
|
||||||
|
assert reference.startswith(order_id)
|
||||||
|
from xml.etree import ElementTree as ET
|
||||||
|
root = ET.fromstring(str(what))
|
||||||
|
self.assertEqual(root.tag, 'form')
|
||||||
|
self.assertEqual(root.attrib['method'], 'POST')
|
||||||
|
self.assertEqual(root.attrib['action'], ogone.ENVIRONMENT_TEST_URL)
|
||||||
|
values = {
|
||||||
|
'CURRENCY': 'EUR',
|
||||||
|
'ORDERID': reference,
|
||||||
|
'PSPID': PSPID,
|
||||||
|
'EMAIL': 'foo@example.com',
|
||||||
|
'AMOUNT': amount.replace('.', ''),
|
||||||
|
'LANGUAGE': 'fr_FR',
|
||||||
|
}
|
||||||
|
values.update({'SHASIGN': ogone_backend.backend.sha_sign_in(values)})
|
||||||
|
for node in root:
|
||||||
|
self.assertIn(node.attrib['type'], ('hidden', 'submit'))
|
||||||
|
self.assertEqual(set(node.attrib.keys()), set(['type', 'name', 'value']))
|
||||||
|
name = node.attrib['name']
|
||||||
|
if node.attrib['type'] == 'hidden':
|
||||||
|
self.assertIn(name, values)
|
||||||
|
self.assertEqual(node.attrib['value'], values[name])
|
||||||
|
|
||||||
|
def test_response(self):
|
||||||
|
ogone_backend = eopayment.Payment('ogone', BACKEND_PARAMS)
|
||||||
|
order_id = 'myorder'
|
||||||
|
data = {'orderid': order_id + eopayment.common.ORDERID_TRANSACTION_SEPARATOR + 'RtEpMXZn4dX8k1rYbwLlby',
|
||||||
|
'payid': '32100123', 'status': 9, 'ncerror': 0}
|
||||||
|
response = ogone_backend.response(urllib.urlencode(data))
|
||||||
|
self.assertEqual(response.order_id, order_id)
|
|
@ -1,18 +1,28 @@
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
import base64
|
import base64
|
||||||
|
import urllib
|
||||||
|
|
||||||
import eopayment.paybox as paybox
|
import eopayment.paybox as paybox
|
||||||
import eopayment
|
import eopayment
|
||||||
|
|
||||||
|
BACKEND_PARAMS = {
|
||||||
|
'platform': 'test',
|
||||||
|
'site': '12345678',
|
||||||
|
'rang': '001',
|
||||||
|
'identifiant': '12345678',
|
||||||
|
'shared_secret': '0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF',
|
||||||
|
'callback': 'http://example.com/callback',
|
||||||
|
}
|
||||||
|
|
||||||
class PayboxTests(TestCase):
|
class PayboxTests(TestCase):
|
||||||
def test_sign(self):
|
def test_sign(self):
|
||||||
key = '0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF'.decode('hex')
|
key = '0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF'.decode('hex')
|
||||||
d = dict(paybox.sign([
|
d = dict(paybox.sign([
|
||||||
['PBX_SITE', '1999888'],
|
['PBX_SITE', '12345678'],
|
||||||
['PBX_RANG', '32'],
|
['PBX_RANG', '32'],
|
||||||
['PBX_IDENTIFIANT', '110647233'],
|
['PBX_IDENTIFIANT', '12345678'],
|
||||||
['PBX_TOTAL', '999'],
|
['PBX_TOTAL', '999'],
|
||||||
['PBX_DEVISE', '978'],
|
['PBX_DEVISE', '978'],
|
||||||
['PBX_CMD', 'TEST Paybox'],
|
['PBX_CMD', 'TEST Paybox'],
|
||||||
['PBX_PORTEUR', 'test@paybox.com'],
|
['PBX_PORTEUR', 'test@paybox.com'],
|
||||||
|
@ -21,25 +31,20 @@ class PayboxTests(TestCase):
|
||||||
['PBX_TIME', '2015-06-08T16:21:16+02:00'],
|
['PBX_TIME', '2015-06-08T16:21:16+02:00'],
|
||||||
],
|
],
|
||||||
key))
|
key))
|
||||||
result = '7ABB5F7A31DF4C8976A44374D3BA2F9831E7927CFD62F774ED378F4E27471708F4EFE6D0BEFA44EBABCBD978B661C74E22EEB16DEF73A510E86D0A5C0E7B6D88'
|
result = '475FE1C45A0D09D26D2CAC9A1AC39C024773D790F50B6DD15B260F55FCD527FD3AD4AA3998F4162EFE9BDC494B9850A673355A32ACC4F85B67F8566037836F8E'
|
||||||
self.assertIn('PBX_HMAC', d)
|
self.assertIn('PBX_HMAC', d)
|
||||||
self.assertEqual(d['PBX_HMAC'], result)
|
self.assertEqual(d['PBX_HMAC'], result)
|
||||||
|
|
||||||
def test_request(self):
|
def test_request(self):
|
||||||
key = '0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF'
|
backend = eopayment.Payment('paybox', BACKEND_PARAMS)
|
||||||
backend = eopayment.Payment('paybox', {
|
|
||||||
'platform': 'test',
|
|
||||||
'site': '12345678',
|
|
||||||
'rang': '001',
|
|
||||||
'identifiant': '12345678',
|
|
||||||
'shared_secret': key,
|
|
||||||
'callback': 'http://example.com/callback',
|
|
||||||
})
|
|
||||||
time = '2015-07-15T18:26:32+02:00'
|
time = '2015-07-15T18:26:32+02:00'
|
||||||
email = 'bdauvergne@entrouvert.com'
|
email = 'bdauvergne@entrouvert.com'
|
||||||
|
order_id = '20160216'
|
||||||
|
transaction = '1234'
|
||||||
|
amount = '19.99'
|
||||||
transaction_id, kind, what = backend.request(
|
transaction_id, kind, what = backend.request(
|
||||||
Decimal('19.99'), email=email,
|
Decimal(amount), email=email, orderid=order_id,
|
||||||
transaction_id='1234', time=time)
|
transaction_id=transaction, time=time)
|
||||||
self.assertEqual(kind, eopayment.FORM)
|
self.assertEqual(kind, eopayment.FORM)
|
||||||
self.assertEqual(transaction_id, '1234')
|
self.assertEqual(transaction_id, '1234')
|
||||||
from xml.etree import ElementTree as ET
|
from xml.etree import ElementTree as ET
|
||||||
|
@ -54,6 +59,7 @@ class PayboxTests(TestCase):
|
||||||
if node.attrib['type'] == 'hidden':
|
if node.attrib['type'] == 'hidden':
|
||||||
self.assertEqual(set(node.attrib.keys()), set(['type', 'name', 'value']))
|
self.assertEqual(set(node.attrib.keys()), set(['type', 'name', 'value']))
|
||||||
name = node.attrib['name']
|
name = node.attrib['name']
|
||||||
|
reference = order_id + eopayment.common.ORDERID_TRANSACTION_SEPARATOR + transaction
|
||||||
values = {
|
values = {
|
||||||
'PBX_RANG': '01',
|
'PBX_RANG': '01',
|
||||||
'PBX_SITE': '12345678',
|
'PBX_SITE': '12345678',
|
||||||
|
@ -61,17 +67,27 @@ class PayboxTests(TestCase):
|
||||||
'PBX_RETOUR': 'montant:M;reference:R;code_autorisation:A;erreur:E;signature:K',
|
'PBX_RETOUR': 'montant:M;reference:R;code_autorisation:A;erreur:E;signature:K',
|
||||||
'PBX_TIME': time,
|
'PBX_TIME': time,
|
||||||
'PBX_PORTEUR': email,
|
'PBX_PORTEUR': email,
|
||||||
'PBX_CMD': '1234',
|
'PBX_CMD': reference,
|
||||||
'PBX_TOTAL': '1999',
|
'PBX_TOTAL': amount.replace('.', ''),
|
||||||
'PBX_DEVISE': '978',
|
'PBX_DEVISE': '978',
|
||||||
'PBX_HASH': 'SHA512',
|
'PBX_HASH': 'SHA512',
|
||||||
'PBX_HMAC': 'A0AA37FC3DD46F3233C0AD3BF95242CD71003D98F33DF85124E4423D53759A82A132EC2CC42B7234B22A75F00CF5DA124DF3A34331F3F6B9D7308B2EF09DCA3C',
|
'PBX_HMAC': '173483CFF84A7ECF21039F99E9A95C5FB53D98A1562184F5B2C4543E4F87BFA227CC2CA10DE989D6C8B4DC03BC2ED44B7D7BDF5B4FABA8274D5D37C2F6445F36',
|
||||||
'PBX_ARCHIVAGE': '1234',
|
'PBX_ARCHIVAGE': '1234',
|
||||||
'PBX_REPONDRE_A': 'http://example.com/callback',
|
'PBX_REPONDRE_A': 'http://example.com/callback',
|
||||||
}
|
}
|
||||||
self.assertIn(name, values)
|
self.assertIn(name, values)
|
||||||
self.assertEqual(node.attrib['value'], values[name])
|
self.assertEqual(node.attrib['value'], values[name])
|
||||||
|
|
||||||
|
def test_response(self):
|
||||||
|
backend = eopayment.Payment('paybox', BACKEND_PARAMS)
|
||||||
|
order_id = '20160216'
|
||||||
|
transaction = '1234'
|
||||||
|
reference = order_id + eopayment.common.ORDERID_TRANSACTION_SEPARATOR + transaction
|
||||||
|
data = {'montant': '4242', 'reference': reference,
|
||||||
|
'code_autorisation': 'A', 'erreur': '00000'}
|
||||||
|
response = backend.response(urllib.urlencode(data))
|
||||||
|
self.assertEqual(response.order_id, order_id)
|
||||||
|
|
||||||
def test_rsa_signature_validation(self):
|
def test_rsa_signature_validation(self):
|
||||||
pkey = '''-----BEGIN PUBLIC KEY-----
|
pkey = '''-----BEGIN PUBLIC KEY-----
|
||||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUgYufHuheMztK1LhQSG6xsOzb
|
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUgYufHuheMztK1LhQSG6xsOzb
|
||||||
|
|
Loading…
Reference in New Issue