From 3d6e233d3648d53f81abcc88b050a28cfbf842cc Mon Sep 17 00:00:00 2001 From: Serghei Mihai Date: Mon, 8 Feb 2016 18:40:45 +0100 Subject: [PATCH] pass order id to all backends (#9941) --- README.txt | 9 +++++++++ eopayment/common.py | 3 +++ eopayment/dummy.py | 10 ++++------ eopayment/ogone.py | 13 +++++++++++-- eopayment/paybox.py | 15 +++++++++++---- eopayment/sips.py | 7 ++++--- eopayment/sips2.py | 6 +++--- eopayment/spplus.py | 7 ++++--- eopayment/systempayv2.py | 13 ++++++++++++- eopayment/tipi.py | 5 +++-- 10 files changed, 64 insertions(+), 24 deletions(-) diff --git a/README.txt b/README.txt index 8591a1f..301797a 100644 --- a/README.txt +++ b/README.txt @@ -29,6 +29,15 @@ reported for logging purpose. 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. +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 ========= diff --git a/eopayment/common.py b/eopayment/common.py index 1aa1ac2..555cda1 100644 --- a/eopayment/common.py +++ b/eopayment/common.py @@ -23,6 +23,9 @@ CANCELLED = 5 CANCELED = 5 # typo for backward compatibility ERROR = 99 +# separator between order and transaction ids +ORDERID_TRANSACTION_SEPARATOR = '!' + class PaymentResponse(object): '''Holds a generic view on the result of payment transaction response. diff --git a/eopayment/dummy.py b/eopayment/dummy.py index 8c0f367..11d1d63 100644 --- a/eopayment/dummy.py +++ b/eopayment/dummy.py @@ -72,7 +72,7 @@ class Payment(PaymentCommon): } 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' ' next_url %s info1 %s info2 %s info3 %s kwargs: %s', __name__, amount, name, address, email, phone, info1, info2, info3, next_url, kwargs) @@ -89,7 +89,7 @@ class Payment(PaymentCommon): 'origin': self.origin } 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(): if query[key] is None: del query[key] @@ -128,13 +128,11 @@ if __name__ == '__main__': 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' r = p.response(retour.split('?',1)[1]) - assert not r[0] + assert not r[0] assert r[1] == '6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T' 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' r = p.response(retour.split('?',1)[1]) - assert r[0] + assert r[0] assert r[1] == '6Tfw2e1bPyYnz7CedZqvdHt7T9XX6T' assert r[3] == 'signature ok' - - diff --git a/eopayment/ogone.py b/eopayment/ogone.py index 281b138..9d65ca0 100644 --- a/eopayment/ogone.py +++ b/eopayment/ogone.py @@ -5,7 +5,7 @@ import urlparse from decimal import Decimal, ROUND_HALF_UP from common import (PaymentCommon, PaymentResponse, FORM, CANCELLED, PAID, - ERROR, Form, DENIED, ACCEPTED) + ERROR, Form, DENIED, ACCEPTED, ORDERID_TRANSACTION_SEPARATOR) def N_(message): return message ENVIRONMENT_TEST = 'TEST' @@ -467,7 +467,13 @@ class Payment(PaymentCommon): def request(self, amount, orderid=None, name=None, email=None, 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: + reference = orderid + ORDERID_TRANSACTION_SEPARATOR + reference + if len(reference) > 30: + raise ValueError("ORDERID's value length exceeds 30 chars") language = language or self.language # convertir en centimes amount = Decimal(amount) * 100 @@ -527,6 +533,9 @@ class Payment(PaymentCommon): self.logger.error('response STATUS=%s NCERROR=%s NCERRORPLUS=%s', status, error, params.get('NCERRORPLUS', '')) 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( result=result, signed=signed, diff --git a/eopayment/paybox.py b/eopayment/paybox.py index 20e3b43..31a90f1 100644 --- a/eopayment/paybox.py +++ b/eopayment/paybox.py @@ -15,7 +15,8 @@ import base64 from gettext import gettext as _ 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'] @@ -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['PBX_SITE'] = unicode(self.site) 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.rang, self.identifiant) 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_RETOUR'] = 'montant:M;reference:R;code_autorisation:A;erreur:E;signature:K' d['PBX_HASH'] = 'SHA512' @@ -252,9 +256,12 @@ class Payment(PaymentCommon): bank_status = PAYBOX_ERROR_CODES.get(prefix + suffix) if bank_status is not None: 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( - order_id=d['reference'][0], + order_id=orderid, signed=signed, bank_data=d, result=result, diff --git a/eopayment/sips.py b/eopayment/sips.py index 028a8f6..73c79d5 100644 --- a/eopayment/sips.py +++ b/eopayment/sips.py @@ -132,13 +132,14 @@ class Payment(PaymentCommon): params.update(self.options) return params - def request(self, amount, name=None, address=None, email=None, phone=None, info1=None, - info2=None, info3=None, next_url=None, **kwargs): + def request(self, amount, name=None, address=None, email=None, phone=None, orderid=None, + info1=None, info2=None, info3=None, next_url=None, **kwargs): params = self.get_request_params() transaction_id = self.transaction_id(6, string.digits, 'sips', params[MERCHANT_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)) if email: params['customer_email'] = email diff --git a/eopayment/sips2.py b/eopayment/sips2.py index 156b4d7..2522028 100644 --- a/eopayment/sips2.py +++ b/eopayment/sips2.py @@ -135,12 +135,12 @@ class Payment(PaymentCommon): def get_url(self): return self.URL[self.platform] - def request(self, amount, name=None, address=None, email=None, phone=None, info1=None, - info2=None, info3=None, next_url=None, **kwargs): + def request(self, amount, name=None, address=None, email=None, phone=None, + orderid=None, info1=None, info2=None, info3=None, next_url=None, **kwargs): data = self.get_data() transaction_id = self.transaction_id(6, string.digits, 'sips2', data['merchantId']) 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)) if email: data['billingContact.email'] = email diff --git a/eopayment/spplus.py b/eopayment/spplus.py index 57e1e5c..1e9b11c 100644 --- a/eopayment/spplus.py +++ b/eopayment/spplus.py @@ -122,8 +122,9 @@ class Payment(PaymentCommon): } devise = '978' - def request(self, amount, name=None, address=None, email=None, phone=None, info1=None, - info2=None, info3=None, next_url=None, logger=LOGGER, **kwargs): + def request(self, amount, name=None, address=None, email=None, phone=None, + 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 \ next_url=%s' % (amount, email, next_url)) reference = self.transaction_id(20, ALPHANUM, 'spplus', self.siret) @@ -134,7 +135,7 @@ next_url=%s' % (amount, email, next_url)) 'langue': self.langue, 'taxe': self.taxe, 'montant': str(Decimal(amount)), - REFERENCE: reference, + REFERENCE: orderid or reference, 'validite': validite, 'version': '1', 'modalite': self.modalite, diff --git a/eopayment/systempayv2.py b/eopayment/systempayv2.py index f975b16..90bb822 100644 --- a/eopayment/systempayv2.py +++ b/eopayment/systempayv2.py @@ -252,7 +252,8 @@ class Payment(PaymentCommon): self.logger = logger or logging.getLogger(__name__) 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 ''' @@ -281,6 +282,16 @@ class Payment(PaymentCommon): kwargs['vads_order_info2'] = unicode(info2) if info3 is not None: 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', self.options[VADS_SITE_ID]) diff --git a/eopayment/tipi.py b/eopayment/tipi.py index 7bb5aaf..763cfa8 100644 --- a/eopayment/tipi.py +++ b/eopayment/tipi.py @@ -48,8 +48,8 @@ class Payment(PaymentCommon): self.numcli = options.pop('numcli', '') self.logger = logger - def request(self, amount, next_url=None, exer=None, refdet=None, - objet=None, email=None, saisie=None, **kwargs): + def request(self, amount, next_url=None, exer=None, orderid=None, + refdet=None, objet=None, email=None, saisie=None, **kwargs): try: montant = Decimal(amount) if Decimal('0') > montant > Decimal('9999.99'): @@ -73,6 +73,7 @@ class Payment(PaymentCommon): 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') -- 2.7.0