0001-standardise-normal_return_url-and-automatic_return_u.patch
eopayment/__init__.py | ||
---|---|---|
45 | 45 |
'siret': '00000000000001-01', \ |
46 | 46 |
} |
47 | 47 |
>>> p = Payment(kind=SPPLUS, options=spplus_options) |
48 |
>>> transaction_id, kind, data = p.request('10.00', email='bob@example.com', \ |
|
49 |
next_url='https://my-site.com') |
|
48 |
>>> transaction_id, kind, data = p.request('10.00', email='bob@example.com') |
|
50 | 49 |
>>> print (transaction_id, kind, data) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE |
51 | 50 |
('...', 1, 'https://www.spplus.net/paiement/init.do?...') |
52 | 51 | |
... | ... | |
86 | 85 |
Arguments: |
87 | 86 |
amount -- the amount of money to ask |
88 | 87 |
email -- the email of the customer (optional) |
89 |
next_url -- the URL where the customer will be returned (optional), |
|
90 | 88 |
usually redundant with the hardwired settings in the bank |
91 | 89 |
configuration panel. At this url you must use the Payment.response |
92 | 90 |
method to analyze the bank returned values. |
eopayment/dummy.py | ||
---|---|---|
1 | 1 |
import urllib |
2 | 2 |
import string |
3 | 3 |
import logging |
4 |
import warnings |
|
4 | 5 | |
5 | 6 |
try: |
6 | 7 |
from cgi import parse_qs |
... | ... | |
27 | 28 |
You must pass the following keys inside the options dictionnary: |
28 | 29 |
- dummy_service_url, the URL of the dummy payment service, it defaults |
29 | 30 |
to the one operated by Entr'ouvert. |
30 |
- direct_notification_url: where to POST to notify the service of a
|
|
31 |
- automatic_return_url: where to POST to notify the service of a
|
|
31 | 32 |
payment |
32 | 33 |
- origin: a human string to display to the user about the origin of |
33 | 34 |
the request. |
34 | 35 |
- siret: an identifier for the eCommerce site, fake. |
35 |
- next_url: the return URL for the user (can be overriden on a per
|
|
36 |
request basis). |
|
36 |
- normal_return_url: the return URL for the user (can be overriden on a
|
|
37 |
per request basis).
|
|
37 | 38 |
''' |
38 | 39 |
description = { |
39 | 40 |
'caption': 'Dummy payment backend', |
40 | 41 |
'parameters': [ |
42 |
{ |
|
43 |
'name': 'normal_return_url', |
|
44 |
'caption': _('Normal return URL'), |
|
45 |
'default': '', |
|
46 |
'required': True, |
|
47 |
}, |
|
48 |
{ |
|
49 |
'name': 'automatic_return_url', |
|
50 |
'caption': _('Automatic return URL'), |
|
51 |
'required': False, |
|
52 |
}, |
|
41 | 53 |
{ 'name': 'dummy_service_url', |
42 | 54 |
'caption': 'URL of the dummy payment service', |
43 | 55 |
'default': SERVICE_URL, |
44 | 56 |
'type': str, |
45 | 57 |
}, |
46 |
{ 'name': 'direct_notification_url', |
|
47 |
'caption': 'direct notification url', |
|
48 |
'type': str, |
|
49 |
}, |
|
50 | 58 |
{ 'name': 'origin', |
51 | 59 |
'caption': 'name of the requesting service, ' |
52 | 60 |
'to present in the user interface', |
... | ... | |
57 | 65 |
'caption': 'dummy siret parameter', |
58 | 66 |
'type': str, |
59 | 67 |
}, |
60 |
{ 'name': 'next_url', |
|
61 |
'caption': 'Return URL for the user', |
|
62 |
'type': str, |
|
63 |
}, |
|
64 | 68 |
{ 'name': 'consider_all_response_signed', |
65 | 69 |
'caption': 'All response will be considered as signed ' |
66 | 70 |
'(to test payment locally for example, as you ' |
... | ... | |
68 | 72 |
'type': bool, |
69 | 73 |
'default': False, |
70 | 74 |
}, |
75 |
{ 'name': 'direct_notification_url', |
|
76 |
'caption': 'direct notification url (replaced by automatic_return_url)', |
|
77 |
'type': str, |
|
78 |
'deprecated': True, |
|
79 |
}, |
|
80 |
{ 'name': 'next_url (replaced by normal_return_url)', |
|
81 |
'caption': 'Return URL for the user', |
|
82 |
'type': str, |
|
83 |
'deprecated': True, |
|
84 |
}, |
|
71 | 85 |
], |
72 | 86 |
} |
73 | 87 | |
... | ... | |
77 | 91 |
' next_url %s info1 %s info2 %s info3 %s kwargs: %s', |
78 | 92 |
__name__, amount, name, address, email, phone, info1, info2, info3, next_url, kwargs) |
79 | 93 |
transaction_id = self.transaction_id(30, ALPHANUM, 'dummy', self.siret) |
80 |
if self.next_url: |
|
81 |
next_url = self.next_url |
|
94 |
normal_return_url = self.normal_return_url |
|
95 |
if next_url and not normal_return_url: |
|
96 |
warnings.warn("passing next_url to request() is deprecated, " |
|
97 |
"set normal_return_url in options", DeprecationWarning) |
|
98 |
normal_return_url = next_url |
|
99 |
automatic_return_url = self.automatic_return_url |
|
100 |
if self.direct_notification_url and not automatic_return_url: |
|
101 |
warnings.warn("direct_notification_url option is deprecated, " |
|
102 |
"use automatic_return_url", DeprecationWarning) |
|
103 |
automatic_return_url = self.direct_notification_url |
|
82 | 104 |
query = { |
83 | 105 |
'transaction_id': transaction_id, |
84 | 106 |
'siret': self.siret, |
85 | 107 |
'amount': amount, |
86 | 108 |
'email': email, |
87 |
'return_url': next_url or '',
|
|
88 |
'direct_notification_url': self.direct_notification_url,
|
|
109 |
'return_url': normal_return_url or '',
|
|
110 |
'direct_notification_url': automatic_return_url or '',
|
|
89 | 111 |
'origin': self.origin |
90 | 112 |
} |
91 | 113 |
query.update(dict(name=name, address=address, email=email, phone=phone, |
eopayment/ogone.py | ||
---|---|---|
407 | 407 |
description = { |
408 | 408 |
'caption': N_('Système de paiement Ogone / Ingenico Payment System e-Commerce'), |
409 | 409 |
'parameters': [ |
410 |
{ |
|
411 |
'name': 'normal_return_url', |
|
412 |
'caption': _('Normal return URL'), |
|
413 |
'default': '', |
|
414 |
'required': True, |
|
415 |
}, |
|
416 |
{ |
|
417 |
'name': 'automatic_return_url', |
|
418 |
'caption': _('Automatic return URL (ignored, must be set in Ogone backoffice)'), |
|
419 |
'required': False, |
|
420 |
}, |
|
410 | 421 |
{'name': 'environment', |
411 | 422 |
'default': ENVIRONMENT_TEST, |
412 | 423 |
'caption': N_(u'Environnement'), |
... | ... | |
487 | 498 |
'LANGUAGE': language, |
488 | 499 |
'CURRENCY': self.currency, |
489 | 500 |
} |
501 |
if self.normal_return_url: |
|
502 |
params['ACCEPTURL'] = self.normal_return_url |
|
503 |
params['BACKURL'] = self.normal_return_url |
|
504 |
params['CANCELURL'] = self.normal_return_url |
|
505 |
params['DECLINEURL'] = self.normal_return_url |
|
506 |
params['EXCEPTIONURL'] = self.normal_return_url |
|
490 | 507 |
if name: |
491 | 508 |
params['CN'] = name |
492 | 509 |
if email: |
eopayment/paybox.py | ||
---|---|---|
14 | 14 |
import base64 |
15 | 15 |
from gettext import gettext as _ |
16 | 16 |
import string |
17 |
import warnings |
|
17 | 18 | |
18 | 19 |
from common import (PaymentCommon, PaymentResponse, FORM, PAID, ERROR, Form, |
19 | 20 |
ORDERID_TRANSACTION_SEPARATOR) |
... | ... | |
127 | 128 |
'''Paybox backend for eopayment. |
128 | 129 | |
129 | 130 |
If you want to handle Instant Payment Notification, you must pass |
130 |
a callback parameter to the request() method specifying the URL of
|
|
131 |
the callback endpoint.
|
|
131 |
provide a automatic_return_url option specifying the URL of the
|
|
132 |
callback endpoint. |
|
132 | 133 | |
133 | 134 |
Email is mandatory to emit payment requests with paybox. |
134 | 135 | |
... | ... | |
144 | 145 |
'caption': _('Paybox'), |
145 | 146 |
'parameters': [ |
146 | 147 |
{ |
148 |
'name': 'normal_return_url', |
|
149 |
'caption': _('Normal return URL'), |
|
150 |
'default': '', |
|
151 |
'required': False, |
|
152 |
}, |
|
153 |
{ |
|
154 |
'name': 'automatic_return_url', |
|
155 |
'caption': _('Automatic return URL'), |
|
156 |
'required': False, |
|
157 |
}, |
|
158 |
{ |
|
147 | 159 |
'name': 'platform', |
148 | 160 |
'caption': _('Plateforme cible'), |
149 | 161 |
'default': 'test', |
... | ... | |
189 | 201 |
{ |
190 | 202 |
'name': 'callback', |
191 | 203 |
'caption': _('Callback URL'), |
204 |
'deprecated': True, |
|
192 | 205 |
}, |
193 | 206 |
] |
194 | 207 |
} |
... | ... | |
212 | 225 |
d['PBX_HASH'] = 'SHA512' |
213 | 226 |
d['PBX_TIME'] = kwargs.get('time') or (unicode(datetime.datetime.utcnow().isoformat('T')).split('.')[0]+'+00:00') |
214 | 227 |
d['PBX_ARCHIVAGE'] = transaction_id |
215 |
if self.callback: |
|
216 |
d['PBX_REPONDRE_A'] = unicode(self.callback) |
|
228 |
if self.normal_return_url: |
|
229 |
d['PBX_EFFECTUE'] = self.normal_return_url |
|
230 |
d['PBX_REFUSE'] = self.normal_return_url |
|
231 |
d['PBX_ANNULE'] = self.normal_return_url |
|
232 |
d['PBX_ATTENTE'] = self.normal_return_url |
|
233 |
automatic_return_url = self.automatic_return_url |
|
234 |
if not automatic_return_url and self.callback: |
|
235 |
warnings.warn("callback option is deprecated, " |
|
236 |
"use automatic_return_url", DeprecationWarning) |
|
237 |
automatic_return_url = self.callback |
|
238 |
if automatic_return_url: |
|
239 |
d['PBX_REPONDRE_A'] = unicode(automatic_return_url) |
|
217 | 240 |
d = d.items() |
218 | 241 |
d = sign(d, self.shared_secret.decode('hex')) |
219 | 242 |
url = URLS[self.platform] |
eopayment/sips.py | ||
---|---|---|
7 | 7 |
import os |
8 | 8 |
import os.path |
9 | 9 |
import uuid |
10 |
import warnings |
|
10 | 11 | |
11 | 12 |
from common import PaymentCommon, HTML, PaymentResponse |
12 | 13 |
from cb import CB_RESPONSE_CODES |
... | ... | |
143 | 144 |
params['amount'] = str(int(Decimal(amount) * 100)) |
144 | 145 |
if email: |
145 | 146 |
params['customer_email'] = email |
146 |
if next_url: |
|
147 |
params['normal_return_url'] = next_url |
|
147 |
normal_return_url = self.normal_return_url |
|
148 |
if next_url and not normal_return_url: |
|
149 |
warnings.warn("passing next_url to request() is deprecated, " |
|
150 |
"set normal_return_url in options", DeprecationWarning) |
|
151 |
normal_return_url = next_url |
|
152 |
if normal_return_url: |
|
153 |
params['normal_return_url'] = normal_return_url |
|
148 | 154 |
code, error, form = self.execute('request', params) |
149 | 155 |
if int(code) == 0: |
150 | 156 |
return params[ORDER_ID], HTML, form |
eopayment/sips2.py | ||
---|---|---|
5 | 5 |
import uuid |
6 | 6 |
import hashlib |
7 | 7 |
from gettext import gettext as _ |
8 |
import warnings |
|
8 | 9 | |
9 | 10 |
from common import PaymentCommon, FORM, Form, PaymentResponse, PAID, ERROR, CANCELED |
10 | 11 | |
... | ... | |
92 | 93 |
{ |
93 | 94 |
'name': 'normal_return_url', |
94 | 95 |
'caption': _('Normal return URL'), |
95 |
'default': 'http://www.example.com/',
|
|
96 |
'default': '', |
|
96 | 97 |
'required': True, |
97 | 98 |
}, |
98 | 99 |
{ |
... | ... | |
129 | 130 |
data['merchantId'] = self.merchand_id |
130 | 131 |
data['keyVersion'] = self.key_version |
131 | 132 |
data['normalReturnUrl'] = self.normal_return_url |
133 |
if self.automatic_return_url: |
|
134 |
date['automaticReturnUrl'] = self.automatic_return_url |
|
132 | 135 |
data['currencyCode'] = self.currency_code |
133 | 136 |
return data |
134 | 137 | |
... | ... | |
144 | 147 |
data['amount'] = unicode(int(Decimal(amount) * 100)) |
145 | 148 |
if email: |
146 | 149 |
data['billingContact.email'] = email |
147 |
if next_url: |
|
150 |
normal_return_url = self.normal_return_url |
|
151 |
if next_url and not normal_return_url: |
|
152 |
warnings.warn("passing next_url to request() is deprecated, " |
|
153 |
"set normal_return_url in options", DeprecationWarning) |
|
154 |
normal_return_url = next_url |
|
155 |
if normal_return_url: |
|
148 | 156 |
data['normalReturnUrl'] = next_url |
149 | 157 |
form = Form( |
150 | 158 |
url=self.get_url(), |
eopayment/spplus.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 | 2 |
from decimal import Decimal |
3 | 3 |
import binascii |
4 |
from gettext import gettext as _ |
|
4 | 5 |
import hmac |
5 | 6 |
import hashlib |
6 | 7 |
import urlparse |
... | ... | |
9 | 10 |
import datetime as dt |
10 | 11 |
import logging |
11 | 12 |
import re |
13 |
import warnings |
|
12 | 14 | |
13 | 15 |
import Crypto.Cipher.DES |
14 | 16 |
from common import (PaymentCommon, URL, PaymentResponse, RECEIVED, ACCEPTED, |
... | ... | |
92 | 94 |
description = { |
93 | 95 |
'caption': "SPPlus payment service of French bank Caisse d'epargne", |
94 | 96 |
'parameters': [ |
97 |
{ |
|
98 |
'name': 'normal_return_url', |
|
99 |
'caption': _('Normal return URL'), |
|
100 |
'default': '', |
|
101 |
'required': True, |
|
102 |
}, |
|
103 |
{ |
|
104 |
'name': 'automatic_return_url', |
|
105 |
'caption': _('Automatic return URL'), |
|
106 |
'required': False, |
|
107 |
}, |
|
95 | 108 |
{ 'name': 'cle', |
96 | 109 |
'caption': 'Secret key, a 40 digits hexadecimal number', |
97 | 110 |
'regexp': re.compile('^ *((?:[a-fA-F0-9] *){40}) *$') |
... | ... | |
123 | 136 |
devise = '978' |
124 | 137 | |
125 | 138 |
def request(self, amount, name=None, address=None, email=None, phone=None, |
126 |
orderid=None, info1=None, info2=None, info3=None, next_url=None,
|
|
139 |
orderid=None info1=None, info2=None, info3=None, next_url=None, |
|
127 | 140 |
logger=LOGGER, **kwargs): |
128 |
logger.debug('requesting spplus payment with montant %s email=%s and \ |
|
129 |
next_url=%s' % (amount, email, next_url)) |
|
141 |
logger.debug('requesting spplus payment with montant %s email=%s' % (amount, email)) |
|
130 | 142 |
reference = self.transaction_id(20, ALPHANUM, 'spplus', self.siret) |
131 | 143 |
validite = dt.date.today()+dt.timedelta(days=1) |
132 | 144 |
validite = validite.strftime('%d/%m/%Y') |
... | ... | |
142 | 154 |
'moyen': self.moyen } |
143 | 155 |
if email: |
144 | 156 |
fields['email'] = email |
145 |
if next_url: |
|
146 |
if (not next_url.startswith('http://') \ |
|
147 |
and not next_url.startswith('https://')) \ |
|
148 |
or '?' in next_url: |
|
149 |
raise ValueError('next_url must be an absolute URL without parameters') |
|
150 |
fields['urlretour'] = next_url |
|
157 |
normal_return_url = self.normal_return_url |
|
158 |
if next_url and not normal_return_url: |
|
159 |
warnings.warn("passing next_url to request() is deprecated, " |
|
160 |
"set normal_return_url in options", DeprecationWarning) |
|
161 |
normal_return_url = next_url |
|
162 |
if normal_return_url: |
|
163 |
if (not normal_return_url.startswith('http://') \ |
|
164 |
and not normal_return_url.startswith('https://')) \ |
|
165 |
or '?' in normal_return_url: |
|
166 |
raise ValueError('normal_return_url must be an absolute URL without parameters') |
|
167 |
fields['urlretour'] = normal_return_url |
|
151 | 168 |
logger.debug('sending fields %s' % fields) |
152 | 169 |
query = urllib.urlencode(fields) |
153 | 170 |
url = '%s?%s&hmac=%s' % (SERVICE_URL, query, sign_url_paiement(self.cle, |
eopayment/systempayv2.py | ||
---|---|---|
5 | 5 |
import logging |
6 | 6 |
import string |
7 | 7 |
import urlparse |
8 |
import warnings |
|
8 | 9 |
from gettext import gettext as _ |
9 | 10 | |
10 | 11 |
from common import PaymentCommon, PaymentResponse, PAID, ERROR, FORM, Form |
... | ... | |
214 | 215 |
description = { |
215 | 216 |
'caption': 'SystemPay, système de paiment du groupe BPCE', |
216 | 217 |
'parameters': [ |
218 |
{ |
|
219 |
'name': 'normal_return_url', |
|
220 |
'caption': _('Normal return URL'), |
|
221 |
'default': '', |
|
222 |
'required': True, |
|
223 |
}, |
|
224 |
{ |
|
225 |
'name': 'automatic_return_url', |
|
226 |
'caption': _('Automatic return URL (ignored, must be set in Payzen/SystemPay backoffice)'), |
|
227 |
'required': False, |
|
228 |
}, |
|
217 | 229 |
{'name': 'service_url', |
218 | 230 |
'default': service_url, |
219 | 231 |
'caption': _(u'URL du service de paiment'), |
... | ... | |
266 | 278 |
kwargs.update(add_vads({'amount': unicode(amount)})) |
267 | 279 |
if amount < 0: |
268 | 280 |
raise ValueError('amount must be an integer >= 0') |
281 |
normal_return_url = self.normal_return_url |
|
269 | 282 |
if next_url: |
270 |
kwargs[VADS_URL_RETURN] = unicode(next_url) |
|
283 |
warnings.warn("passing next_url to request() is deprecated, " |
|
284 |
"set normal_return_url in options", DeprecationWarning) |
|
285 |
normal_return_url = next_url |
|
286 |
if normal_return_url: |
|
287 |
kwargs[VADS_URL_RETURN] = unicode(normal_return_url) |
|
271 | 288 |
if name is not None: |
272 | 289 |
kwargs['vads_cust_name'] = unicode(name) |
273 | 290 |
if address is not None: |
eopayment/tipi.py | ||
---|---|---|
7 | 7 |
from urlparse import parse_qs |
8 | 8 |
from gettext import gettext as _ |
9 | 9 |
import logging |
10 |
import warnings |
|
10 | 11 | |
11 | 12 |
from systempayv2 import isonow |
12 | 13 | |
... | ... | |
39 | 40 |
'help_text': _(u'ne pas modifier si vous ne savez pas'), |
40 | 41 |
'validation': lambda x: x.startswith('http'), |
41 | 42 |
'required': True, |
42 |
} |
|
43 |
}, |
|
44 |
{ |
|
45 |
'name': 'normal_return_url', |
|
46 |
'caption': _('Normal return URL (unused by TIPI)'), |
|
47 |
'required': False, |
|
48 |
}, |
|
49 |
{ |
|
50 |
'name': 'automatic_return_url', |
|
51 |
'caption': _('Automatic return URL'), |
|
52 |
'required': True, |
|
53 |
}, |
|
43 | 54 |
], |
44 | 55 |
} |
45 | 56 | |
... | ... | |
61 | 72 |
'a decimal integer with less than 4 digits ' |
62 | 73 |
'before and 2 digits after the decimal point ' |
63 | 74 |
', here it is %s' % repr(amount)) |
64 |
if next_url is not None: |
|
65 |
if not isinstance(next_url, str) or \ |
|
66 |
not next_url.startswith('http'): |
|
75 | ||
76 |
automatic_return_url = self.automatic_return_url |
|
77 |
if next_url and not automatic_return_url: |
|
78 |
warnings.warn("passing next_url to request() is deprecated, " |
|
79 |
"set automatic_return_url in options", DeprecationWarning) |
|
80 |
automatic_return_url = next_url |
|
81 |
if automatic_return_url is not None: |
|
82 |
if not isinstance(automatic_return_url, str) or \ |
|
83 |
not automatic_return_url.startswith('http'): |
|
67 | 84 |
raise ValueError('URLCL invalid URL format') |
68 | 85 |
try: |
69 | 86 |
if exer is not None: |
... | ... | |
117 | 134 |
} |
118 | 135 |
if exer: |
119 | 136 |
params['exer'] = exer |
120 |
if next_url:
|
|
121 |
params['urlcl'] = next_url
|
|
137 |
if automatic_return_url:
|
|
138 |
params['urlcl'] = automatic_return_url
|
|
122 | 139 |
url = '%s?%s' % (self.service_url, urlencode(params)) |
123 | 140 |
return transaction_id, URL, url |
124 | 141 | |
125 |
- |