Prima di poter interagire con il sistema di interscambio (SdI) bisogna fare l'accreditamento del canale. Una volta fatto ciò ti verrà fornito un "Kit di Test" contenete i seguenti certificati:
- testservizi.fatturapa.it.cer
- SistemaInterscambioFatturaPATest.cer
- servizi.fatturapa.it.cer
- SistemaInterscambioFatturaPA.cer
- caentrate.der
- CAEntratetest.cer
E, sempre dalla pagina di gestione del canale, potrai scaricare due certificati (per client e server) chiamati SDI-
Oltre a tutto ciò avrai a disposizione i file *.key
e *.cer
che hai utilizzato per l'accreditamento del canale.
Come si usano questi certificati? #
Per utilizzare questi certificati all'interno di un client PHP è necessario ottenere delle chiavi derivate che PHP sia in grado di trattare.
In particolare il file SDI-<PartitaIVA>.cer
del client (per comodità ora mi riferirò a questo file indicandolo SDI-12345678-client.cer
) dovrà essere convertito nel formato .pem tramite il seguente comando:
openssl x509 -inform der -in SDI-12345678-client.cer -out SDI-12345678-client.pem
Inoltre dovrai unire i certificati caentrate.der
e CAEntratetest.cer
con questo comando:
cat caentrate.der <(echo) CAEntratetest.cer > CA_Agenzia_delle_Entrate_all.pem
È fondamentale che inizio e fine dei singoli certificati siano su linee differenti
NOTA: aprendo il file CA_Agenzia_delle_Entrate_all.pem
con un editor di testo è fondamentale verificare che END CERTIFICATE e BEGIN CERTIFICATE siano su due linee separate.
A questo punto io ho esteso il SoapClient
di PHP per poter utilizzare curl in modo da avere la possibilità di fare il debug di tutto ciò che accade durante la chiamata.
<?php
class DebugSoapClient extends \SoapClient
{
/**
* @inheritdoc
*/
public function __doRequest($request, $location, $action, $version, $one_way = null)
{
$soap_request = $request;
$certspath = __dir__ . "/certs/";
//CA file
$cafile = "CA_Agenzia_delle_Entrate_all.pem";
//PRIVATE KEY client file
$keyFile = "private-client.key";
//Client CERT file
$clientCertFile = "SDI-12345678-client.pem";
$header = [
'Content-type: text/xml;charset="utf-8"',
'Accept: text/xml',
'Cache-Control: no-cache',
'Pragma: no-cache',
"SOAPAction: {$action}",
'Content-length: ' . strlen($soap_request),
];
$soap_do = curl_init();
$url = $location;
$options = [
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSLKEY => $certspath . $keyFile,
CURLOPT_SSLCERT => $certspath . $clientCertFile,
CURLOPT_CAINFO => $certspath . $cafile,
CURLOPT_SSL_ENABLE_ALPN => false,
CURLOPT_TIMEOUT => 60,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
CURLOPT_VERBOSE => true,
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $soap_request,
CURLOPT_HTTPHEADER => $header,
];
curl_setopt_array($soap_do, $options);
$output = curl_exec($soap_do);
var_dump('curl output = ');
var_dump($output);
$info = curl_getinfo($soap_do);
var_dump('curl info = ');
var_dump($info);
var_dump('curl http code = ' . $info['http_code']);
if ($output === false) {
$err_num = curl_errno($soap_do);
$err_desc = curl_error($soap_do);
$httpcode = curl_getinfo($soap_do, CURLINFO_HTTP_CODE);
var_dump("—CURL FAIL RESPONSE:\ndati={$output}\nerr_num={$err_num}\nerr_desc={$err_desc}\nhttpcode={$httpcode}");
} else {
// Operation completed successfully
var_dump('success');
}
curl_close($soap_do);
return $output;
}
}
Il codice che vedi qui sopra lo puoi trovare anche in questo repository su GitHub.
Conclusione #
Questo codice è il frutto di diverse ore spese a capire come funziona il SdI. Un particolare ringraziamento va agli utenti del forum Italia. E' proprio grazie al loro contributo se sono riuscito a creare questo script 👏
Fonti: Accreditamento SDICoop: configurazione SSL su Apache e Installazione certificati canale SDICOOP
Se questo post ti è piaciuto e ti è stato utile ti invito ad iscriverti al mio canale Telegram. Se invece hai domande o vuoi lasciare un commento puoi contattarmi direttamente su Telegram o su Twitter. A presto!