Projet

Général

Profil

0001-add-Saga-payment-method-46502.patch

Benjamin Dauvergne, 29 octobre 2020 23:40

Télécharger (24,7 ko)

Voir les différences:

Subject: [PATCH] add Saga payment method (#46502)

 eopayment/__init__.py                       |   5 +-
 eopayment/saga.py                           | 251 ++++++++++++++++++++
 tests/conftest.py                           | 112 +++++++++
 tests/data/saga-test_error_parametrage.json |   1 +
 tests/test_saga.py                          |  71 ++++++
 5 files changed, 438 insertions(+), 2 deletions(-)
 create mode 100644 eopayment/saga.py
 create mode 100644 tests/conftest.py
 create mode 100644 tests/data/saga-test_error_parametrage.json
 create mode 100644 tests/test_saga.py
eopayment/__init__.py
31 31
__all__ = ['Payment', 'URL', 'HTML', 'FORM', 'SIPS', 'SYSTEMPAY',
32 32
           'TIPI', 'DUMMY', 'get_backend', 'RECEIVED', 'ACCEPTED', 'PAID',
33 33
           'DENIED', 'CANCELED', 'CANCELLED', 'ERROR', 'WAITING',
34
           'get_backends', 'PAYFIP_WS']
34
           'get_backends', 'PAYFIP_WS', 'SAGA']
35 35

  
36 36
if six.PY3:
37 37
    __all__.extend(['KEYWARE', 'MOLLIE'])
......
47 47
PAYFIP_WS = 'payfip_ws'
48 48
KEYWARE = 'keyware'
49 49
MOLLIE = 'mollie'
50
SAGA = 'saga'
50 51

  
51 52
logger = logging.getLogger(__name__)
52 53

  
......
57 58
    return module.Payment
58 59

  
59 60
__BACKENDS = [DUMMY, SIPS, SIPS2, SYSTEMPAY, OGONE, PAYBOX, PAYZEN,
60
              TIPI, PAYFIP_WS, KEYWARE, MOLLIE]
61
              TIPI, PAYFIP_WS, KEYWARE, MOLLIE, SAGA]
61 62

  
62 63

  
63 64
def get_backends():
eopayment/saga.py
1
# -*- coding: utf-8 -*-
2
# eopayment - online payment library
3
# Copyright (C) 2011-2020 Entr'ouvert
4
#
5
# This program is free software: you can redistribute it and/or modify it
6
# under the terms of the GNU Affero General Public License as published
7
# by the Free Software Foundation, either version 3 of the License, or
8
# (at your option) any later version.
9
#
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
# GNU Affero General Public License for more details.
14
#
15
# You should have received a copy of the GNU Affero General Public License
16
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17

  
18
from __future__ import unicode_literals, print_function
19

  
20
import functools
21

  
22
from six.moves.urllib.parse import urljoin, parse_qs
23

  
24
import lxml.etree as ET
25
import zeep
26
import zeep.exceptions
27

  
28
from .common import (PaymentException, PaymentCommon, ResponseError, URL, PAID,
29
                     DENIED, CANCELLED, ERROR, PaymentResponse)
30

  
31
_zeep_transport = None
32

  
33

  
34
class SagaError(PaymentException):
35
    pass
36

  
37

  
38
class Saga(object):
39
    def __init__(self, wsdl_url, service_url=None, zeep_client_kwargs=None):
40
        self.wsdl_url = wsdl_url
41
        kwargs = (zeep_client_kwargs or {}).copy()
42
        if _zeep_transport and 'transport' not in kwargs:
43
            kwargs['transport'] = _zeep_transport
44
        self.client = zeep.Client(wsdl_url, **kwargs)
45
        # distribued WSDL is wrong :/
46
        if service_url:
47
            self.client.service._binding_options['address'] = service_url
48

  
49
    def soap_call(self, operation, content_tag, **kwargs):
50
        content = getattr(self.client.service, operation)(**kwargs)
51
        if 'ISO-8859-1' in content:
52
            encoded_content = content.encode('latin1')
53
        else:
54
            encoded_content = content.encode('utf-8')
55
        try:
