SDICoop Ricezione - 2024 English / French tutorial - Nginx, uwsgi, Python, Django

Preamble: Everything that follows is to be taken with some distance (both technical and human), and all comments are my personal opinion. This is just my experience as a developer.

This text was originally written in French (in next post), then translated into English. Sorry if there are any odd turns of phrase.

As I’m a new member I can’t add more than 4 links in my message so I’ve had to enter them without it being a real link, sorry. I’ll edit my message once I can.

Hello everyone,

I’ve just finished integrating Ricezione in very basic mode (only “WSR01” the first item in the test plan, i.e. receive an invoice or batch, and answer OK = ER01) for a French company, and I’m posting this information in English/French to help as many people as possible in my case, as I had to consult and translate many, many resources to do so, since the English documentation is incomplete and poorly translated, the test system complex and obscure, and pretty much the only useful exchanges are here, in Italian - quite logical since it’s your official language, and thanks to all of you for posting all this and exchanging in public! :slight_smile:

So our integration concerns a company under French law (with a French VAT number) and our server/webapp uses the technologies mentioned in the title, but I think 95% of what I’m presenting is adaptable and will be useful to everyone.

STEP 0 - Acquire a PEC address

This is essential for accreditation.

Not all PEC providers accept French companies, there are several possibilities, but we have chosen Intesi Group: www.intesigroup. com/en/pec/

STEP 1 - “Richiesta di accreditamento canale” channel accreditation request

The FAQ in English: www.fatturapa.gov.it/en/faq/faq-accreditamento-canale/

The form: www.fatturapa.gov.it/en/servizionline/accreditare-il-canale/

Here we will choose only “SDICoop - Reception Service”.

Fill in the information, bearing in mind that for the “Riferimento Accordo” / “Contact for the service agreement” tax code you need to enter the company’s VAT number again, since you don’t have an Italian personal tax code.

Then put in bogus endpoints like sdi.votredomaine. fr/sdi_reception. There’s no instant test, and you can change them later.

For CSR and certificates (for a french company with a SIREN) :

  • Generate a private key

openssl genrsa -out sdi-{{SIREN}}-client.key 2048

  • Generate CSR

openssl req -new -key sdi-{{SIREN}}-client.key -out sdi-{{SIREN}}-client.csr

  • Enter
    Country Name : FR
    State or Province Name : {{postal code}}
    Locality Name : {{city}}
    Organization Name : {{legal company name entered on 1st page}}
    Common Name : SDI-{{SIREN}}

openssl genrsa -out sdi-{{SIREN}}-server.key 2048

openssl req -new -key sdi-{{SIREN}}-server.key -out sdi-{{SIREN}}-server.csr

Keep all these files in a safe place…

At the end, you’ll get a “RichiestaAccreditamento.zip” file, which you should also keep.

STEP 2 - Sign the zip

This step was imho totally uncalled-for, but you’re going to have to buy a QES eIDAS certificate from a company recognized by ADIG (spoiler it’s only Italian companies, the list is here www.agid. gov.it/it/piattaforme/firma-elettronica-qualificata/prestatori-di-servizi-fiduciari-attivi-in-italia) even though it’s a European standard and all QES eIDAS should be recognized. Anyway.

That’s all it’ll do, sign the zip at the start. Then you can throw it away…

We chose Infocert:
infocert. digital/consumer/qes/
checkout.infocert. digital/articles/SIGN-QES-EDOCID

We had the QES drawn up in the name of the company CEO, who is also the “Riferimento Accordo” / “Contact for the service agreement” and it was OK.

They have a signature system in their Gosign webapp that works pretty well, so we didn’t look any further.

You need to sign the zip in CAdES (.p7m), not detached (.p7s).

Keep the RichiestaAccreditamento.zip.p7m in a safe place, as this is what will allow you to connect to the SdI accreditation webapp !!!

STEP 3 - Send the signed zip

Connect to your PEC and send an email to the address given at the end of the accreditation form, type “sdi01@pec.fatturapa.it” (01 can be 02 03 etc), with the RichiestaAccreditamento.zip.p7m in attachment.

If everything is OK, you’ll receive an email back fairly quickly with the subject line “POSTA CERTIFICATA: [Sistema di Interscambio]: richiesta presa in carico”.

STEP 4 - Log in to Manage the channel “Gestire il canale“ / “Manage the channel“

Once you’ve received the email from sdi confirming that it’s OK, go to Fatturazione elettronica per la P.A., select the .zip.p7m and enter the captcha.

