start support for PayFiP Regie web-service (#38405)
This commit is contained in:
parent
8ae9b712c4
commit
edb97113d5
|
@ -5,3 +5,7 @@ include VERSION
|
|||
include README.txt
|
||||
include eopayment/request
|
||||
include eopayment/response
|
||||
include eopayment/resource/PaiementSecuriseService.wsdl
|
||||
include eopayment/resource/PaiementSecuriseService1.xsd
|
||||
include eopayment/resource/PaiementSecuriseService2.xsd
|
||||
include eopayment/resource/PaiementSecuriseService3.xsd
|
||||
|
|
31
README.txt
31
README.txt
|
@ -37,3 +37,34 @@ fields, in order to allow to match them in payment system backoffice. They are:
|
|||
|
||||
For other backends, the order and transaction ids, separated by '!' are sent in
|
||||
order id field, so they can be matched in backoffice.
|
||||
|
||||
PayFiP
|
||||
======
|
||||
|
||||
You can test your PayFiP regie web-service connection with an integrated CLI utility:
|
||||
|
||||
$ python3 -m eopayment.payfip_ws info-client --help
|
||||
Usage: payfip_ws.py info-client [OPTIONS] NUMCLI
|
||||
|
||||
Options:
|
||||
--help Show this message and exit.
|
||||
|
||||
$ python3 -m eopayment.payfip_ws get-idop --help
|
||||
Usage: payfip_ws.py get-idop [OPTIONS] NUMCLI
|
||||
|
||||
Options:
|
||||
--saisie [T|X|W] [required]
|
||||
--exer TEXT [required]
|
||||
--montant INTEGER [required]
|
||||
--refdet TEXT [required]
|
||||
--mel TEXT [required]
|
||||
--url-notification TEXT [required]
|
||||
--url-redirect TEXT [required]
|
||||
--objet TEXT
|
||||
--help Show this message and exit.
|
||||
|
||||
$ python3 -m eopayment.payfip_ws info-paiement --help
|
||||
Usage: payfip_ws.py info-paiement [OPTIONS] IDOP
|
||||
|
||||
Options:
|
||||
--help Show this message and exit.
|
||||
|
|
|
@ -0,0 +1,346 @@
|
|||
# eopayment - online payment library
|
||||
# Copyright (C) 2011-2019 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import copy
|
||||
import datetime
|
||||
from decimal import Decimal, ROUND_DOWN
|
||||
import functools
|
||||
import os
|
||||
import random
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from gettext import gettext as _
|
||||
|
||||
import six
|
||||
from six.moves.urllib.parse import parse_qs
|
||||
|
||||
import zeep
|
||||
import zeep.exceptions
|
||||
|
||||
from .systempayv2 import isonow
|
||||
from .common import (PaymentCommon, PaymentResponse, URL, PAID, DENIED,
|
||||
CANCELLED, ERROR, ResponseError, PaymentException)
|
||||
|
||||
WSDL_URL = 'https://www.tipi.budget.gouv.fr/tpa/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService?wsdl' # noqa: E501
|
||||
|
||||
SERVICE_URL = 'https://www.tipi.budget.gouv.fr/tpa/services/securite' # noqa: E501
|
||||
|
||||
PAYMENT_URL = 'https://www.tipi.budget.gouv.fr/tpa/paiementws.web?idop=%s'
|
||||
|
||||
|
||||
def clear_namespace(element):
|
||||
def helper(element):
|
||||
if element.tag.startswith('{'):
|
||||
element.tag = element.tag[element.tag.index('}') + 1:]
|
||||
for subelement in element:
|
||||
helper(subelement)
|
||||
|
||||
element = copy.deepcopy(element)
|
||||
helper(element)
|
||||
return element
|
||||
|
||||
|
||||
class PayFiPError(PaymentException):
|
||||
def __init__(self, code, message, origin=None):
|
||||
self.code = code
|
||||
self.message = message
|
||||
self.origin = origin
|
||||
args = [code, message]
|
||||
if origin:
|
||||
args.append(origin)
|
||||
super(PayFiPError, self).__init__(*args)
|
||||
|
||||
|
||||
class PayFiP(object):
|
||||
'''Encapsulate SOAP web-services of PayFiP'''
|
||||
|
||||
def __init__(self, wsdl_url=None, service_url=None, zeep_client_kwargs=None):
|
||||
self.client = zeep.Client(wsdl_url or WSDL_URL, **(zeep_client_kwargs or {}))
|
||||
# distribued WSDL is wrong :/
|
||||
self.client.service._binding_options['address'] = service_url or SERVICE_URL
|
||||
|
||||
def fault_to_exception(self, fault):
|
||||
if fault.message != 'fr.gouv.finances.cp.tpa.webservice.exceptions.FonctionnelleErreur' or fault.detail is None:
|
||||
return
|
||||
detail = clear_namespace(fault.detail)
|
||||
code = detail.find('FonctionnelleErreur/code')
|
||||
if code is None or not code.text:
|
||||
return PayFiPError('inconnu', ET.tostring(detail))
|
||||
descriptif = detail.find('FonctionnelleErreur/descriptif')
|
||||
libelle = detail.find('FonctionnelleErreur/libelle')
|
||||
return PayFiPError(
|
||||
code=code.text,
|
||||
message=(descriptif is not None and descriptif.text)
|
||||
or (libelle is not None and libelle.text)
|
||||
or '')
|
||||
|
||||
def _perform(self, request_qname, operation, **kwargs):
|
||||
RequestType = self.client.get_type(request_qname) # noqa: E501
|
||||
try:
|
||||
return getattr(self.client.service, operation)(RequestType(**kwargs))
|
||||
except zeep.exceptions.Fault as fault:
|
||||
raise self.fault_to_exception(fault) or PayFiPError('unknown', fault.message, fault)
|
||||
except zeep.exceptions.Error as zeep_error:
|
||||
raise PayFiPError('erreur-soap', str(zeep_error), zeep_error)
|
||||
|
||||
def get_info_client(self, numcli):
|
||||
return self._perform(
|
||||
'{http://securite.service.tpa.cp.finances.gouv.fr/reponse}RecupererDetailClientRequest',
|
||||
'recupererDetailClient',
|
||||
numCli=numcli)
|
||||
|
||||
def get_idop(self, numcli, saisie, exer, refdet, montant, mel, url_notification, url_redirect, objet=None):
|
||||
return self._perform(
|
||||
'{http://securite.service.tpa.cp.finances.gouv.fr/requete}CreerPaiementSecuriseRequest',
|
||||
'creerPaiementSecurise',
|
||||
numcli=numcli,
|
||||
saisie=saisie,
|
||||
exer=exer,
|
||||
montant=montant,
|
||||
refdet=refdet,
|
||||
mel=mel,
|
||||
urlnotif=url_notification,
|
||||
urlredirect=url_redirect,
|
||||
objet=objet)
|
||||
|
||||
def get_info_paiement(self, idop):
|
||||
return self._perform(
|
||||
'{http://securite.service.tpa.cp.finances.gouv.fr/reponse}RecupererDetailPaiementSecuriseRequest',
|
||||
'recupererDetailPaiementSecurise',
|
||||
idOp=idop)
|
||||
|
||||
|
||||
class Payment(PaymentCommon):
|
||||
'''Produce requests for and verify response from the TIPI online payment
|
||||
processor from the French Finance Ministry.
|
||||
|
||||
'''
|
||||
|
||||
description = {
|
||||
'caption': 'TIPI, Titres Payables par Internet',
|
||||
'parameters': [
|
||||
{
|
||||
'name': 'numcli',
|
||||
'caption': _(u'Client number'),
|
||||
'help_text': _(u'6 digits number provided by DGFIP'),
|
||||
'validation': lambda s: str.isdigit(s) and len(s) == 6,
|
||||
'required': True,
|
||||
},
|
||||
{
|
||||
'name': 'service_url',
|
||||
'default': SERVICE_URL,
|
||||
'caption': _(u'PayFIP WS service URL'),
|
||||
'help_text': _(u'do not modify if you do not know'),
|
||||
'validation': lambda x: x.startswith('http'),
|
||||
},
|
||||
{
|
||||
'name': 'wsdl_url',
|
||||
'default': WSDL_URL,
|
||||
'caption': _(u'PayFIP WS WSDL URL'),
|
||||
'help_text': _(u'do not modify if you do not know'),
|
||||
'validation': lambda x: x.startswith('http'),
|
||||
},
|
||||
{
|
||||
'name': 'saisie',
|
||||
'caption': _('Payment type'),
|
||||
'default': 'T',
|
||||
'choices': [
|
||||
('T', _('test')),
|
||||
('X', _('activation')),
|
||||
('W', _('production')),
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'normal_return_url',
|
||||
'caption': _('User return URL'),
|
||||
'required': True,
|
||||
},
|
||||
{
|
||||
'name': 'automatic_return_url',
|
||||
'caption': _('Asynchronous return URL'),
|
||||
'required': True,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Payment, self).__init__(*args, **kwargs)
|
||||
wsdl_url = self.wsdl_url
|
||||
# use cached WSDL
|
||||
if wsdl_url == WSDL_URL:
|
||||
base_path = os.path.join(os.path.dirname(__file__), 'resource', 'PaiementSecuriseService.wsdl')
|
||||
wsdl_url = 'file://%s' % base_path
|
||||
self.payfip = PayFiP(wsdl_url=wsdl_url, service_url=self.service_url)
|
||||
|
||||
def _generate_refdet(self):
|
||||
return '%s%010d' % (isonow(), random.randint(1, 1000000000))
|
||||
|
||||
def request(self, amount, email, **kwargs):
|
||||
try:
|
||||
montant = Decimal(amount)
|
||||
# MONTANT must be sent as centimes
|
||||
montant = montant * Decimal('100')
|
||||
montant = montant.to_integral_value(ROUND_DOWN)
|
||||
if not (Decimal('0') < montant <= Decimal('10000000')):
|
||||
raise ValueError('MONTANT > 100000 euros or < 0')
|
||||
montant = str(montant)
|
||||
except ValueError:
|
||||
raise ValueError(
|
||||
'MONTANT invalid format, must be '
|
||||
'a decimal integer with less than 4 digits '
|
||||
'before and 2 digits after the decimal point '
|
||||
', here it is %s' % repr(amount))
|
||||
|
||||
numcli = self.numcli
|
||||
urlnotif = self.automatic_return_url
|
||||
urlredirect = self.normal_return_url
|
||||
exer = str(datetime.date.today().year)
|
||||
refdet = kwargs.get('refdet', self._generate_refdet())
|
||||
mel = email
|
||||
if hasattr(mel, 'decode'):
|
||||
mel = email.decode('ascii')
|
||||
|
||||
try:
|
||||
if '@' not in mel:
|
||||
raise ValueError('no @ in MEL')
|
||||
if not (6 <= len(mel) <= 80):
|
||||
raise ValueError('len(MEL) is invalid, must be between 6 and 80')
|
||||
except Exception as e:
|
||||
raise ValueError('MEL is not a valid email, %r' % mel, e)
|
||||
|
||||
# check saisie
|
||||
saisie = self.saisie
|
||||
if saisie not in ('T', 'X', 'W'):
|
||||
raise ValueError('SAISIE invalid format, %r, must be M, T, X or A' % saisie)
|
||||
|
||||
idop = self.payfip.get_idop(numcli=numcli, saisie=saisie, exer=exer,
|
||||
refdet=refdet, montant=montant, mel=mel,
|
||||
url_notification=urlnotif,
|
||||
url_redirect=urlredirect)
|
||||
|
||||
return str(idop), URL, PAYMENT_URL % idop
|
||||
|
||||
def response(self, query_string, **kwargs):
|
||||
fields = parse_qs(query_string, True)
|
||||
idop = (fields.get('idop') or [None])[0]
|
||||
|
||||
if not idop:
|
||||
raise ResponseError('missing idop parameter in query string')
|
||||
|
||||
try:
|
||||
response = self.payfip.get_info_paiement(idop)
|
||||
except PayFiPError as e:
|
||||
raise ResponseError('invalid return from payfip', e)
|
||||
|
||||
if response.resultrans == 'P':
|
||||
result = PAID
|
||||
bank_status = ''
|
||||
elif response.resultrans == 'R':
|
||||
result = DENIED
|
||||
bank_status = 'refused'
|
||||
elif response.resultrans == 'A':
|
||||
result = CANCELLED
|
||||
bank_status = 'cancelled'
|
||||
else:
|
||||
result = ERROR
|
||||
bank_status = 'unknown result code: %r' % response.resultrans
|
||||
|
||||
transaction_id = response.refdet
|
||||
transaction_id += ' ' + idop
|
||||
if response.numauto:
|
||||
transaction_id += ' ' + response.numauto
|
||||
|
||||
return PaymentResponse(
|
||||
result=result,
|
||||
bank_status=bank_status,
|
||||
signed=True,
|
||||
bank_data={k: response[k] for k in response},
|
||||
order_id=idop,
|
||||
transaction_id=transaction_id,
|
||||
test=response.saisie == 'T')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import click
|
||||
|
||||
def show_payfip_error(func):
|
||||
@functools.wraps(func)
|
||||
def f(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except PayFiPError as e:
|
||||
click.echo(click.style('PayFiP ERROR : %s "%s"' % (e.code, e.message), fg='red'))
|
||||
return f
|
||||
|
||||
@click.group()
|
||||
@click.option('--wsdl-url', default=None)
|
||||
@click.option('--service-url', default=None)
|
||||
@click.pass_context
|
||||
def main(ctx, wsdl_url, service_url):
|
||||
import logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
# hide warning from zeep
|
||||
logging.getLogger('zeep.wsdl.bindings.soap').level = logging.ERROR
|
||||
|
||||
ctx.obj = PayFiP(wsdl_url=wsdl_url, service_url=service_url)
|
||||
|
||||
def numcli(ctx, param, value):
|
||||
if not isinstance(value, six.string_types) or len(value) != 6 or not value.isdigit():
|
||||
raise click.BadParameter('numcli must a 6 digits number')
|
||||
return value
|
||||
|
||||
@main.command()
|
||||
@click.argument('numcli', callback=numcli, type=str)
|
||||
@click.pass_obj
|
||||
@show_payfip_error
|
||||
def info_client(payfip, numcli):
|
||||
response = payfip.get_info_client(numcli)
|
||||
for key in response:
|
||||
print('%15s:' % key, response[key])
|
||||
|
||||
@main.command()
|
||||
@click.argument('numcli', callback=numcli, type=str)
|
||||
@click.option('--saisie', type=click.Choice(['T', 'X', 'W']), required=True)
|
||||
@click.option('--exer', type=str, required=True)
|
||||
@click.option('--montant', type=int, required=True)
|
||||
@click.option('--refdet', type=str, required=True)
|
||||
@click.option('--mel', type=str, required=True)
|
||||
@click.option('--url-notification', type=str, required=True)
|
||||
@click.option('--url-redirect', type=str, required=True)
|
||||
@click.option('--objet', default=None, type=str)
|
||||
@click.pass_obj
|
||||
@show_payfip_error
|
||||
def get_idop(payfip, numcli, saisie, exer, montant, refdet, mel, objet, url_notification, url_redirect):
|
||||
idop = payfip.get_idop(numcli=numcli, saisie=saisie, exer=exer,
|
||||
montant=montant, refdet=refdet, mel=mel,
|
||||
objet=objet, url_notification=url_notification,
|
||||
url_redirect=url_redirect)
|
||||
print('idOp:', idop)
|
||||
print(PAYMENT_URL % idop)
|
||||
|
||||
@main.command()
|
||||
@click.argument('idop', type=str)
|
||||
@click.pass_obj
|
||||
@show_payfip_error
|
||||
def info_paiement(payfip, idop):
|
||||
print(payfip.get_info_paiement(idop))
|
||||
|
||||
main()
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.8 svn-revision#13980. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.7-b01-. --><definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" targetNamespace="http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService" name="PaiementSecuriseService">
|
||||
<types>
|
||||
<xsd:schema>
|
||||
<xsd:import namespace="http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService" schemaLocation="PaiementSecuriseService1.xsd"/>
|
||||
</xsd:schema>
|
||||
<xsd:schema>
|
||||
<xsd:import namespace="http://securite.service.tpa.cp.finances.gouv.fr/requete" schemaLocation="PaiementSecuriseService2.xsd"/>
|
||||
</xsd:schema>
|
||||
<xsd:schema>
|
||||
<xsd:import namespace="http://securite.service.tpa.cp.finances.gouv.fr/reponse" schemaLocation="PaiementSecuriseService3.xsd"/>
|
||||
</xsd:schema>
|
||||
</types>
|
||||
<message name="creerPaiementSecurise">
|
||||
<part name="parameters" element="tns:creerPaiementSecurise"/>
|
||||
</message>
|
||||
<message name="creerPaiementSecuriseResponse">
|
||||
<part name="parameters" element="tns:creerPaiementSecuriseResponse"/>
|
||||
</message>
|
||||
<message name="FonctionnelleErreur">
|
||||
<part name="fault" element="tns:FonctionnelleErreur"/>
|
||||
</message>
|
||||
<message name="TechDysfonctionnementErreur">
|
||||
<part name="fault" element="tns:TechDysfonctionnementErreur"/>
|
||||
</message>
|
||||
<message name="TechIndisponibiliteErreur">
|
||||
<part name="fault" element="tns:TechIndisponibiliteErreur"/>
|
||||
</message>
|
||||
<message name="TechProtocolaireErreur">
|
||||
<part name="fault" element="tns:TechProtocolaireErreur"/>
|
||||
</message>
|
||||
<message name="recupererDetailClient">
|
||||
<part name="parameters" element="tns:recupererDetailClient"/>
|
||||
</message>
|
||||
<message name="recupererDetailClientResponse">
|
||||
<part name="parameters" element="tns:recupererDetailClientResponse"/>
|
||||
</message>
|
||||
<message name="recupererDetailPaiementSecurise">
|
||||
<part name="parameters" element="tns:recupererDetailPaiementSecurise"/>
|
||||
</message>
|
||||
<message name="recupererDetailPaiementSecuriseResponse">
|
||||
<part name="parameters" element="tns:recupererDetailPaiementSecuriseResponse"/>
|
||||
</message>
|
||||
<portType name="PaiementSecuriseService">
|
||||
<operation name="creerPaiementSecurise">
|
||||
<input message="tns:creerPaiementSecurise"/>
|
||||
<output message="tns:creerPaiementSecuriseResponse"/>
|
||||
<fault message="tns:FonctionnelleErreur" name="FonctionnelleErreur"/>
|
||||
<fault message="tns:TechDysfonctionnementErreur" name="TechDysfonctionnementErreur"/>
|
||||
<fault message="tns:TechIndisponibiliteErreur" name="TechIndisponibiliteErreur"/>
|
||||
<fault message="tns:TechProtocolaireErreur" name="TechProtocolaireErreur"/>
|
||||
</operation>
|
||||
<operation name="recupererDetailClient">
|
||||
<input message="tns:recupererDetailClient"/>
|
||||
<output message="tns:recupererDetailClientResponse"/>
|
||||
<fault message="tns:FonctionnelleErreur" name="FonctionnelleErreur"/>
|
||||
<fault message="tns:TechDysfonctionnementErreur" name="TechDysfonctionnementErreur"/>
|
||||
<fault message="tns:TechIndisponibiliteErreur" name="TechIndisponibiliteErreur"/>
|
||||
<fault message="tns:TechProtocolaireErreur" name="TechProtocolaireErreur"/>
|
||||
</operation>
|
||||
<operation name="recupererDetailPaiementSecurise">
|
||||
<input message="tns:recupererDetailPaiementSecurise"/>
|
||||
<output message="tns:recupererDetailPaiementSecuriseResponse"/>
|
||||
<fault message="tns:FonctionnelleErreur" name="FonctionnelleErreur"/>
|
||||
<fault message="tns:TechDysfonctionnementErreur" name="TechDysfonctionnementErreur"/>
|
||||
<fault message="tns:TechIndisponibiliteErreur" name="TechIndisponibiliteErreur"/>
|
||||
<fault message="tns:TechProtocolaireErreur" name="TechProtocolaireErreur"/>
|
||||
</operation>
|
||||
</portType>
|
||||
<binding name="PaiementSecuriseServicePortBinding" type="tns:PaiementSecuriseService">
|
||||
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
|
||||
<operation name="creerPaiementSecurise">
|
||||
<soap:operation soapAction=""/>
|
||||
<input>
|
||||
<soap:body use="literal"/>
|
||||
</input>
|
||||
<output>
|
||||
<soap:body use="literal"/>
|
||||
</output>
|
||||
<fault name="FonctionnelleErreur">
|
||||
<soap:fault name="FonctionnelleErreur" use="literal"/>
|
||||
</fault>
|
||||
<fault name="TechDysfonctionnementErreur">
|
||||
<soap:fault name="TechDysfonctionnementErreur" use="literal"/>
|
||||
</fault>
|
||||
<fault name="TechIndisponibiliteErreur">
|
||||
<soap:fault name="TechIndisponibiliteErreur" use="literal"/>
|
||||
</fault>
|
||||
<fault name="TechProtocolaireErreur">
|
||||
<soap:fault name="TechProtocolaireErreur" use="literal"/>
|
||||
</fault>
|
||||
</operation>
|
||||
<operation name="recupererDetailClient">
|
||||
<soap:operation soapAction=""/>
|
||||
<input>
|
||||
<soap:body use="literal"/>
|
||||
</input>
|
||||
<output>
|
||||
<soap:body use="literal"/>
|
||||
</output>
|
||||
<fault name="FonctionnelleErreur">
|
||||
<soap:fault name="FonctionnelleErreur" use="literal"/>
|
||||
</fault>
|
||||
<fault name="TechDysfonctionnementErreur">
|
||||
<soap:fault name="TechDysfonctionnementErreur" use="literal"/>
|
||||
</fault>
|
||||
<fault name="TechIndisponibiliteErreur">
|
||||
<soap:fault name="TechIndisponibiliteErreur" use="literal"/>
|
||||
</fault>
|
||||
<fault name="TechProtocolaireErreur">
|
||||
<soap:fault name="TechProtocolaireErreur" use="literal"/>
|
||||
</fault>
|
||||
</operation>
|
||||
<operation name="recupererDetailPaiementSecurise">
|
||||
<soap:operation soapAction=""/>
|
||||
<input>
|
||||
<soap:body use="literal"/>
|
||||
</input>
|
||||
<output>
|
||||
<soap:body use="literal"/>
|
||||
</output>
|
||||
<fault name="FonctionnelleErreur">
|
||||
<soap:fault name="FonctionnelleErreur" use="literal"/>
|
||||
</fault>
|
||||
<fault name="TechDysfonctionnementErreur">
|
||||
<soap:fault name="TechDysfonctionnementErreur" use="literal"/>
|
||||
</fault>
|
||||
<fault name="TechIndisponibiliteErreur">
|
||||
<soap:fault name="TechIndisponibiliteErreur" use="literal"/>
|
||||
</fault>
|
||||
<fault name="TechProtocolaireErreur">
|
||||
<soap:fault name="TechProtocolaireErreur" use="literal"/>
|
||||
</fault>
|
||||
</operation>
|
||||
</binding>
|
||||
<service name="PaiementSecuriseService">
|
||||
<port name="PaiementSecuriseServicePort" binding="tns:PaiementSecuriseServicePortBinding">
|
||||
<soap:address location="http://www.tipi.budget.gouv.fr:80/tpa/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService"/>
|
||||
</port>
|
||||
</service>
|
||||
</definitions>
|
|
@ -0,0 +1,116 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.8 svn-revision#13980. --><xs:schema xmlns:ns2="http://securite.service.tpa.cp.finances.gouv.fr/reponse" xmlns:ns1="http://securite.service.tpa.cp.finances.gouv.fr/requete" xmlns:tns="http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService">
|
||||
|
||||
<xs:import namespace="http://securite.service.tpa.cp.finances.gouv.fr/requete" schemaLocation="PaiementSecuriseService2.xsd"/>
|
||||
|
||||
<xs:import namespace="http://securite.service.tpa.cp.finances.gouv.fr/reponse" schemaLocation="PaiementSecuriseService3.xsd"/>
|
||||
|
||||
<xs:element name="FonctionnelleErreur" type="tns:FonctionnelleErreur"/>
|
||||
|
||||
<xs:element name="TechDysfonctionnementErreur" type="tns:TechDysfonctionnementErreur"/>
|
||||
|
||||
<xs:element name="TechIndisponibiliteErreur" type="tns:TechIndisponibiliteErreur"/>
|
||||
|
||||
<xs:element name="TechProtocolaireErreur" type="tns:TechProtocolaireErreur"/>
|
||||
|
||||
<xs:element name="creerPaiementSecurise" type="tns:creerPaiementSecurise"/>
|
||||
|
||||
<xs:element name="creerPaiementSecuriseResponse" type="tns:creerPaiementSecuriseResponse"/>
|
||||
|
||||
<xs:element name="recupererDetailClient" type="tns:recupererDetailClient"/>
|
||||
|
||||
<xs:element name="recupererDetailClientResponse" type="tns:recupererDetailClientResponse"/>
|
||||
|
||||
<xs:element name="recupererDetailPaiementSecurise" type="tns:recupererDetailPaiementSecurise"/>
|
||||
|
||||
<xs:element name="recupererDetailPaiementSecuriseResponse" type="tns:recupererDetailPaiementSecuriseResponse"/>
|
||||
|
||||
<xs:complexType name="creerPaiementSecurise">
|
||||
<xs:sequence>
|
||||
<xs:element name="arg0" type="ns1:CreerPaiementSecuriseRequest" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="creerPaiementSecuriseResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="return" type="ns2:CreerPaiementSecuriseResponse" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="FonctionnelleErreur">
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="descriptif" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="libelle" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="message" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="severite" type="xs:int"/>
|
||||
<xs:element name="suppressed" type="tns:throwable" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="throwable">
|
||||
<xs:sequence>
|
||||
<xs:element name="stackTrace" type="tns:stackTraceElement" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="stackTraceElement" final="extension restriction">
|
||||
<xs:sequence/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TechDysfonctionnementErreur">
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="descriptif" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="libelle" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="message" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="severite" type="xs:int"/>
|
||||
<xs:element name="suppressed" type="tns:throwable" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TechIndisponibiliteErreur">
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="descriptif" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="libelle" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="message" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="severite" type="xs:int"/>
|
||||
<xs:element name="suppressed" type="tns:throwable" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="TechProtocolaireErreur">
|
||||
<xs:sequence>
|
||||
<xs:element name="code" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="descriptif" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="libelle" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="message" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="severite" type="xs:int"/>
|
||||
<xs:element name="suppressed" type="tns:throwable" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="recupererDetailClient">
|
||||
<xs:sequence>
|
||||
<xs:element name="arg0" type="ns2:RecupererDetailClientRequest" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="recupererDetailClientResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="return" type="ns2:RecupererDetailClientResponse" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="recupererDetailPaiementSecurise">
|
||||
<xs:sequence>
|
||||
<xs:element name="arg0" type="ns2:RecupererDetailPaiementSecuriseRequest" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="recupererDetailPaiementSecuriseResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="return" type="ns2:RecupererDetailPaiementSecuriseResponse" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.8 svn-revision#13980. --><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://securite.service.tpa.cp.finances.gouv.fr/requete">
|
||||
|
||||
<xs:complexType name="CreerPaiementSecuriseRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="exer" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="mel" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="montant" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="numcli" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="objet" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="refdet" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="saisie" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="urlnotif" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="urlredirect" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.2.8 svn-revision#13980. --><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://securite.service.tpa.cp.finances.gouv.fr/reponse">
|
||||
|
||||
<xs:complexType name="CreerPaiementSecuriseResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="idOp" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="RecupererDetailClientRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="numCli" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="RecupererDetailClientResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="libelleN1" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="libelleN2" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="libelleN3" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="numcli" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="IdentifiantGen" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="RecupererDetailPaiementSecuriseRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="idOp" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="RecupererDetailPaiementSecuriseResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="dattrans" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="exer" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="heurtrans" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="idOp" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="mel" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="montant" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="numauto" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="numcli" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="objet" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="refdet" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="resultrans" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="saisie" type="xs:string" minOccurs="0"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
2
setup.py
2
setup.py
|
@ -123,6 +123,8 @@ setuptools.setup(
|
|||
'pytz',
|
||||
'requests',
|
||||
'six',
|
||||
'click',
|
||||
'zeep',
|
||||
],
|
||||
cmdclass={
|
||||
'sdist': eo_sdist,
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
[["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:recupererDetailClient xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <numCli>090909</numCli>\n </arg0>\n </ns0:recupererDetailClient>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <ns2:recupererDetailClientResponse xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <return>\n <libelleN1>RR COMPOSTEURS INDIVIDUELS</libelleN1>\n <libelleN2>POUETPOUET</libelleN2>\n <libelleN3>COLLECTE VALORISATION DECHETS</libelleN3>\n <numcli>090909</numcli>\n </return>\n </ns2:recupererDetailClientResponse>\n </S:Body>\n</S:Envelope>\n"]]
|
|
@ -0,0 +1 @@
|
|||
[["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:creerPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <exer>2019</exer>\n <mel>john.doeexample.com</mel>\n <montant>9990000001</montant>\n <numcli>090909</numcli>\n <objet>coucou</objet>\n <refdet>ABCDEF</refdet>\n <saisie>T</saisie>\n <urlnotif>https://notif.payfip.example.com/</urlnotif>\n <urlredirect>https://redirect.payfip.example.com/</urlredirect>\n </arg0>\n </ns0:creerPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <S:Fault xmlns:ns4=\"http://www.w3.org/2003/05/soap-envelope\">\n <faultcode>S:Server</faultcode>\n <faultstring>fr.gouv.finances.cp.tpa.webservice.exceptions.FonctionnelleErreur</faultstring>\n <detail>\n <ns2:FonctionnelleErreur xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <code>A2</code>\n <descriptif/>\n <libelle>Adresse mél incorrecte. </libelle>\n <severite>2</severite>\n </ns2:FonctionnelleErreur>\n </detail>\n </S:Fault>\n </S:Body>\n</S:Envelope>\n"]]
|
|
@ -0,0 +1 @@
|
|||
[["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:creerPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <exer>2019</exer>\n <mel>john.doe@example.com</mel>\n <montant>1000</montant>\n <numcli>090909</numcli>\n <objet>coucou</objet>\n <refdet>ABCDEFGH</refdet>\n <saisie>T</saisie>\n <urlnotif>https://notif.payfip.example.com/</urlnotif>\n <urlredirect>https://redirect.payfip.example.com/</urlredirect>\n </arg0>\n </ns0:creerPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <ns2:creerPaiementSecuriseResponse xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <return>\n <idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp>\n </return>\n </ns2:creerPaiementSecuriseResponse>\n </S:Body>\n</S:Envelope>\n"]]
|
|
@ -0,0 +1 @@
|
|||
[["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:creerPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <exer>2019</exer>\n <mel>john.doe@example.com</mel>\n <montant>1000</montant>\n <numcli>090909</numcli>\n <objet>coucou</objet>\n <refdet>ABCD</refdet>\n <saisie>T</saisie>\n <urlnotif>https://notif.payfip.example.com/</urlnotif>\n <urlredirect>https://redirect.payfip.example.com/</urlredirect>\n </arg0>\n </ns0:creerPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <S:Fault xmlns:ns4=\"http://www.w3.org/2003/05/soap-envelope\">\n <faultcode>S:Server</faultcode>\n <faultstring>fr.gouv.finances.cp.tpa.webservice.exceptions.FonctionnelleErreur</faultstring>\n <detail>\n <ns2:FonctionnelleErreur xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <code>R3</code>\n <descriptif/>\n <libelle>Le format du paramètre REFDET n'est pas conforme</libelle>\n <severite>2</severite>\n </ns2:FonctionnelleErreur>\n </detail>\n </S:Fault>\n </S:Body>\n</S:Envelope>\n"]]
|
|
@ -0,0 +1 @@
|
|||
[["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:recupererDetailPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp>\n </arg0>\n </ns0:recupererDetailPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <S:Fault xmlns:ns4=\"http://www.w3.org/2003/05/soap-envelope\">\n <faultcode>S:Server</faultcode>\n <faultstring>fr.gouv.finances.cp.tpa.webservice.exceptions.FonctionnelleErreur</faultstring>\n <detail>\n <ns2:FonctionnelleErreur xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <code>P1</code>\n <descriptif/>\n <libelle>IdOp incorrect.</libelle>\n <severite>2</severite>\n </ns2:FonctionnelleErreur>\n </detail>\n </S:Fault>\n </S:Body>\n</S:Envelope>\n"]]
|
|
@ -0,0 +1 @@
|
|||
[["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:recupererDetailPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp>\n </arg0>\n </ns0:recupererDetailPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <S:Fault xmlns:ns4=\"http://www.w3.org/2003/05/soap-envelope\">\n <faultcode>S:Server</faultcode>\n <faultstring>fr.gouv.finances.cp.tpa.webservice.exceptions.FonctionnelleErreur</faultstring>\n <detail>\n <ns2:FonctionnelleErreur xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <code>P5</code><descriptif />\n <libelle>Résultat de la transaction non connu.</libelle><severite>2</severite>\n </ns2:FonctionnelleErreur>\n </detail>\n </S:Fault>\n </S:Body>\n</S:Envelope>\n"]]
|
|
@ -0,0 +1 @@
|
|||
[["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:recupererDetailPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp>\n </arg0>\n </ns0:recupererDetailPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <ns2:recupererDetailPaiementSecuriseResponse xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <return>\n <dattrans>12122019</dattrans><exer>20</exer><heurtrans>1311</heurtrans><idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp><mel>john.doe@example.com</mel><montant>1000</montant><numauto>112233445566-tip</numauto><numcli>090909</numcli><objet>coucou</objet><refdet>EFEFAEFG</refdet><resultrans>V</resultrans><saisie>T</saisie>\n </return>\n </ns2:recupererDetailPaiementSecuriseResponse>\n </S:Body>\n</S:Envelope>\n"]]
|
|
@ -0,0 +1,4 @@
|
|||
[
|
||||
["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:creerPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <exer>2019</exer>\n <mel>john.doe@example.com</mel>\n <montant>1000</montant>\n <numcli>090909</numcli>\n <refdet>201912261758460053903194</refdet>\n <saisie>T</saisie>\n <urlnotif>https://notif.payfip.example.com/</urlnotif>\n <urlredirect>https://redirect.payfip.example.com/</urlredirect>\n </arg0>\n </ns0:creerPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <ns2:creerPaiementSecuriseResponse xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <return>\n <idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp>\n </return>\n </ns2:creerPaiementSecuriseResponse>\n </S:Body>\n</S:Envelope>\n"],
|
||||
["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:recupererDetailPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp>\n </arg0>\n </ns0:recupererDetailPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <ns2:recupererDetailPaiementSecuriseResponse xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <return>\n <dattrans>12122019</dattrans><exer>20</exer><heurtrans>1311</heurtrans><idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp><mel>john.doe@example.com</mel><montant>1000</montant><numcli>090909</numcli><refdet>201912261758460053903194</refdet><resultrans>A</resultrans><saisie>T</saisie>\n </return>\n </ns2:recupererDetailPaiementSecuriseResponse>\n </S:Body>\n</S:Envelope>\n"]
|
||||
]
|
|
@ -0,0 +1,4 @@
|
|||
[
|
||||
["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:creerPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <exer>2019</exer>\n <mel>john.doe@example.com</mel>\n <montant>1000</montant>\n <numcli>090909</numcli>\n <refdet>201912261758460053903194</refdet>\n <saisie>T</saisie>\n <urlnotif>https://notif.payfip.example.com/</urlnotif>\n <urlredirect>https://redirect.payfip.example.com/</urlredirect>\n </arg0>\n </ns0:creerPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <ns2:creerPaiementSecuriseResponse xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <return>\n <idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp>\n </return>\n </ns2:creerPaiementSecuriseResponse>\n </S:Body>\n</S:Envelope>\n"],
|
||||
["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:recupererDetailPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp>\n </arg0>\n </ns0:recupererDetailPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <ns2:recupererDetailPaiementSecuriseResponse xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <return>\n <dattrans>12122019</dattrans><exer>20</exer><heurtrans>1311</heurtrans><idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp><mel>john.doe@example.com</mel><montant>1000</montant><numcli>090909</numcli><refdet>201912261758460053903194</refdet><resultrans>R</resultrans><saisie>T</saisie>\n </return>\n </ns2:recupererDetailPaiementSecuriseResponse>\n </S:Body>\n</S:Envelope>\n"]
|
||||
]
|
|
@ -0,0 +1,4 @@
|
|||
[
|
||||
["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:creerPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <exer>2019</exer>\n <mel>john.doe@example.com</mel>\n <montant>1000</montant>\n <numcli>090909</numcli>\n <refdet>201912261758460053903194</refdet>\n <saisie>T</saisie>\n <urlnotif>https://notif.payfip.example.com/</urlnotif>\n <urlredirect>https://redirect.payfip.example.com/</urlredirect>\n </arg0>\n </ns0:creerPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <ns2:creerPaiementSecuriseResponse xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <return>\n <idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp>\n </return>\n </ns2:creerPaiementSecuriseResponse>\n </S:Body>\n</S:Envelope>\n"],
|
||||
["<soap-env:Envelope xmlns:soap-env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <soap-env:Body>\n <ns0:recupererDetailPaiementSecurise xmlns:ns0=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <arg0>\n <idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp>\n </arg0>\n </ns0:recupererDetailPaiementSecurise>\n </soap-env:Body>\n</soap-env:Envelope>\n", "<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">\n <S:Body>\n <ns2:recupererDetailPaiementSecuriseResponse xmlns:ns2=\"http://securite.service.tpa.cp.finances.gouv.fr/services/mas_securite/contrat_paiement_securise/PaiementSecuriseService\">\n <return>\n <dattrans>12122019</dattrans><exer>20</exer><heurtrans>1311</heurtrans><idOp>cc0cb210-1cd4-11ea-8cca-0213ad91a103</idOp><mel>john.doe@example.com</mel><montant>1000</montant><numauto>112233445566-tip</numauto><numcli>090909</numcli><refdet>201912261758460053903194</refdet><resultrans>P</resultrans><saisie>T</saisie>\n </return>\n </ns2:recupererDetailPaiementSecuriseResponse>\n </S:Body>\n</S:Envelope>\n"]
|
||||
]
|
|
@ -0,0 +1,251 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
# eopayment - online payment library
|
||||
# Copyright (C) 2011-2019 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import json
|
||||
import lxml.etree as ET
|
||||
|
||||
import httmock
|
||||
import pytest
|
||||
|
||||
from zeep.plugins import HistoryPlugin
|
||||
|
||||
import eopayment
|
||||
from eopayment.payfip_ws import PayFiP, PayFiPError
|
||||
|
||||
|
||||
def xmlindent(content):
|
||||
if hasattr(content, 'encode') or hasattr(content, 'decode'):
|
||||
content = ET.fromstring(content)
|
||||
return ET.tostring(content, pretty_print=True).decode('utf-8', 'ignore')
|
||||
|
||||
NUMCLI = '090909'
|
||||
|
||||
|
||||
# freeze time to fix EXER field to 2019
|
||||
@pytest.fixture(autouse=True)
|
||||
def freezer(freezer):
|
||||
freezer.move_to('2019-12-12')
|
||||
|
||||
|
||||
class PayFiPHTTMock(object):
|
||||
def __init__(self, request):
|
||||
history_path = 'tests/data/payfip-%s.json' % request.function.__name__
|
||||
with open(history_path) as fd:
|
||||
self.history = json.load(fd)
|
||||
self.counter = 0
|
||||
|
||||
@httmock.urlmatch()
|
||||
def mock(self, url, request):
|
||||
request_content, response_content = self.history[self.counter]
|
||||
self.counter += 1
|
||||
assert xmlindent(request.body) == request_content
|
||||
return response_content
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def payfip(request):
|
||||
history = HistoryPlugin()
|
||||
|
||||
@httmock.urlmatch()
|
||||
def raise_on_request(url, request):
|
||||
# ensure we do not access network
|
||||
from requests.exceptions import RequestException
|
||||
raise RequestException('huhu')
|
||||
|
||||
with httmock.HTTMock(raise_on_request):
|
||||
payfip = PayFiP(wsdl_url='file://eopayment/resource/PaiementSecuriseService.wsdl',
|
||||
zeep_client_kwargs={'plugins': [history]})
|
||||
try:
|
||||
if 'update_data' not in request.keywords:
|
||||
with httmock.HTTMock(PayFiPHTTMock(request).mock):
|
||||
yield payfip
|
||||
else:
|
||||
yield payfip
|
||||
finally:
|
||||
# add @pytest.mark.update_data to test to update fixtures data
|
||||
if 'update_data' in request.keywords:
|
||||
history_path = 'tests/data/payfip-%s.json' % request.function.__name__
|
||||
d = [
|
||||
(xmlindent(exchange['sent']['envelope']),
|
||||
xmlindent(exchange['received']['envelope']))
|
||||
for exchange in history._buffer
|
||||
]
|
||||
content = json.dumps(d)
|
||||
with open(history_path, 'wb') as fd:
|
||||
fd.write(content)
|
||||
|
||||
# pytestmark = pytest.mark.update_data
|
||||
|
||||
|
||||
def test_get_client_info(payfip):
|
||||
result = payfip.get_info_client(NUMCLI)
|
||||
assert result.numcli == NUMCLI
|
||||
assert result.libelleN2 == 'POUETPOUET'
|
||||
|
||||
NOTIF_URL = 'https://notif.payfip.example.com/'
|
||||
REDIRECT_URL = 'https://redirect.payfip.example.com/'
|
||||
|
||||
|
||||
def test_get_idop_ok(payfip):
|
||||
result = payfip.get_idop(
|
||||
numcli=NUMCLI,
|
||||
exer='2019',
|
||||
refdet='ABCDEFGH',
|
||||
montant='1000',
|
||||
mel='john.doe@example.com',
|
||||
objet='coucou',
|
||||
url_notification=NOTIF_URL,
|
||||
url_redirect=REDIRECT_URL,
|
||||
saisie='T')
|
||||
assert result == 'cc0cb210-1cd4-11ea-8cca-0213ad91a103'
|
||||
|
||||
|
||||
def test_get_idop_refdet_error(payfip):
|
||||
with pytest.raises(PayFiPError, match='.*R3.*Le format.*REFDET.*conforme'):
|
||||
payfip.get_idop(
|
||||
numcli=NUMCLI,
|
||||
exer='2019',
|
||||
refdet='ABCD',
|
||||
montant='1000',
|
||||
mel='john.doe@example.com',
|
||||
objet='coucou',
|
||||
url_notification='https://notif.payfip.example.com/',
|
||||
url_redirect='https://redirect.payfip.example.com/',
|
||||
saisie='T')
|
||||
|
||||
|
||||
def test_get_idop_adresse_mel_incorrect(payfip):
|
||||
with pytest.raises(PayFiPError, match='.*A2.*Adresse.*incorrecte'):
|
||||
payfip.get_idop(
|
||||
numcli=NUMCLI,
|
||||
exer='2019',
|
||||
refdet='ABCDEF',
|
||||
montant='9990000001',
|
||||
mel='john.doeexample.com',
|
||||
objet='coucou',
|
||||
url_notification='https://notif.payfip.example.com/',
|
||||
url_redirect='https://redirect.payfip.example.com/',
|
||||
saisie='T')
|
||||
|
||||
|
||||
def test_get_info_paiement_ok(payfip):
|
||||
result = payfip.get_info_paiement('cc0cb210-1cd4-11ea-8cca-0213ad91a103')
|
||||
assert {k: result[k] for k in result} == {
|
||||
'dattrans': '12122019',
|
||||
'exer': '20',
|
||||
'heurtrans': '1311',
|
||||
'idOp': 'cc0cb210-1cd4-11ea-8cca-0213ad91a103',
|
||||
'mel': 'john.doe@example.com',
|
||||
'montant': '1000',
|
||||
'numauto': '112233445566-tip',
|
||||
'numcli': NUMCLI,
|
||||
'objet': 'coucou',
|
||||
'refdet': 'EFEFAEFG',
|
||||
'resultrans': 'V',
|
||||
'saisie': 'T'
|
||||
}
|
||||
|
||||
|
||||
def test_get_info_paiement_P1(payfip):
|
||||
# idop par pas encore reçu par la plate-forme ou déjà nettoyé (la nuit)
|
||||
with pytest.raises(PayFiPError, match='.*P1.*IdOp incorrect.*'):
|
||||
payfip.get_info_paiement('cc0cb210-1cd4-11ea-8cca-0213ad91a103')
|
||||
|
||||
|
||||
def test_get_info_paiement_P5(payfip):
|
||||
# idop reçu par la plate-forme mais transaction en cours
|
||||
with pytest.raises(PayFiPError, match='.*P5.*sultat de la transaction non connu.*'):
|
||||
payfip.get_info_paiement('cc0cb210-1cd4-11ea-8cca-0213ad91a103')
|
||||
|
||||
|
||||
def test_payment_ok(request):
|
||||
payment = eopayment.Payment('payfip_ws', {
|
||||
'numcli': '090909',
|
||||
'automatic_return_url': NOTIF_URL,
|
||||
'normal_return_url': REDIRECT_URL,
|
||||
})
|
||||
|
||||
with httmock.HTTMock(PayFiPHTTMock(request).mock):
|
||||
payment_id, kind, url = payment.request(
|
||||
amount='10.00',
|
||||
email='john.doe@example.com',
|
||||
# make test deterministic
|
||||
refdet='201912261758460053903194')
|
||||
|
||||
assert payment_id == 'cc0cb210-1cd4-11ea-8cca-0213ad91a103'
|
||||
assert kind == eopayment.URL
|
||||
assert url == 'https://www.tipi.budget.gouv.fr/tpa/paiementws.web?idop=cc0cb210-1cd4-11ea-8cca-0213ad91a103'
|
||||
|
||||
response = payment.response('idop=%s' % payment_id)
|
||||
assert response.result == eopayment.PAID
|
||||
assert response.bank_status == ''
|
||||
assert response.order_id == payment_id
|
||||
assert response.transaction_id == (
|
||||
'201912261758460053903194 cc0cb210-1cd4-11ea-8cca-0213ad91a103 112233445566-tip')
|
||||
|
||||
|
||||
def test_payment_denied(request):
|
||||
payment = eopayment.Payment('payfip_ws', {
|
||||
'numcli': '090909',
|
||||
'automatic_return_url': NOTIF_URL,
|
||||
'normal_return_url': REDIRECT_URL,
|
||||
})
|
||||
|
||||
with httmock.HTTMock(PayFiPHTTMock(request).mock):
|
||||
payment_id, kind, url = payment.request(
|
||||
amount='10.00',
|
||||
email='john.doe@example.com',
|
||||
# make test deterministic
|
||||
refdet='201912261758460053903194')
|
||||
|
||||
assert payment_id == 'cc0cb210-1cd4-11ea-8cca-0213ad91a103'
|
||||
assert kind == eopayment.URL
|
||||
assert url == 'https://www.tipi.budget.gouv.fr/tpa/paiementws.web?idop=cc0cb210-1cd4-11ea-8cca-0213ad91a103'
|
||||
|
||||
response = payment.response('idop=%s' % payment_id)
|
||||
assert response.result == eopayment.DENIED
|
||||
assert response.bank_status == 'refused'
|
||||
assert response.order_id == payment_id
|
||||
assert response.transaction_id == '201912261758460053903194 cc0cb210-1cd4-11ea-8cca-0213ad91a103'
|
||||
|
||||
|
||||
def test_payment_cancelled(request):
|
||||
payment = eopayment.Payment('payfip_ws', {
|
||||
'numcli': '090909',
|
||||
'automatic_return_url': NOTIF_URL,
|
||||
'normal_return_url': REDIRECT_URL,
|
||||
})
|
||||
|
||||
with httmock.HTTMock(PayFiPHTTMock(request).mock):
|
||||
payment_id, kind, url = payment.request(
|
||||
amount='10.00',
|
||||
email='john.doe@example.com',
|
||||
# make test deterministic
|
||||
refdet='201912261758460053903194')
|
||||
|
||||
assert payment_id == 'cc0cb210-1cd4-11ea-8cca-0213ad91a103'
|
||||
assert kind == eopayment.URL
|
||||
assert url == 'https://www.tipi.budget.gouv.fr/tpa/paiementws.web?idop=cc0cb210-1cd4-11ea-8cca-0213ad91a103'
|
||||
|
||||
response = payment.response('idop=%s' % payment_id)
|
||||
assert response.result == eopayment.CANCELLED
|
||||
assert response.bank_status == 'cancelled'
|
||||
assert response.order_id == payment_id
|
||||
assert response.transaction_id == '201912261758460053903194 cc0cb210-1cd4-11ea-8cca-0213ad91a103'
|
Loading…
Reference in New Issue