56
            tree = ET.fromstring(encoded_content)
57
        except Exception:
58
            raise SagaError('Invalid SAGA response "%s"' % content[:1024])
59
        if tree.tag == 'erreur':
60
            raise SagaError(tree.text)
61
        if tree.tag != content_tag:
62
            raise SagaError('Invalid SAGA response "%s"' % content[:1024])
63
        return tree
64

  
65
    def transaction(self, num_service, id_tiers, compte, lib_ecriture, montant,
66
                    urlretour_asynchrone, email, urlretour_synchrone):
67
        tree = self.soap_call(
68
            'Transaction',
69
            'url',
70
            num_service=num_service,
71
            id_tiers=id_tiers,
72
            compte=compte,
73
            lib_ecriture=lib_ecriture,
74
            montant=montant,
75
            urlretour_asynchrone=urlretour_asynchrone,
76
            email=email,
77
            urlretour_synchrone=urlretour_synchrone)
78
        # tree == <url>...</url>
79
        return tree.text
80

  
81
    def page_retour(self, operation, idop):
82
        tree = self.soap_call(
83
            operation,
84
            'ok',
85
            idop=idop)
86
        # tree == <ok id_tiers="A1"
87
        # etat="paye" email="albert,dupond@monsite.com" num_service="222222"
88
        # montant="100.00" compte="708"
89
        # lib_ecriture="Paiement pour M. Albert Dupondréservationsejourxxxx" />
90
        return tree.attrib
91

  
92
    def page_retour_synchrone(self, idop):
93
        return self.page_retour('PageRetourSynchrone', idop)
94

  
95
    def page_retour_asynchrone(self, idop):
96
        return self.page_retour('PageRetourAsynchrone', idop)
97

  
98

  
99
class Payment(PaymentCommon):
100
    description = {
101
        'caption': 'Système de paiement Saga / SAGA',
102
        'parameters': [
103
            {
104
                'name': 'base_url',
105
                'caption': 'URL de base du WSDL',
106
                'help_text': 'Sans la partie /paiement_internet_ws_ministere?wsdl',
107
                'required': True,
108
            },
109
            {
110
                'name': 'num_service',
111
                'caption': 'Numéro du service',
112
                'required': True,
113
            },
114
            {
115
                'name': 'compte',
116
                'caption': 'Compte de recettes',
117
                'required': True,
118
            },
119
            {
120
                'name': 'normal_return_url',
121
                'caption': 'Normal return URL',
122
                'default': '',
123
                'required': True,
124
            },
125
            {
126
                'name': 'automatic_return_url',
127
                'caption': 'Automatic return URL (ignored, must be set in Ogone backoffice)',
128
                'required': False,
129
            },
130
        ]
131
    }
132

  
133
    @property
134
    def saga(self):
135
        return Saga(
136
            wsdl_url=urljoin(self.base_url, 'paiement_internet_ws_ministere?wsdl'))
137

  
138
    def request(self, amount, email, description, **kwargs):
139
        num_service = self.num_service
140
        id_tiers = '-1'
141
        compte = self.compte
142
        lib_ecriture = description
143
        montant = self.clean_amount(amount, max_amount=100000, cents=False)
144
        urlretour_synchrone = self.normal_return_url
145
        # email
146
        urlretour_asynchrone = self.automatic_return_url
147

  
148
        url = self.saga.transaction(
149
            num_service=num_service,
150
            id_tiers=id_tiers,
151
            compte=compte,
152
            lib_ecriture=lib_ecriture,
153
            montant=montant,
154
            urlretour_asynchrone=urlretour_asynchrone,
155
            email=email,
156
            urlretour_synchrone=urlretour_synchrone)
157

  
158
        try:
159
            idop = parse_qs(url.split('?', 1)[-1])['idop'][0]
160
        except Exception:
161
            raise SagaError('Invalid payment URL, no idop: %s' % url)
162

  
163
        return str(idop), URL, url
164

  
165
    def response(self, query_string, **kwargs):
166
        fields = parse_qs(query_string, True)
167
        idop = (fields.get('idop') or [None])[0]