The interface is one time out of 2 in English or Italian…no way to change it manually.

Go to “Test Interoperabilità (Sdicoop)” / “Interoperability tests”, you’ll first be asked to download the “KitDiTest”, then you can access “Gestione test di Interoperabilità” / “Manage interoperability tests”.

You can also modify endpoints at any time by clicking on “Modificare Endpoint” / “Change Endpoint“.

STEP 5 - Preparing certificates

  • Convert the cer server supplied to pem

openssl x509 -inform der -in SDI-{{SIREN}}-server.cer -out SDI-{{SIREN}}-server.pem

  • Convert CA certs to pem

openssl x509 -keyform DER -in caentrate.cer -out caentrate.pem
openssl x509 -keyform DER -in SistemaInterscambioFatturaPA.cer -out SistemaInterscambioFatturaPA.pem
openssl x509 -keyform DER -in CAEntratetest.cer -out CAEntratetest.pem
openssl x509 -keyform DER -in SistemaInterscambioFatturaPATest.cer -out SistemaInterscambioFatturaPATest.pem

  • Create the certificate chain for nginx
    Copy these 5 certificates into sdi-chain-all.pem, putting the SDI-{{SIREN}}-server.pem FIRST (very important!).
    You can, of course, put only the test certs in test and prod in prod.

  • Optional : Create the certificate chain to verify the client certificate from SdICoop (= authenticate it’s really the SdI sending you invoices)
    Copy the last 4 certificates (not the SDI-{{SIREN}}-server.pem) into sdi-chain-trusted.pem

STEP 6 - Configuring the server

I won’t go into detail here, but you’ll need to :

  • Set up a dedicated sub-domain (to be able to configure another server directive on nginx with specific TLS certs)

  • Configure a dedicated uwsgi worker (simpler for debugging, maintenance etc.)

  • Configure nginx, that’s our conf.
    !!! VERY IMPORTANT!!!
    SdI doesn’t manage SNI (Server Name Indication)…So this server directive for SdI must be the 1st one in your nginx conf otherwise it won’t work…

server {
    listen {{server_ip}}:80 ssl;
    listen {{server_ip}}:443 ssl;
    server_name sdicoop.{{domain}}.com;

    proxy_connect_timeout 100s;
    proxy_send_timeout 100s;
    proxy_read_timeout 100s;
    send_timeout 100s;
    uwsgi_connect_timeout 100s;
    uwsgi_send_timeout 100s;
    uwsgi_read_timeout 100s;

    ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_certificate {{certs_dir}}/sdi-chain-all.pem;
    ssl_certificate_key {{certs_dir}}/sdi-{{SIREN}}-server.key;

    ###
    # Either that
    ssl_verify_client off;
    # Or that
    ssl_verify_client on;
    ssl_verify_depth 5;
    ssl_certificate {{certs_dir}}/sdi-chain-trusted.pem;
    ###

    ssl_stapling off;
    ssl_stapling_verify off;

    ...

    location /sdicoop_reception {
        # Useful for debugging, you can put 2 different files back in production
        access_log {{logs_dir}}/nginx-sdicoop-access.log;
        error_log {{logs_dir}}/nginx-sdicoop-access.log warn;

        uwsgi_pass unix:/path/to/uwsgi_sdi.sock;
        uwsgi_param Host $host;
        uwsgi_param X-Real-IP $remote_addr;
        uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
        uwsgi_param X-Forwarded-Proto $http_x_forwarded_proto;
    }
}
  • Serving SOAP code

This is fairly simple for the dev stage, but you can add to it as needed: I have a Django url+view that logs and responds to ER01 in the correct SOAP format

@csrf_exempt
def sdicoop_reception(request):
    logger.debug(“sdicoop_reception !”)
    logger.debug(request.headers)
    logger.debug(request.body)

    response = “<soapenv:Envelope xmlns:soapenv=\”http://schemas.xmlsoap.org/soap/envelope/\“>”
    response += “<soapenv:Body>”
    response += “<ns2:fileSdIConMetadati xmlns:ns2=\”http://www.fatturapa.gov.it/sdi/ws/ricezione/v1.0/types\“>”
    response += “<Esito>ER01</Esito>”
    response += “</ns2:fileSdIConMetadati>”
    response += “</soapenv:Body>”
    response += “</soapenv:Envelope>”

    return HttpResponse(response, content_type=“text/xml”)

STEP 8 - Testing TLS

  • Test, you should have a line “Verify return code: 19 (self-signed certificate in certificate chain)”

