SDICOOP (canale web services) - Rinnovo Certificati

io, per la pare inoltro al SDI, Ho generato il pfx a partire dalla chiave privata che avevo già e del nuovo certificato che ho ricevuto … e adesso funziona regolarmente

Grazie Mille per le risposte,

mi sa che per me non è attualmente una strada percorribile perchè pare che il client SOAP di php non supporti l’invio in pfx ma non capisco perchè non dovrebbero andare bene i nuovi certificati con la “vecchia” chiave inviati separatamente (funzionante fino a ieri) piuttosto che tutto in un unico file pfx combinato :frowning:

Qualcuno ha affrontato il problema in php e riesce a darmi un feedback specifico?

Questo è il client che uso io per inviare

<?php 
namespace App\Utils;


class MySoapClient extends \SoapClient
{
    const USER_AGENT = 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)';
    const REGEX_ENV  = '/<soap[\s\S]*nvelope>/i';
    const REGEX_XOP  = '/<xop:include[\s\S]*cid:%s@[\s\S]*?<\/xop:Include>/i';
    const REGEX_CID  = '/cid:([0-9a-zA-Z-]+)@/i';
    const REGEX_CON  = '/Content-ID:[\s\S].+?%s[\s\S].+?>([\s\S]*?)--MIMEBoundary/i';
    
    /**
     * Path al certificato della CA
     * @var string
     */
    public $caCertFile;
    
    /**
     * Path alla chiave privata
     * @var string
     */
    public $privateKeyFile;
    
    /**
     * Path al certificato client
     * @var string
     */
    public $clientCertFile;
    
    /**
     * Url del proxy (es. host:port)
     * @var string
     */
    public $proxyUrl;
    
    /**
     * Autenticazione del proxy (es. username:password)
     * @var string
     */
    public $proxyAuth;
    
    /**
     * Headers dell'ultima richiesta
     * @var array
     */
    private $lastRequestHeaders;
    
    /**
     * Headers dell'ultima risposta
     * @var array
     */
    private $lastResponseHeaders;
    
    /**
     * Body dell'ultima richiesta
     * @var string
     */
    private $lastRequestBody;
    
    /**
     * Body dell'ultima risposta
     * @var string
     */
    private $lastResponseBody;
    
    
    /**
     * @inheritdoc
     */
    public function __doRequest($request, $location, $action, $version, $one_way = null)
    {
        // reset
        $this->lastResponseBody = '';
        $this->lastResponseHeaders = array();

        $this->lastRequestHeaders = array(
            'Content-type: text/xml;charset="utf-8"',
            'Accept: text/xml',
            'Cache-Control: no-cache',
            'Pragma: no-cache',
            'SOAPAction: '.$action,
            'Content-length: ' . strlen($request),
        );
        $this->lastRequestBody = $request;
        
        $ch = curl_init();
        
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_SSL_ENABLE_ALPN, false);
        curl_setopt($ch, CURLOPT_SSLKEY, $this->privateKeyFile);
        curl_setopt($ch, CURLOPT_SSLCERT, $this->clientCertFile);
        curl_setopt($ch, CURLOPT_CAINFO, $this->caCertFile);

        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_USERAGENT, self::USER_AGENT);
        curl_setopt($ch, CURLOPT_URL, $location);
        curl_setopt($ch, CURLOPT_POST , true);
        
        curl_setopt($ch, CURLOPT_HTTPHEADER, $this->lastRequestHeaders);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $this->lastRequestBody);
        
        curl_setopt($ch, CURLOPT_HEADERFUNCTION, array(&$this, 'handleHeaderLine'));
        
        if( !empty($this->proxyUrl) ){
            curl_setopt($ch, CURLOPT_PROXY, $this->proxyUrl);
            if( !empty($this->proxyAuth) ){
                curl_setopt($ch, CURLOPT_PROXYUSERPWD, $this->proxyAuth);
            }
        }
        
        $this->lastResponseBody = curl_exec($ch);
        
        // $time = time();
        // file_put_contents('F:\srv-sdi\var\request\\'.$time .'-raw.txt', $this->lastResponseBody);

        if ( false === $this->lastResponseBody ) {
            $err_num  = curl_errno($ch);
            $err_desc = curl_error($ch);
            $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            
            curl_close($ch);
            
            throw new \Exception('[HTTP:'. $httpcode .'] ' . $err_desc, $err_num);
        }
        
        curl_close($ch);
        
        $this->lastResponseBody = $this->__processResponse($this->lastResponseBody);
        
        // file_put_contents('F:\srv-sdi\var\request\\'.$time .'-parsed.txt', $this->lastResponseBody);

        return $this->lastResponseBody;
    }
    
    /**
     * Processa la risposta per supportare il formato MTOM
     * NB teniamo il metodo pubblico per favorire i test unitari
     * @param string $response
     * @throws \Exception
     * @return string
     */
    public function __processResponse($response){
        
        $xml_response = null;
        
        // recupera la risposta xml isolandola da quella mtom
        preg_match(self::REGEX_ENV, $response, $xml_response);
        
        if ( !is_array($xml_response) || count($xml_response) <= 0 ) {
            throw new \Exception('No XML has been found.');
        }
        // prendiamo il primo elemento dell'array
        $xml_response = reset($xml_response);

        // recuperiamo i tag xop
        $xop_elements = null;
        preg_match_all(sprintf(self::REGEX_XOP, '.*'), $response, $xop_elements);
        // prendiamo il primo elemento dell'array
        $xop_elements = reset($xop_elements);
        
        if ( is_array($xop_elements) && count($xop_elements) > 0 ) {
            foreach ($xop_elements as $xop_element) {
                
                // recuperiamo il cid
                $matches = null;
                preg_match(self::REGEX_CID, $xop_element, $matches);
                
                if( isset($matches[1]) ){
                    $cid = $matches[1];
                    
                    // recuperiamo il contenuto associato al cid
                    $matches = null;
                    preg_match(sprintf(self::REGEX_CON, $cid), $response, $matches);
                    
                    if( isset($matches[1]) ){
                        $binary = trim($matches[1]);
                        $binary = base64_encode($binary);
                        
                        // sostituiamo il tag xop:Include con base64_encode(binary)
                        // nota: SoapClient fa automaticamente il base64_decode(binary)
                        $old_xml_response = $xml_response;
                        $xml_response = preg_replace(sprintf(self::REGEX_XOP, $cid), $binary, $xml_response);
                        if( $old_xml_response === $xml_response ){
                            throw new \Exception('xop replace failed');
                        }
                    } else {
                        throw new \Exception('binary not found.');
                    }
                } else {
                    throw new \Exception('cid not found.');
                }
            }
        }
        
        return $xml_response;
    }
    
    /**
     * @inheritdoc
     */
    public function __getLastRequestHeaders(){
        return implode("\n", $this->lastRequestHeaders);
    }
    
    /**
     * @inheritdoc
     */
    public function __getLastResponseHeaders(){
        return implode("\n", $this->lastResponseHeaders);
    }
    
    /**
     * @inheritdoc
     */
    public function __getLastRequest(){
        return $this->lastRequestBody;
    }
    
    /**
     * @inheritdoc
     */
    public function __getLastResponse(){
        return $this->lastResponseBody;
    }
    
    /**
     * Handle singolo header richiesta cURL
     * return integer
     */
    public function handleHeaderLine($curl, $header_line){
        $this->lastResponseHeaders[] = $header_line;
        return strlen($header_line);
    }
}