168

  
169
        if not idop:
170
            raise ResponseError('missing idop parameter in query')
171

  
172
        redirect = kwargs.get('redirect', False)
173

  
174
        if redirect:
175
            response = self.saga.page_retour_synchrone(idop=idop)
176
        else:
177
            response = self.saga.page_retour_asynchrone(idop=idop)
178

  
179
        etat = response['etat']
180
        if etat == 'paye':
181
            result = PAID
182
            bank_status = 'paid'
183
        elif etat == 'refus':
184
            result = DENIED
185
            bank_status = 'refused'
186
        elif etat == 'abandon':
187
            result = CANCELLED
188
            bank_status = 'cancelled'
189
        else:
190
            result = ERROR
191
            bank_status = 'unknown result code: etat=%r' % etat
192

  
193
        return PaymentResponse(
194
            result=result,
195
            bank_status=bank_status,
196
            signed=True,
197
            bank_data=response,
198
            order_id=idop,
199
            transaction_id=idop,
200
            test=False)
201

  
202

  
203
if __name__ == '__main__':
204
    import click
205

  
206
    def show_payfip_error(func):
207
        @functools.wraps(func)
208
        def f(*args, **kwargs):
209
            try:
210
                return func(*args, **kwargs)
211
            except SagaError as e:
212
                click.echo(click.style('SAGA ERROR : %s' % e, fg='red'))
213
        return f
214

  
215
    @click.group()
216
    @click.option('--wsdl-url')
217
    @click.option('--service-url', default=None)
218
    @click.pass_context
219
    def main(ctx, wsdl_url, service_url):
220
        import logging
221
        logging.basicConfig(level=logging.INFO)
222
        # hide warning from zeep
223
        logging.getLogger('zeep.wsdl.bindings.soap').level = logging.ERROR
224

  
225
        ctx.obj = Saga(wsdl_url=wsdl_url, service_url=service_url)
226

  
227
    @main.command()
228
    @click.option('--num-service', type=str, required=True)
229
    @click.option('--id-tiers', type=str, required=True)
230
    @click.option('--compte', type=str, required=True)
231
    @click.option('--lib-ecriture', type=str, required=True)
232
    @click.option('--montant', type=str, required=True)
233
    @click.option('--urlretour-asynchrone', type=str, required=True)
234
    @click.option('--email', type=str, required=True)
235
    @click.option('--urlretour-synchrone', type=str, required=True)
236
    @click.pass_obj
237
    @show_payfip_error
238
    def transaction(saga, num_service, id_tiers, compte, lib_ecriture, montant,
239
                    urlretour_asynchrone, email, urlretour_synchrone):
240
        url = saga.transaction(
241
            num_service=num_service,
242
            id_tiers=id_tiers,
243
            compte=compte,
244
            lib_ecriture=lib_ecriture,
245
            montant=montant,
246
            urlretour_asynchrone=urlretour_asynchrone,
247
            email=email,
248
            urlretour_synchrone=urlretour_synchrone)
249
        print('url:', url)
250

  
251
    main()
tests/conftest.py
1
# eopayment - online payment library
2
# Copyright (C) 2011-2020 Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
import json
18

  
19
import pytest
20

  
21
import httmock
22
import lxml.etree as ET
23

  
24
from requests.adapters import HTTPAdapter
25
from requests import Session
26

  
27

  
28
def pytest_addoption(parser):
29
    parser.addoption("--save-http-session", action="store_true", help="save HTTP session")
30
    parser.addoption("--target-url", help="target URL")
31

  
32

  
33
class LoggingAdapter(HTTPAdapter):
34
    def __init__(self, *args, **kwargs):
35
        self.history = []
36
        super(LoggingAdapter, self).__init__(*args, **kwargs)
37

  
38
    def send(self, request, *args, **kwargs):
39
        response = super(LoggingAdapter, self).send(request, *args, **kwargs)
40
        self.history.append((request, response))
41
        return response
42

  
43

  
44
def xmlindent(content):
45
    if hasattr(content, 'encode') or hasattr(content, 'decode'):
46
        content = ET.fromstring(content)