openssl s_client -connect sdicoop.{{domain}}.com:443 -CAfile CAEntratetest.pem

  • Prod, you should have a line “Verify return code: 0 (ok)”

openssl s_client -connect sdicoop.{{domain}}.com:443 -CAfile CAEntratetest.pem

If you don’t have these lines, there’s no point in going any further, there’s a problem in your configuration somewhere… Repeat all the points 1 by 1.

STEP 7 - Simulate shipments “Simulatore invio“ / “Simulator sending“

Once all this is available online, go to “Simulatore invio”. To start simple you can choose the 1st option of the 3 choices, then “Invia”.

You can see the progress and history on “Flussi” (flows).

Normally this should go straight through and you’ll see a green tick on Flussi and the first WSR01 “Ricezione Fattura” test validated on “Avanzamento“ (progress)!

This is the only compulsory test, so afterwards you can go to “Richiesta di passaggio in produzione” (Request passage into production).

NB: Once you’ve gone into production, you won’t be able to run tests or access this section (“Test Interoperabilità”), but you will still be able to access “Modificare Endpoint”. So if you want to validate the other 3 optional tests for B2G, or run more extensive tests with batches of invoices, Cades, etc., don’t go to prod just yet!

I’d like to take this opportunity to say that it’s a real shame not to leave the possibility of continuing to simulate sendings, which would make it possible to gradually integrate and potentially debug more easily. If ever someone from SdI reads me…

Don’t hesitate if you have any questions in English or French, I’ll try to answer them!

Good luck to you all!
JB

1 Mi Piace

VERSION FRANCAISE

Préambule : Tout ce qui suit est à prendre avec du recul (technique comme humain), et toutes les remarques ne sont que mon avis personnel. Ce n’est que mon expérience de développeur.

Ce texte a d’abord été rédigé en français puis traduit en anglais, désolé si il y a des tournures bizarres.

Comme je suis un nouveau membre je ne peux mettre que 4 liens dans mon message, j’ai du les modifier mais je les remettrais plus tard.

Bonjour tout le monde,

Je viens de terminer l’intégration de Ricezione en mode très basique (uniquement “WSR01” le premier item du plan de test, à savoir recevoir une facture ou un lot, et répondre OK = ER01) pour une société française, et je poste ces informations en Anglais / Français pour aider le maximum de gens dans mon cas car j’ai du consulter et traduire de très nombreuses ressources pour y arriver puisque la documentation en anglais est incomplète et mal traduite, le système de test complexe et obscur, et quasiment les seuls échanges utiles sont ici, en italien - tout à fait logique puisque c’est votre langue officielle et merci à tous de poster tout cela et d’échanger en public ! :slight_smile:

Notre intégration concerne donc une société de droit français (avec numéro de TVA français) et notre serveur/webapp utilise les technologies citées dans le titre, mais je pense que 95% de ce que je présente est adaptable et sera utile à tout le monde.

ETAPE 0 - Acquérir une adresse PEC

Cela est indispensable pour l’accréditation.

Attention tous les fournisseurs PEC n’acceptent pas les sociétés francaises, il y a plusieurs possibilités mais nous avons choisi Intesi Group.

ETAPE 1 - Demande pour Accréditer le canal “Richiesta di accreditamento canale”

La FAQ en anglais : www.fatturapa.gov.it/en/faq/faq-accreditamento-canale/

Le formulaire : www.fatturapa.gov.it/en/servizionline/accreditare-il-canale/

Ici on ne va choisir que “SDICoop - Reception Service”.

Remplissez les informations en sachant que pour le tax code du “Contact for the service agreement” il faut remettre le numéro de TVA de la société puisque vous n’avez pas de code fiscal personnel italien.

Ensuite vous mettez des endpoints bidons du type “sdi.votredomaine. fr/sdi_reception”, il n’y a pas de test instantané et vous pourrez les changer plus tard.

Pour la CSR et les certificats :

  • Générer une clé privée

openssl genrsa -out sdi-{{SIREN}}-client.key 2048

  • Générer la CSR

openssl req -new -key sdi-{{SIREN}}-client.key -out sdi-{{SIREN}}-client.csr

Entrer
Country Name : FR
State or Province Name : {{code postal}}
Locality Name : {{ville}}
Organization Name : {{nom légal société renseigné à la 1ère page}}
Common Name : SDI-{{SIREN}}

openssl genrsa -out sdi-{{SIREN}}-server.key 2048

openssl req -new -key sdi-{{SIREN}}-server.key -out sdi-{{SIREN}}-server.csr

Bien conserver tous ces fichiers…

