SDICoop: configurazione PHP SoapClient / SoapServer (Apache) per invio e ricezione di test

A me continua a dare SSLException: protocol version.

Sogei mi ha risposto questo:

La invitiamo a verificare che richiamando il proprio endpoint di test da browser venga sempre richiesto un certificato. In caso contrario la configurazione SSL non è ben definita e le notifiche non possono esser consegnate.

Come dovrei fare a verificarlo?

volevo informare che se proviamo a xonnetterci tramite

ssh> openssl s_client -CAfile CA_Agenzia_delle_Entrate_all.pem -cert SDI-XXXXXXXXXXX-Client.pem -key client.key -connect 217.175.53.96:443

Il server di test ci risponde (ok)

Ma se proviamo ad utilizzare lo script php “403”

Questo oggetto php viene generato correttamente ?

SdiSoapClient {#219
+caCertFile: “/home/XXXXXXXXX/fatturapa.XXXXXX.it/storage/app/certificati/CA_Agenzia_delle_Entrate_all.pem”
+privateKeyFile: “/home/XXXXXXXXX/fatturapa.XXXXXXXXX.it/storage/app/certificati/client.key”
+clientCertFile: “/home/XXXXXXXXX/fatturapa.XXXXXXXXX.it/storage/app/certificati/SDI-XXXXXXXXX-Client.pem”
+proxyUrl: null
+proxyAuth: null
-lastRequestHeaders: null
-lastResponseHeaders: null
-lastRequestBody: null
-lastResponseBody: null
+“location”: “https://testservizi.fatturapa.it/ricevi_file
+“trace”: 1
+“_stream_context”: stream-context resource @266
options: array:1 [▼
“http” => array:2 [▼
“protocol_version” => 1.1
“header” => “Connection: close\r\n”
]
]
}
+“_soap_version”: 1
+“sdl”: SOAP SDL resource @269
}

Ho utilizzato il vostro script ma non riesco a farlo funzionare.

la funzione $sdiSoapClient->__getFunctions() mi restituisce correttamente il risultato ma se richiamo $sdiSoapClient->RiceviFile($fileSdIAccoglienza) mi restituisce sempre “Could not connect to host”
Ho provato più volte a ricreare i certificati e sono tutti .pem sembra tutto corretto e non so più che pesci prendere.

Help me please


Rettifico: errore mio che sbagliavo ad utilizzare la classe e quindi non inviava i certificati.
Ora sembra funzionare. Grazie Per il lavoro che fate

1 Mi Piace

Anche io ho lo stesso problema, continuo a ricevere l’errore “Could not connect to host” ma non ho idea se sia causato dai certificati o meno.

Ciao Stefano, anch’io sono bloccato a questo punto ma non so se si può risolvere con Serverplan. Tu hai fatto qualche progresso? Vedi anche qua: Test Interoperabilità - TrasmissioneFatture risulta in javax.net.ssl.SSLException: Received fatal alert: protocol_version

Ok, ho scoperto che è un problema con il certificato.

Togliendo l’opzione

"local_cert" => "path/mycert.cer"

E aggiungendo l’opzione

stream_context" => stream_context_create(
    array(
        'ssl' => array(
            'verify_peer'       => false,
        ),
    )
),

Sono riuscito almeno ad ottenere l’errore 403 - Forbidden.
Se riesco a farlo funzionare con il certificato vi faccio sapere.

Intanto vi metto il codice che ho usato per far apparire Forbidden anzichè Could not connect to host

$options = array(
    // "local_cert" => Storage::disk('local')->path('fattura_elettronica/cert/mycert.cer'),
    "location" => "https://servizi.fatturapa.it/ricevi_file",
    'connection_timeout'     => 10,
    'default_socket_timeout' => 10,
    "trace" => 1,
    "exceptions" => 1,
    "stream_context" => stream_context_create(
        array(
            'ssl' => array(
                'verify_peer'       => false,
            ),
        )
    ),
);

$service = new \SoapClient(Storage::disk('local')->path('fattura_elettronica/wsdl/SdIRiceviFile_v1.0.wsdl'), $options);
$service->__soapCall('RiceviFile', array());

Ok, risolto il problema.
Usando la classe SdiSoapClient e i certificati corretti sono riuscito a fare l’invio.
In questo post trovate le istruzioni:

Ciao andrea, scusa il dist :open_mouth:

Noi abbiamo usato lo stesso script ma a noi ritorna sempre 403, sai mica perchè ?

Sicuro sarà un problema di certificati sbagliati, prova a debuggare il client assicurandoti di usare trace = 1 nelle opzioni e stampando questo:

var_dump($sdiSoapClient->__getLastResponse());
var_dump($sdiSoapClient->__getLastResponseHeaders());
var_dump($sdiSoapClient->__getLastRequest());
var_dump($sdiSoapClient->__getLastRequestHeaders());

Se metto i certificati sbagliati infatti ricevo come errore Error 403: AuthenticationFailed

Ciao Mauro,
Niente, ora abbiamo messo su un vps in Cloud vergine e riproviamo.

Sperando di connetterci, potresti indicarci quali certificati usi su Apache per l’autenticazione test ?

ps.

