Ver Mensaje Individual
  #11  
Antiguo 10-04-2025
Avatar de morta71
morta71 morta71 is offline
Miembro
 
Registrado: may 2006
Ubicación: Girona - España
Posts: 33
Reputación: 0
morta71 Va por buen camino
Cita:
Empezado por Jariverom Ver Mensaje
Estoy en ese mismo punto, pero he conseguido extraer mas sobre el error y me especifica que falta la Cabecera en el XML y en la variable donde tengo el XML si está ese nodo.
Yo lo tengo desarrollado en PHP (Symfony) y a grandes rasgos esta es mi implementación:

Tengo las clases según las especificaciones del WSDL de la AEAT (CabeceraType, Destinatarios, DatosPresentacionType, etc...), pero se pueden obviar dichas clases y en lugar de pasar objetos al cliente SOAP se pueden pasar los datos en un array asociativo con la misma estructura, o el XML directo.

Para realizar los envíos SOAP tengo una clase SoapVerifactu.class:

Código PHP:
class SoapVerifactu extends \SoapClient
{
    public function 
__construct(
        
CertificadoService $certificado,
        
#[Autowire('%sif_verifactu_wsdl%')] string $wdsl,
        #[Autowire('%sif_verifactu_endpoint%')] string $location,
        
array $options = [],
        
bool $ssl_verifypeer true)
    {
        if (!
$certificado->valid()) {
            throw new \
RuntimeException('Certificado no válido. Compruebe que el certificado digital sea válido.');
        }

        
$options += [
            
'trace' => true,
            
'cache_wsdl' => WSDL_CACHE_NONE,
            
'classmap' => [       // Omitir si se prefiere no mapear con clases propias
                
'CabeceraConsultaSf' => CabeceraConsulta::class,
                
'CabeceraType' => Cabecera::class,
                
'Destinatarios' => Destinatarios::class,
                
'DatosPresentacionType' => DatosPresentacionType::class,
                
'DatosPresentacion2Type' => DatosPresentacion2Type::class,
                
'DesgloseRectificacionType' => DesgloseRectificacionType::class,
                
'DesgloseType' => DesgloseType::class,
                
'DetalleType' => DetalleType::class,
                
'EncadenamientoFacturaAnteriorType' => EncadenamientoFacturaAnteriorType::class,
                
'EstadoRegFactuType' => EstadoRegFactuType::class,
                
'FacturasRectificadas' => FacturasRectificadas::class,
                
'FacturasSustituidas' => FacturasSustituidas::class,
                
'FiltroConsulta' => FiltroConsulta::class,
                
'IDFacturaARType' => IDFacturaARType::class,
                
'IDFacturaExpedidaType' => IDFacturaExpedidaType::class,
                
'IDOtroType' => IDOtroType::class,
                
'ObligadoEmisionConsultaType' => ObligadoEmisionConsultaType::class,
                
'OperacionType' => OperacionType::class,
                
'PeriodoImputacion' => PeriodoImputacionType::class,
                
'PersonaFisicaJuridicaESType' => PersonaFisicaJuridicaESType::class,
                
'PersonaFisicaJuridicaType' => PersonaFisicaJuridicaType::class,
                
'RegistroDuplicadoType' => RegistroDuplicadoType::class,
                
'RegistroRespuestaConsultaRegFacturacionType' => RegistroRespuestaConsultaRegFacturacionType::class,
                
'RemisionVoluntaria' => RemisionVoluntaria::class,
                
'RespuestaBaseType' => RespuestaRegFactuSistemaFacturacion::class,
                
'RespuestaConsultaFactuSistemaFacturacionType' => RespuestaConsultaFactuSistemaFacturacionType::class,
                
'RespuestaDatosRegistroFacturacionType' => RespuestaDatosRegistroFacturacionType::class,
                
'RespuestaExpedidaType' => RespuestaExpedidaType::class,
            ],
            
'local_cert' => $certificado->pem(),   // path al certificado PEM
            
'passphrase' => $certificado->key(),   // pin/clave
            
'location' => $location,
            
'stream_context' => [
                
'http' => [
                    
'user_agent' => 'PHPSoapClient',
                ],
                
'ssl' => [
                    
'ciphers' => 'DEFAULT@SECLEVEL=1',
                ],
            ],
        ];

        
$options['stream_context'] = $this->stream_context($options['stream_context'], $ssl_verifypeer);

        
parent::__construct($wdsl$options);
    }

    public function 
consultaFacturacion(array $parametros): mixed
    
{
        return 
$this->__soapCall('ConsultaFactuSistemaFacturacion', [$parametros]);
    }

    public function 
registroFacturacion(array $parametros): mixed
    
{
        
// Para envío de string XML
        // return $this->__doRequest($xml, $this->location, '', 1);

        
return $this->__soapCall('RegFactuSistemaFacturacion', [$parametros]);
    }

    protected function 
stream_context($options = [], $ssl_verifypeer true)
    {
        switch (
gettype($options)) {
            case 
'array':
                
$context stream_context_create($options);
                break;
            case 
'resource':
                
$context $options;
        }

        if (!
$ssl_verifypeer) {
            
stream_context_set_option($context, [
                
'ssl' => [
                    
'verify_peer' => false,
                    
'verify_peer_name' => false,
                    
'allow_self_signed' => true,
                ],
            ]);
        }

        return 
$context;
    }

La llamada al servicio SOAP la realizo de la siguiente manera:

Código PHP:
public function __construct(
    ...,
    private 
SoapVerifactu $soap,
) {
}
 ...
 
public function 
execute() {
    ....
    
    
/** @var RespuestaRegFactuSistemaFacturacion $respuesta */
    
$respuesta $this->soap->registroFacturacion([
        
'Cabecera' => $cabecera,        // objeto CabeceraType o un array asociativo
        
'RegistroFactura' => $registrosFactura,    // objeto con los registros de factura o array asociativo
    
]);
    ...

La respuesta es un objeto RespuestaRegFactuSistemaFacturacion según se describe en el WSDL/XSD de la AEAT.

Hasta ahora he realizado envíos y consultas sin problemas.

Espero que te sirva de ayuda.
Responder Con Cita