47
    return ET.tostring(content, pretty_print=True).decode('utf-8', 'ignore')
48

  
49

  
50
@pytest.fixture
51
def record_http_session(request):
52
    module_name = request.module.__name__.split('test_', 1)[-1]
53
    function_name = request.function.__name__
54
    save = request.config.getoption('--save-http-session')
55
    filename = 'tests/data/%s-%s.json' % (module_name, function_name)
56

  
57
    def is_xml_content_type(r):
58
        headers = r.headers
59
        content_type = headers.get('content-type')
60
        return content_type and content_type.startswith(('text/xml', 'application/xml'))
61

  
62
    if save:
63
        session = Session()
64
        adapter = LoggingAdapter()
65
        session.mount('http://', adapter)
66
        session.mount('https://', adapter)
67
        try:
68
            yield session
69
        finally:
70
            with open(filename, 'w') as fd:
71
                history = []
72

  
73
                for request, response in adapter.history:
74
                    request_content = (request.body or b'')
75
                    response_content = (response.content or b'')
76

  
77
                    if is_xml_content_type(request):
78
                        request_content = xmlindent(request_content)
79
                    else:
80
                        request_content = request_content.decode('utf-8')
81
                    if is_xml_content_type(response):
82
                        response_content = xmlindent(response_content)
83
                    else:
84
                        response_content = response_content.decode('utf-8')
85
                    history.append((request_content, response_content))
86
                json.dump(history, fd)
87
    else:
88
        with open(filename) as fd:
89
            history = json.load(fd)
90

  
91
        class Mocker:
92
            counter = 0
93

  
94
            @httmock.urlmatch()
95
            def mock(self, url, request):
96
                expected_request_content, response_content = history[self.counter]
97
                self.counter += 1
98
                if expected_request_content:
99
                    request_content = request.body or b''
100
                    if is_xml_content_type(request):
101
                        request_content = xmlindent(request_content)
102
                    else:
103
                        request_content = request_content.decode('utf-8')
104
                    assert request_content == expected_request_content
105
                return response_content
106
        with httmock.HTTMock(Mocker().mock):
107
            yield None
108

  
109

  
110
@pytest.fixture
111
def target_url(request):
112
    return request.config.getoption('--target-url') or 'https://target.url/'
