standardise normal_return_url and automatic_return_url options (#9998)

This commit is contained in:
Frédéric Péters 2016-02-16 10:51:41 +01:00 committed by Benjamin Dauvergne
parent 8cd625e465
commit b69cefbfa8
9 changed files with 166 additions and 41 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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': N_('Normal return URL'),
'default': '',
'required': True,
},
{
'name': 'automatic_return_url',
'caption': N_('Automatic return URL (ignored, must be set in Ogone backoffice)'),
'required': False,
},
{'name': 'environment',
'default': ENVIRONMENT_TEST,
'caption': N_(u'Environnement'),
@ -487,6 +498,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:

View File

@ -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,
ORDERID_TRANSACTION_SEPARATOR)
@ -127,8 +128,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):
description = {
'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'),
@ -189,6 +201,7 @@ class Payment(PaymentCommon):
{
'name': 'callback',
'caption': _('Callback URL'),
'deprecated': True,
},
]
}
@ -212,8 +225,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]

View File

@ -7,6 +7,7 @@ import logging
import os
import os.path
import uuid
import warnings
from common import PaymentCommon, HTML, PaymentResponse
from cb import CB_RESPONSE_CODES
@ -143,8 +144,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

View File

@ -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(),

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from decimal import Decimal
import binascii
from gettext import gettext as _
import hmac
import hashlib
import urlparse
@ -9,6 +10,7 @@ import string
import datetime as dt
import logging
import re
import warnings
import Crypto.Cipher.DES
from common import (PaymentCommon, URL, PaymentResponse, RECEIVED, ACCEPTED,
@ -92,6 +94,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}) *$')
@ -125,8 +138,7 @@ class Payment(PaymentCommon):
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))
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')
@ -142,12 +154,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,

View File

@ -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'),
@ -266,8 +278,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:

View File

@ -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:
@ -117,8 +134,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