E’ la stessa classe che uso io quindi anche tu non utilizzi il pfx ma avvalori le tre variabili sotto col la CA, il cert client e la chiave giusto?

Ciao a tutti. Finora funzionava tutto bene ma da circa le 14.30 abbiamo problemi nell’invio di fatture. Qualcun altro ha lo stesso problema?

è una classe che ho fatto io e condiviso su questo forum…
Si non uso il pfx

Idem. Tutto rotto. Aspettiamo… e poi recupereremo le notifiche…

un saluto a tutti
anche noi dalle 14:40 circa non riusciamo più ad inviare:
"Nessun endpoint in ascolto su https://servizi.fatturapa.it/ricevi_file in grado di accettare il messaggio"

confermo, ultima fattura inviata alle 14.29, poi sono spariti :smiley:

Confermo anch’io… attualmente ogni richiesta fallische con un timeout (dopo 30 secondi di attesa)

Confermo, Connection timed out after 30001 milliseconds

Anche da noi stesso problema, connection timeout. Noi tra l’altro aspettiamo 180s

1 Mi Piace

Cavolo, stavo sostituendo proprio oggi i certificati… pensavo era un mio problema ed invece…
Da circa un’ora mi da il seguente errore:
2021/06/01 16:03:39 [error] 17915#17915: *1817 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught Exception: [HTTP:100] Operation timed out after 30000 milliseconds with 0 bytes received in send-invoice-to-sdi/sdiSoapClient.php:122

Parrebbe intervento di manutenzione che dovrebbe terminare entro le 17.
Nel frattempo tra i sistemi di notifica funzionano solo quelli PA (ci sono arrivate solo diverse notifiche di accettato da parte della PA), mentre non ci sono arrivate fatture ricevute.
No panic. C’è l’Italia ferma, nessuno di noi è l’unico a subire.
Domani è festa, c’è tutto il tempo per recuperare eventualmente… :smiley:

Ciao come hai avuto questa informazione sull’intervento di manutenzione? (Che ancora sembra in atto in realtà).
Sarebbe bello se potessero avvisarci per tempo in questi casi, o quanto meno una status page che mostri lo stato di salute dei loro sistemi.

Antonino… e come ho avuto l’informazione… Ho chiamato incazzato!
E scordiamoci “l’avviso per tempo”. Ormai dopo 2 anni e mezzo di fattura elettronica credo sia chiaro che le giornate come questa siano prive di preavviso.
E siano prive anche di tempistiche precise: sono le 17.32 e siamo già a 3 ore di vuoto completo.

5 Mi Piace

Speravo esistesse un modo a me sconosciuto per avere le comunicazioni per tempo :unamused:

Ciao a Tutti, Anche io ho lo stesso problema.
da dopo le 12:30 https://servizi.fatturapa.it/ricevi_file non risponde.
Sono rimasta molto tempo in attesa al telefono nel tentativo di parlare con un operatore ma non ho avuto successo.
Qualcuno ho visto invece ha ricevuto informazioni su quando è previsto il ripristino, ma che numero avete usato? io ho usato il 800 299 940
Grazie infinite

Ciao,
anche noi stesso problema.
Ottimo lavoro ragazzi.
Grazie mille.
Saluti e buon lavoro.

Sogniamo il giorno in cui avremo una pagina per verificare lo stato del servizio e una mail che ci avvisi di un’eventuale manutenzione prima che avvenga. :slightly_smiling_face:

“…ma non è questo il giorno!”

1 Mi Piace