From efa3525186b4f94afe1550ec552ebfe33baa8e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Tue, 16 Feb 2016 10:51:41 +0100 Subject: [PATCH] standardise normal_return_url and automatic_return_url options (#9998) --- eopayment/__init__.py | 4 +--- eopayment/dummy.py | 52 ++++++++++++++++++++++++++++++++++-------------- eopayment/ogone.py | 17 ++++++++++++++++ eopayment/paybox.py | 31 +++++++++++++++++++++++++---- eopayment/sips.py | 9 +++++++-- eopayment/sips2.py | 12 +++++++++-- eopayment/spplus.py | 32 +++++++++++++++++++++-------- eopayment/systempayv2.py | 19 +++++++++++++++++- eopayment/tipi.py | 29 +++++++++++++++++++++------ 9 files changed, 164 insertions(+), 41 deletions(-) diff --git a/eopayment/__init__.py b/eopayment/__init__.py index 1d5dade..39441c8 100644 --- a/eopayment/__init__.py +++ b/eopayment/__init__.py @@ -45,8 +45,7 @@ class Payment(object): 'siret': '00000000000001-01', \ } >>> p = Payment(kind=SPPLUS, options=spplus_options) - >>> transaction_id, kind, data = p.request('10.00', email='bob@example.com', \ - next_url='https://my-site.com') + >>> transaction_id, kind, data = p.request('10.00', email='bob@example.com') >>> print (transaction_id, kind, data) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE ('...', 1, 'https://www.spplus.net/paiement/init.do?...') @@ -86,7 +85,6 @@ class Payment(object): Arguments: amount -- the amount of money to ask email -- the email of the customer (optional) - next_url -- the URL where the customer will be returned (optional), usually redundant with the hardwired settings in the bank configuration panel. At this url you must use the Payment.response method to analyze the bank returned values. diff --git a/eopayment/dummy.py b/eopayment/dummy.py index 8c0f367..fa5d3aa 100644 --- a/eopayment/dummy.py +++ b/eopayment/dummy.py @@ -1,6 +1,7 @@ import urllib import string import logging +import warnings try: from cgi import parse_qs @@ -27,26 +28,33 @@ class Payment(PaymentCommon): You must pass the following keys inside the options dictionnary: - dummy_service_url, the URL of the dummy payment service, it defaults to the one operated by Entr'ouvert. - - direct_notification_url: where to POST to notify the service of a + - automatic_return_url: where to POST to notify the service of a payment - origin: a human string to display to the user about the origin of the request. - siret: an identifier for the eCommerce site, fake. - - next_url: the return URL for the user (can be overriden on a per - request basis). + - normal_return_url: the return URL for the user (can be overriden on a + per request basis). ''' description = { 'caption': 'Dummy payment backend', 'parameters': [ + { + 'name': 'normal_return_url', + 'caption': _('Normal return URL'), + 'default': '', + 'required': True, + }, + { + 'name': 'automatic_return_url', + 'caption': _('Automatic return URL'), + 'required': False, + }, { 'name': 'dummy_service_url', 'caption': 'URL of the dummy payment service', 'default': SERVICE_URL, 'type': str, }, - { 'name': 'direct_notification_url', - 'caption': 'direct notification url', - 'type': str, - }, { 'name': 'origin', 'caption': 'name of the requesting service, ' 'to present in the user interface', @@ -57,10 +65,6 @@ class Payment(PaymentCommon): 'caption': 'dummy siret parameter', 'type': str, }, - { 'name': 'next_url', - 'caption': 'Return URL for the user', - 'type': str, - }, { 'name': 'consider_all_response_signed', 'caption': 'All response will be considered as signed ' '(to test payment locally for example, as you ' @@ -68,6 +72,16 @@ class Payment(PaymentCommon): 'type': bool, 'default': False, }, + { 'name': 'direct_notification_url', + 'caption': 'direct notification url (replaced by automatic_return_url)', + 'type': str, + 'deprecated': True, + }, + { 'name': 'next_url (replaced by normal_return_url)', + 'caption': 'Return URL for the user', + 'type': str, + 'deprecated': True, + }, ], } @@ -77,15 +91,23 @@ class Payment(PaymentCommon): ' next_url %s info1 %s info2 %s info3 %s kwargs: %s', __name__, amount, name, address, email, phone, info1, info2, info3, next_url, kwargs) transaction_id = self.transaction_id(30, ALPHANUM, 'dummy', self.siret) - if self.next_url: - next_url = self.next_url + normal_return_url = self.normal_return_url + if next_url and not normal_return_url: + warnings.warn("passing next_url to request() is deprecated, " + "set normal_return_url in options", DeprecationWarning) + normal_return_url = next_url + automatic_return_url = self.automatic_return_url + if self.direct_notification_url and not automatic_return_url: + warnings.warn("direct_notification_url option is deprecated, " + "use automatic_return_url", DeprecationWarning) + automatic_return_url = self.direct_notification_url query = { 'transaction_id': transaction_id, 'siret': self.siret, 'amount': amount, 'email': email, - 'return_url': next_url or '', - 'direct_notification_url': self.direct_notification_url, + 'return_url': normal_return_url or '', + 'direct_notification_url': automatic_return_url or '', 'origin': self.origin } query.update(dict(name=name, address=address, email=email, phone=phone, diff --git a/eopayment/ogone.py b/eopayment/ogone.py index 281b138..045c2af 100644 --- a/eopayment/ogone.py +++ b/eopayment/ogone.py @@ -407,6 +407,17 @@ class Payment(PaymentCommon): description = { 'caption': N_('Système de paiement Ogone / Ingenico Payment System e-Commerce'), 'parameters': [ + { + 'name': 'normal_return_url', + 'caption': _('Normal return URL'), + 'default': '', + 'required': True, + }, + { + 'name': 'automatic_return_url', + 'caption': _('Automatic return URL (ignored, must be set in Ogone backoffice)'), + 'required': False, + }, {'name': 'environment', 'default': ENVIRONMENT_TEST, 'caption': N_(u'Environnement'), @@ -480,6 +491,12 @@ class Payment(PaymentCommon): 'LANGUAGE': language, 'CURRENCY': self.currency, } + if self.normal_return_url: + params['ACCEPTURL'] = self.normal_return_url + params['BACKURL'] = self.normal_return_url + params['CANCELURL'] = self.normal_return_url + params['DECLINEURL'] = self.normal_return_url + params['EXCEPTIONURL'] = self.normal_return_url if name: params['CN'] = name if email: diff --git a/eopayment/paybox.py b/eopayment/paybox.py index 20e3b43..87aff37 100644 --- a/eopayment/paybox.py +++ b/eopayment/paybox.py @@ -14,6 +14,7 @@ import urllib import base64 from gettext import gettext as _ import string +import warnings from common import PaymentCommon, PaymentResponse, FORM, PAID, ERROR, Form @@ -126,8 +127,8 @@ class Payment(PaymentCommon): '''Paybox backend for eopayment. If you want to handle Instant Payment Notification, you must pass - a callback parameter to the request() method specifying the URL of - the callback endpoint. + provide a automatic_return_url option specifying the URL of the + callback endpoint. Email is mandatory to emit payment requests with paybox. @@ -143,6 +144,17 @@ class Payment(PaymentCommon): 'caption': _('Paybox'), 'parameters': [ { + 'name': 'normal_return_url', + 'caption': _('Normal return URL'), + 'default': '', + 'required': False, + }, + { + 'name': 'automatic_return_url', + 'caption': _('Automatic return URL'), + 'required': False, + }, + { 'name': 'platform', 'caption': _('Plateforme cible'), 'default': 'test', @@ -188,6 +200,7 @@ class Payment(PaymentCommon): { 'name': 'callback', 'caption': _('Callback URL'), + 'deprecated': True, }, ] } @@ -208,8 +221,18 @@ class Payment(PaymentCommon): d['PBX_HASH'] = 'SHA512' d['PBX_TIME'] = kwargs.get('time') or (unicode(datetime.datetime.utcnow().isoformat('T')).split('.')[0]+'+00:00') d['PBX_ARCHIVAGE'] = transaction_id - if self.callback: - d['PBX_REPONDRE_A'] = unicode(self.callback) + if self.normal_return_url: + d['PBX_EFFECTUE'] = self.normal_return_url + d['PBX_REFUSE'] = self.normal_return_url + d['PBX_ANNULE'] = self.normal_return_url + d['PBX_ATTENTE'] = self.normal_return_url + automatic_return_url = self.automatic_return_url + if not automatic_return_url and self.callback: + warnings.warn("callback option is deprecated, " + "use automatic_return_url", DeprecationWarning) + automatic_return_url = self.callback + if automatic_return_url: + d['PBX_REPONDRE_A'] = unicode(automatic_return_url) d = d.items() d = sign(d, self.shared_secret.decode('hex')) url = URLS[self.platform] diff --git a/eopayment/sips.py b/eopayment/sips.py index 028a8f6..b3b301f 100644 --- a/eopayment/sips.py +++ b/eopayment/sips.py @@ -142,8 +142,13 @@ class Payment(PaymentCommon): params['amount'] = str(int(Decimal(amount) * 100)) if email: params['customer_email'] = email - if next_url: - params['normal_return_url'] = next_url + normal_return_url = self.normal_return_url + if next_url and not normal_return_url: + warnings.warn("passing next_url to request() is deprecated, " + "set normal_return_url in options", DeprecationWarning) + normal_return_url = next_url + if normal_return_url: + params['normal_return_url'] = normal_return_url code, error, form = self.execute('request', params) if int(code) == 0: return params[ORDER_ID], HTML, form diff --git a/eopayment/sips2.py b/eopayment/sips2.py index 156b4d7..17f86c1 100644 --- a/eopayment/sips2.py +++ b/eopayment/sips2.py @@ -5,6 +5,7 @@ from decimal import Decimal import uuid import hashlib from gettext import gettext as _ +import warnings from common import PaymentCommon, FORM, Form, PaymentResponse, PAID, ERROR, CANCELED @@ -92,7 +93,7 @@ class Payment(PaymentCommon): { 'name': 'normal_return_url', 'caption': _('Normal return URL'), - 'default': 'http://www.example.com/', + 'default': '', 'required': True, }, { @@ -129,6 +130,8 @@ class Payment(PaymentCommon): data['merchantId'] = self.merchand_id data['keyVersion'] = self.key_version data['normalReturnUrl'] = self.normal_return_url + if self.automatic_return_url: + date['automaticReturnUrl'] = self.automatic_return_url data['currencyCode'] = self.currency_code return data @@ -144,7 +147,12 @@ class Payment(PaymentCommon): data['amount'] = unicode(int(Decimal(amount) * 100)) if email: data['billingContact.email'] = email - if next_url: + normal_return_url = self.normal_return_url + if next_url and not normal_return_url: + warnings.warn("passing next_url to request() is deprecated, " + "set normal_return_url in options", DeprecationWarning) + normal_return_url = next_url + if normal_return_url: data['normalReturnUrl'] = next_url form = Form( url=self.get_url(), diff --git a/eopayment/spplus.py b/eopayment/spplus.py index 57e1e5c..0fffe0e 100644 --- a/eopayment/spplus.py +++ b/eopayment/spplus.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from decimal import Decimal import binascii +from gettext import gettext as _ import hmac import hashlib import urlparse @@ -92,6 +93,17 @@ class Payment(PaymentCommon): description = { 'caption': "SPPlus payment service of French bank Caisse d'epargne", 'parameters': [ + { + 'name': 'normal_return_url', + 'caption': _('Normal return URL'), + 'default': '', + 'required': True, + }, + { + 'name': 'automatic_return_url', + 'caption': _('Automatic return URL'), + 'required': False, + }, { 'name': 'cle', 'caption': 'Secret key, a 40 digits hexadecimal number', 'regexp': re.compile('^ *((?:[a-fA-F0-9] *){40}) *$') @@ -124,8 +136,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, logger=LOGGER, **kwargs): - logger.debug('requesting spplus payment with montant %s email=%s and \ -next_url=%s' % (amount, email, next_url)) + logger.debug('requesting spplus payment with montant %s email=%s' % (amount, email)) reference = self.transaction_id(20, ALPHANUM, 'spplus', self.siret) validite = dt.date.today()+dt.timedelta(days=1) validite = validite.strftime('%d/%m/%Y') @@ -141,12 +152,17 @@ next_url=%s' % (amount, email, next_url)) 'moyen': self.moyen } if email: fields['email'] = email - if next_url: - if (not next_url.startswith('http://') \ - and not next_url.startswith('https://')) \ - or '?' in next_url: - raise ValueError('next_url must be an absolute URL without parameters') - fields['urlretour'] = next_url + normal_return_url = self.normal_return_url + if next_url and not normal_return_url: + warnings.warn("passing next_url to request() is deprecated, " + "set normal_return_url in options", DeprecationWarning) + normal_return_url = next_url + if normal_return_url: + if (not normal_return_url.startswith('http://') \ + and not normal_return_url.startswith('https://')) \ + or '?' in normal_return_url: + raise ValueError('normal_return_url must be an absolute URL without parameters') + fields['urlretour'] = normal_return_url logger.debug('sending fields %s' % fields) query = urllib.urlencode(fields) url = '%s?%s&hmac=%s' % (SERVICE_URL, query, sign_url_paiement(self.cle, diff --git a/eopayment/systempayv2.py b/eopayment/systempayv2.py index f975b16..221499a 100644 --- a/eopayment/systempayv2.py +++ b/eopayment/systempayv2.py @@ -5,6 +5,7 @@ import hashlib import logging import string import urlparse +import warnings from gettext import gettext as _ from common import PaymentCommon, PaymentResponse, PAID, ERROR, FORM, Form @@ -214,6 +215,17 @@ class Payment(PaymentCommon): description = { 'caption': 'SystemPay, système de paiment du groupe BPCE', 'parameters': [ + { + 'name': 'normal_return_url', + 'caption': _('Normal return URL'), + 'default': '', + 'required': True, + }, + { + 'name': 'automatic_return_url', + 'caption': _('Automatic return URL (ignored, must be set in Payzen/SystemPay backoffice)'), + 'required': False, + }, {'name': 'service_url', 'default': service_url, 'caption': _(u'URL du service de paiment'), @@ -265,8 +277,13 @@ class Payment(PaymentCommon): kwargs.update(add_vads({'amount': unicode(amount)})) if amount < 0: raise ValueError('amount must be an integer >= 0') + normal_return_url = self.normal_return_url if next_url: - kwargs[VADS_URL_RETURN] = unicode(next_url) + warnings.warn("passing next_url to request() is deprecated, " + "set normal_return_url in options", DeprecationWarning) + normal_return_url = next_url + if normal_return_url: + kwargs[VADS_URL_RETURN] = unicode(normal_return_url) if name is not None: kwargs['vads_cust_name'] = unicode(name) if address is not None: diff --git a/eopayment/tipi.py b/eopayment/tipi.py index 7bb5aaf..308b62d 100644 --- a/eopayment/tipi.py +++ b/eopayment/tipi.py @@ -7,6 +7,7 @@ from urllib import urlencode from urlparse import parse_qs from gettext import gettext as _ import logging +import warnings from systempayv2 import isonow @@ -39,7 +40,17 @@ class Payment(PaymentCommon): '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, + }, ], } @@ -61,9 +72,15 @@ class Payment(PaymentCommon): 'a decimal integer with less than 4 digits ' 'before and 2 digits after the decimal point ' ', here it is %s' % repr(amount)) - if next_url is not None: - if not isinstance(next_url, str) or \ - not next_url.startswith('http'): + + automatic_return_url = self.automatic_return_url + if next_url and not automatic_return_url: + warnings.warn("passing next_url to request() is deprecated, " + "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'): raise ValueError('URLCL invalid URL format') try: if exer is not None: @@ -116,8 +133,8 @@ class Payment(PaymentCommon): } if exer: params['exer'] = exer - if next_url: - params['urlcl'] = next_url + if automatic_return_url: + params['urlcl'] = automatic_return_url url = '%s?%s' % (self.service_url, urlencode(params)) return transaction_id, URL, url -- 2.7.0