Per client hai fatto qualche modifica su apache.conf ?

Attenzione perchè per il solo invio delle fatture non è necessario installare nulla su apache, i certificati di apache servono solo per la ricezione delle notifiche e delle fatture. Per esempio io gli invii di prova li sto facendo anche da localhost senza neanche usare ssl.

Comunque se leggi bene al link che ho postato sopra spiegano anche come generare i certificati da utilizzare per il client soap.

Niente ora abbiamo chiesto l’accreditamento anche per lo SDIFTP

Abbiamo configurato lo spazio in pochi minuti è gestito con un controller di laravel è molto semplice anziché SOAP

Sto seguendo anch’io l’esempio con il wrapper settando correttamente tutti i certificati ma ahimè le mie richieste vanno in timeout.
Ho notato che tra le curlopt una non mi viene riconosciuta.

Visto che sei riuscito a inviare una fattura correttamente, posso chiederti la configurazione del tuo server?
In particolare m’incuriosisce la versione di PHP e quella di cURL, da console:

php -v
curl -V

rispettivamente.

Grazie mille

php 7.0.8 e curl 7.55.1 ma dubito sia un problema di versione, piuttosto devi controllare di aver effettuato correttamente la chiamata soap.
Nel mio caso mi ricordo che mi andava in timeout quando il collegamento al wsdl non era corretto, nei logs di apache trovavo un sacco di tentativi di riconnessione perchè continuava a riprovare non trovando il wsdl finchè non andava in timeout.

Se non lo hai fatto scarica e metti il wsdl sul tuo server.

Prova anche a specificare la location dell’endpoint in quanto ho visto che ci mette molto meno a completare la richiesta.

php 5.6.21
cURL 7.29
in questa versione di cURL, l’opt CURLOPT_SSL_ENABLE_ALPN non è presente, quindi non viene applicata.

Purtroppo i file WSDL vengono caricati correttamente (da percorso locale).
I certificati sono settati come nell’esempio e sono raggiungibili e leggibili dal client SOAP.

EDIT: Ho notato che nei file WSDL la location definita per i servizi è un URL http (il che fa sicuramente fallire tutto poiché prova una connessione SSL sulla porta 80). Risulta quindi OBBLIGATORIO definire la location nell’array delle opzioni o comunque prima di fare la chiamata al metodo RiceviFile.

Ora, le mie richieste non vanno più in timeout ma restituiscono l’errore:

unable to load client cert: -8018 (SEC_ERROR_UNKNOWN_PKCS11_ERROR)

per entrambe le location:

https://servizi.fatturapa.it/ricevi_file (redirect sulla porta 443 dell’URL nei file WSDL)
https://testservizi.fatturapa.it/ricevi_file (URL indicato nell’esempio della classe wrapper)

ti conviene aggiornare php alla versione 7 ed usare CURLOPT_SSL_ENABLE_ALPN

A me non va… va in timeout con l’errore:

Fatal error : Uncaught Exception: [HTTP:100] Operation timed out after 30001 milliseconds with 0 bytes received in /var/www/vhosts/magazzinoperfetto.cloud/fe-test.magazzinoperfetto.cloud/SdiSoapClient.php:122 Stack trace: #0 [internal function]: SdiSoapClient->__doRequest(’<?xml version="…’, ‘https://testser…’, ‘http://www.fatt…’, 1, 0) #1 /var/www/vhosts/magazzinoperfetto.cloud/fe-test.magazzinoperfetto.cloud/test.php(39): SoapClient->__call(‘RiceviFile’, Array) #2 {main} thrown in /var/www/vhosts/magazzinoperfetto.cloud/fe-test.magazzinoperfetto.cloud/SdiSoapClient.php on line 122

Dopo una giornata di sclero, prove e ricerca sono riuscito a risolvere nel più stupido dei modi.
Non potendo aggiornare PHP e cURL dati dei vincoli di operatività con altri progetti nel server, ho attivato la CURLOPT_SSL_ENABLE_ALPN tramite il suo valore effettivo, ossia 226.
Vuoi per via del OS, vuoi per via di PHP, vuoi per via cURL ma la define del nome non c’era, l’opzione invece si, a quanto pare.

Ora, settati correttamente i certificati, tramite il SdiSoapClient ricevo l’effettiva presa in carico del SdI (una ricevuta senza errori e con un identificativo SDI), adesso ci sarà da ridere nella gestione delle notifiche e ricezione fatture dato che a quanto pare i server sono down.

Ho notato che usi un metodo deprecato della classe SoapClient:

Puoi effettuare la chiamata in altri due modi:

__soapCall( 'RiceviFile' , Array args, [Array opts]);
RiceviFile(Array args);

Nel mio caso la mia connessione andava in timeout a causa del fatto che non specificato esplicitamente la location al client, cosa che puoi fare passando un’array che includa l’opzione:

‘location’ => ‘https://testservizi.fatturapa.it/ricevi_file

in fase di creazione del client.
Questo perché nel file WSDL che carica il client sono specificati degli endpoint NON https://.

Altrimenti, potrebbe andare in timeout anche se non carica i certificati corretti, ma in tal caso è più probabile che ti restituisca un altro tipo di errore.