Vous allez récupérer à la fin un fichier “RichiestaAccreditamento.zip” à bien conserver également.

ETAPE 2 - Signer le zip

L’étape complétement abusée mais vous allez devoir acheter un certificat QES eIDAS auprès d’une société reconnue par l’ADIG (spoiler c’est que des boîtes italiennes, la liste ici www.agid. gov.it/it/piattaforme/firma-elettronica-qualificata/prestatori-di-servizi-fiduciari-attivi-in-italia) alors que c’est une norme européenne et que tous les QES eIDAS devraient être reconnus. Bref.

Il ne servira qu’à ca, signer le zip au départ. Vous pouvez le jeter ensuite…

On a choisi Infocert :
infocert. digital/consumer/qes/
checkout.infocert. digital/articles/SIGN-QES-EDOCID

Nous avons fait établir le QES au nom du Directeur de la société, qui est aussi le “Riferimento Accordo” / “Contact for the service agreement” et c’était OK.

Ils ont un système de signature dans leur webapp Gosign qui fonctionne pas trop mal donc on a pas cherché plus loin.

Il faut signer le zip en CAdES (.p7m) et pas détachée / detached qui serait en .p7s.

Conservez précieusement le RichiestaAccreditamento.zip.p7m, c’est lui qui vous permettra de vous connecter à la webapp d’accréditation du SdI !!!

ETAPE 3 - Envoyer le zip signé

Connectez-vous à votre PEC et envoyez un email à l’adresse reçue à la fin du formulaire d’accréditation, du type “sdi01@pec.fatturapa.it” (le 01 peut être 02 03 etc), avec en PJ le RichiestaAccreditamento.zip.p7m

Si tout est OK vous recevrez un email en retour assez rapidement avec un sujet “POSTA CERTIFICATA: [Sistema di Interscambio]: richiesta presa in carico”

ETAPE 4 - Se connecter à Gérer le canal “Gestire il canale” / “Manage the channel”

Une fois que vous avez reçu l’email du sdi vous confirmant que c’est OK, allez sur Fatturazione elettronica per la P.A., sélectionnez le .zip.p7m et entrez le captcha.

L’interface est une fois sur 2 en anglais ou italien…pas moyen de changer manuellement.

Allez sur “Test Interoperabilità (Sdicoop)” / “Interoperability tests”, on vous demandera d’abord de télécharger le “KitDiTest”, puis vous pourrez accéder à " Gestione test di Interoperabilità" / “Manage interoperability tests”.

Vous pouvez aussi modifier les endpoints quand vous le voulez sur “Modificare Endpoint” / “Change Endpoint”.

ETAPE 5 - Préparer les certificats

  • Convertir le cer server fourni en pem

openssl x509 -inform der -in SDI-{{SIREN}}-server.cer -out SDI-{{SIREN}}-server.pem

  • Convertir les CA certs en pem

openssl x509 -keyform DER -in caentrate.cer -out caentrate.pem
openssl x509 -keyform DER -in SistemaInterscambioFatturaPA.cer -out SistemaInterscambioFatturaPA.pem
openssl x509 -keyform DER -in CAEntratetest.cer -out CAEntratetest.pem
openssl x509 -keyform DER -in SistemaInterscambioFatturaPATest.cer -out SistemaInterscambioFatturaPATest.pem

  • Créer le certificate chain pour nginx
    Copier ces 5 certificats dans sdi-chain-all.pem en mettant le SDI-{{SIREN}}-server.pem EN PREMIER (très important !)
    Vous pouvez ne mettre que les certs de test pour les tests et prod en prod bien entendu.

  • Optionnel : Créer le certificate chain pour vérifier le certificat client de SdiCoop (= authentifier que c’est réellement le SdI qui vous envoie des factures)
    Copier les 4 derniers certificats (pas le SDI-{{SIREN}}-server.pem) dans sdi-chain-trusted.pem

ETAPE 6 - Configurer le serveur

Je ne vais pas rentrer dans le détail mais il faut :

  • Configurer un sous-domaine dédié (pour pouvoir configurer une autre directive server sur nginx avec les certs TLS spécifiques)

  • Configurer un worker dédié uwsgi (plus simple pour débug, maintenance etc)

  • Configurer nginx, voilà notre conf.
    !!! TRES IMPORTANT !!!
    Le SdI ne gère pas le SNI (Server Name Indication)…Donc cette directive server pour le SdI doit impérativement être la 1ère dans votre conf nginx sinon cela ne fonctionnera pas…