tests/data/saga-test_error_parametrage.json
1
[["", "<wsdl:definitions xmlns:apachesoap=\"http://xml.apache.org/xml-soap\" xmlns:impl=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\" xmlns:intf=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\" xmlns:wsdlsoap=\"http://schemas.xmlsoap.org/wsdl/soap/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\">\n<!--WSDL created by Apache Axis version: 1.4\nBuilt on Apr 22, 2006 (06:55:48 PDT)-->\n\n   <wsdl:message name=\"PageRetourAsynchroneRequest\">\n\n      <wsdl:part name=\"idop\" type=\"xsd:string\"/>\n\n   </wsdl:message>\n\n   <wsdl:message name=\"TransactionResponse\">\n\n      <wsdl:part name=\"TransactionReturn\" type=\"xsd:string\"/>\n\n   </wsdl:message>\n\n   <wsdl:message name=\"PageRetourAsynchroneResponse\">\n\n      <wsdl:part name=\"PageRetourAsynchroneReturn\" type=\"xsd:string\"/>\n\n   </wsdl:message>\n\n   <wsdl:message name=\"PageRetourSynchroneResponse\">\n\n      <wsdl:part name=\"PageRetourSynchroneReturn\" type=\"xsd:string\"/>\n\n   </wsdl:message>\n\n   <wsdl:message name=\"PageRetourSynchroneRequest\">\n\n      <wsdl:part name=\"idop\" type=\"xsd:string\"/>\n\n   </wsdl:message>\n\n   <wsdl:message name=\"TransactionRequest\">\n\n      <wsdl:part name=\"num_service\" type=\"xsd:string\"/>\n\n      <wsdl:part name=\"id_tiers\" type=\"xsd:string\"/>\n\n      <wsdl:part name=\"compte\" type=\"xsd:string\"/>\n\n      <wsdl:part name=\"lib_ecriture\" type=\"xsd:string\"/>\n\n      <wsdl:part name=\"montant\" type=\"xsd:string\"/>\n\n      <wsdl:part name=\"urlretour_asynchrone\" type=\"xsd:string\"/>\n\n      <wsdl:part name=\"email\" type=\"xsd:string\"/>\n\n      <wsdl:part name=\"urlretour_synchrone\" type=\"xsd:string\"/>\n\n   </wsdl:message>\n\n   <wsdl:portType name=\"PaiementLigneWebServiceWSMinistere\">\n\n      <wsdl:operation name=\"PageRetourAsynchrone\" parameterOrder=\"idop\">\n\n         <wsdl:input message=\"impl:PageRetourAsynchroneRequest\" name=\"PageRetourAsynchroneRequest\"/>\n\n         <wsdl:output message=\"impl:PageRetourAsynchroneResponse\" name=\"PageRetourAsynchroneResponse\"/>\n\n      </wsdl:operation>\n\n      <wsdl:operation name=\"PageRetourSynchrone\" parameterOrder=\"idop\">\n\n         <wsdl:input message=\"impl:PageRetourSynchroneRequest\" name=\"PageRetourSynchroneRequest\"/>\n\n         <wsdl:output message=\"impl:PageRetourSynchroneResponse\" name=\"PageRetourSynchroneResponse\"/>\n\n      </wsdl:operation>\n\n      <wsdl:operation name=\"Transaction\" parameterOrder=\"num_service id_tiers compte lib_ecriture montant urlretour_asynchrone email urlretour_synchrone\">\n\n         <wsdl:input message=\"impl:TransactionRequest\" name=\"TransactionRequest\"/>\n\n         <wsdl:output message=\"impl:TransactionResponse\" name=\"TransactionResponse\"/>\n\n      </wsdl:operation>\n\n   </wsdl:portType>\n\n   <wsdl:binding name=\"paiement_internet_ws_ministereSoapBinding\" type=\"impl:PaiementLigneWebServiceWSMinistere\">\n\n      <wsdlsoap:binding style=\"rpc\" transport=\"http://schemas.xmlsoap.org/soap/http\"/>\n\n      <wsdl:operation name=\"PageRetourAsynchrone\">\n\n         <wsdlsoap:operation soapAction=\"\"/>\n\n         <wsdl:input name=\"PageRetourAsynchroneRequest\">\n\n            <wsdlsoap:body encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" namespace=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\" use=\"encoded\"/>\n\n         </wsdl:input>\n\n         <wsdl:output name=\"PageRetourAsynchroneResponse\">\n\n            <wsdlsoap:body encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" namespace=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\" use=\"encoded\"/>\n\n         </wsdl:output>\n\n      </wsdl:operation>\n\n      <wsdl:operation name=\"PageRetourSynchrone\">\n\n         <wsdlsoap:operation soapAction=\"\"/>\n\n         <wsdl:input name=\"PageRetourSynchroneRequest\">\n\n            <wsdlsoap:body encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" namespace=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\" use=\"encoded\"/>\n\n         </wsdl:input>\n\n         <wsdl:output name=\"PageRetourSynchroneResponse\">\n\n            <wsdlsoap:body encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" namespace=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\" use=\"encoded\"/>\n\n         </wsdl:output>\n\n      </wsdl:operation>\n\n      <wsdl:operation name=\"Transaction\">\n\n         <wsdlsoap:operation soapAction=\"\"/>\n\n         <wsdl:input name=\"TransactionRequest\">\n\n            <wsdlsoap:body encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" namespace=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\" use=\"encoded\"/>\n\n         </wsdl:input>\n\n         <wsdl:output name=\"TransactionResponse\">\n\n            <wsdlsoap:body encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" namespace=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\" use=\"encoded\"/>\n\n         </wsdl:output>\n\n      </wsdl:operation>\n\n   </wsdl:binding>\n\n   <wsdl:service name=\"PaiementLigneWebServiceWSMinistereService\">\n\n      <wsdl:port binding=\"impl:paiement_internet_ws_ministereSoapBinding\" name=\"paiement_internet_ws_ministere\">\n\n         <wsdlsoap:address location=\"https://passerelle-moncompte.cutm-ea-dev-publik.nfrance.com/pfs/sagaweb/paiement_internet_ws_ministere\"/>\n\n      </wsdl:port>\n\n   </wsdl:service>\n\n</wsdl:definitions>\n"], ["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n  <soap-env:Body>\n    <ns0:Transaction xmlns:ns0=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\">\n      <num_service>1</num_service>\n      <id_tiers>-1</id_tiers>\n      <compte>1</compte>\n      <lib_ecriture>R&#233;servation concert XYZ num&#233;ro 1234</lib_ecriture>\n      <montant>10.00</montant>\n      <urlretour_asynchrone>https://automatic.notif.url/automatic/</urlretour_asynchrone>\n      <email>john.doe@example.com</email>\n      <urlretour_synchrone>https://normal.notif.url/normal/</urlretour_synchrone>\n    </ns0:Transaction>\n  </soap-env:Body>\n</soap-env:Envelope>\n", "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n  <soapenv:Body>\n    <ns1:TransactionResponse xmlns:ns1=\"http://web_service.saga.futursystem.com/namespace/paiement_internet_ws_ministere\" soapenv:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n      <TransactionReturn xsi:type=\"xsd:string\">&lt;?xml version=\"1.0\" encoding=\"ISO-8859-1\"?&gt;&lt;erreur&gt;M&#233;thode Transaction_WS_Ministere - Impossible de d&#233;terminer le param&#233;trage de la solution du paiement en ligne de r&#233;gie correspondante.&lt;/erreur&gt;</TransactionReturn>\n    </ns1:TransactionResponse>\n  </soapenv:Body>\n</soapenv:Envelope>\n"]]
tests/test_saga.py
1
# coding: utf-8
2
#
3
# eopayment - online payment library
4
# Copyright (C) 2011-2020 Entr'ouvert
5
#
6
# This program is free software: you can redistribute it and/or modify it
7
# under the terms of the GNU Affero General Public License as published
8
# by the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU Affero General Public License for more details.
15
#
16
# You should have received a copy of the GNU Affero General Public License
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18

  
19
from __future__ import print_function, unicode_literals
20

  
21
import pytest
22

  
23
import zeep.transports
24

  
25
import eopayment
26

  
27

  
28
@pytest.fixture
29
def saga(record_http_session):
30
    if record_http_session:
31
        from eopayment import saga
32

  
33
        saga._zeep_transport = zeep.transports.Transport(session=record_http_session)
34
        try:
35
            yield None
36
        finally:
37
            saga._zeep_transport = None
38
    else:
39
        yield
40

  
41

  
42
@pytest.fixture
43
def backend_factory(saga, target_url):
44
    def factory(**kwargs):
45
        return eopayment.Payment('saga', dict({
46
            'base_url': target_url,
47
            'num_service': '868',
48
            'compte': '70688',
49
            'automatic_return_url': 'https://automatic.notif.url/automatic/',
50
            'normal_return_url': 'https://normal.notif.url/normal/',
51
        }, **kwargs))
52
    return factory
53

  
54

  
55
def test_error_parametrage(backend_factory):
56
    payment = backend_factory(num_service='1', compte='1')
57
    with pytest.raises(eopayment.PaymentException, match='Impossible de déterminer le paramétrage'):
58
        transaction_id, kind, url = payment.request(
59
            amount='10.00',
60
            email='john.doe@example.com',
61
            description='Réservation concert XYZ numéro 1234')
62

  
63

  
64
def test_request(backend_factory):
65
    transaction_id, kind, url = backend_factory().request(
66
        amount='10.00',
67
        email='john.doe@example.com',
68
        description='Réservation concert XYZ numéro 1234')
69
    assert transaction_id == '347b2060-1a37-11eb-af92-0213ad91a103'
70
    assert kind == eopayment.URL
71
    assert url == 'https://www.tipi.budget.gouv.fr/tpa/paiementws.web?idop=347b2060-1a37-11eb-af92-0213ad91a103'
0
-