server {
    listen {{server_ip}}:80 ssl;
    listen {{server_ip}}:443 ssl;
    server_name sdicoop.{{domaine}}.com;

    proxy_connect_timeout       100s;
    proxy_send_timeout          100s;
    proxy_read_timeout          100s;
    send_timeout                100s;
    uwsgi_connect_timeout       100s;
    uwsgi_send_timeout          100s;
    uwsgi_read_timeout          100s;

    ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    ssl_certificate {{certs_dir}}/sdi-chain-all.pem;
    ssl_certificate_key {{certs_dir}}/sdi-{{SIREN}}-server.key;

    ###
    # Soit ca
    ssl_verify_client off;
    # Soit ca
    ssl_verify_client on;
    ssl_verify_depth 5;
    ssl_certificate {{certs_dir}}/sdi-chain-trusted.pem;
    ###

    ssl_stapling off;
    ssl_stapling_verify off;

    ...

    location /sdicoop_reception {
        # Utile pour le debug, vous pourrez remettre 2 fichiers différents en prod
        access_log  {{logs_dir}}/nginx-sdicoop-access.log;
        error_log  {{logs_dir}}/nginx-sdicoop-access.log warn;

        uwsgi_pass                      unix:/path/to/uwsgi_sdi.sock;
        uwsgi_param Host                $host;
        uwsgi_param X-Real-IP           $remote_addr;
        uwsgi_param X-Forwarded-For     $proxy_add_x_forwarded_for;
        uwsgi_param X-Forwarded-Proto   $http_x_forwarded_proto;
    }
}
  • Servir le code SOAP

Là c’est assez simple pour l’étape dev, à étoffer ensuite selon vos besoins : j’ai une url+view Django qui log et répond ER01 dans le bon format SOAP

@csrf_exempt
def sdicoop_reception(request):
    logger.debug("sdicoop_reception !")
    logger.debug(request.headers)
    logger.debug(request.body)

    response = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">"
    response += "<soapenv:Body>"
    response += "<ns2:fileSdIConMetadati xmlns:ns2=\"http://www.fatturapa.gov.it/sdi/ws/ricezione/v1.0/types\">"
    response += "<Esito>ER01</Esito>"
    response += "</ns2:fileSdIConMetadati>"
    response += "</soapenv:Body>"
    response += "</soapenv:Envelope>"

    return HttpResponse(response, content_type="text/xml")

ETAPE 8 - Tester le TLS

  • Test, vous devez avoir une ligne “Verify return code: 19 (self-signed certificate in certificate chain)”

openssl s_client -connect sdicoop.{{domaine}}.com:443 -CAfile CAEntratetest.pem

  • Prod, vous devez avoir une ligne “Verify return code: 0 (ok)”

openssl s_client -connect sdicoop.{{domaine}}.com:443 -CAfile CAEntratetest.pem

Si vous n’avez pas ces lignes, ca ne sert à rien d’aller plus loin, il y a un soucis dans votre config quelque part…Reprenez tous les points 1 par 1.

ETAPE 7 - Simuler des envois “Simulatore invio” / “Simulator sending”

Une fois tout cela dispo en ligne, allez sur “Simulatore invio”. Basiquement vous pouvez choisir la 1ère option des 3 choix, puis “Invia”

Vous pouvez voir l’avancée et l’historique sur “Flussi” (flux).

Normalement cela devrait passer directement et vous verrez une coche verte sur Flussi et le premier test WSR01 “Ricezione Fattura” validé sur Avanzamento (avancement) !

C’est le seul obligatoire donc ensuite vous pouvez aller sur “Richiesta di passaggio in produzione” (Demander le passage en production)

NB : Une fois passé en prod vous ne pourrez plus faire des tests et plus accéder à cette section là (“Test Interoperabilità”) mais vous pourrez toujours accéder à “Modificare Endpoint”. Donc si vous voulez valider les 3 autres tests facultatifs pour le B2G, ou bien faire des tests plus amples avec des lots de factures, du Cades, etc, ne passez pas tout de suite en prod !

J’en profite pour dire que c’est vraiment dommage de ne pas laisser la possibilité de continuer à simuler des envois ce qui permettrait d’intégrer progressivement et potentiellement faire plus facilement des débugs. Si jamais quelqu’un du SdI me lit…

Voilà je crois que j’ai fait le tour, n’hésitez pas si vous avez la moindre question en anglais ou français j’essaierai d’y répondre !

Bon courage à tous !
JB

Do you mean ssl_client_certificate {{certs_dir}}/sdi-chain-trusted.pem;, right?