Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Internet
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1301  
Antiguo 15-02-2024
Sistel Sistel is offline
Miembro
 
Registrado: nov 2019
Ubicación: Bilbao
Posts: 372
Poder: 5
Sistel Va por buen camino
Y aclararon que si se opta por utilizar Verifactu ya no hay obligación de firma de la factura ni de llevar el registro de eventos.
Por supuesto, sí se obliga en Verifactu a que la factura lleve un hash.
Responder Con Cita
  #1302  
Antiguo 15-02-2024
ermendalenda ermendalenda is offline
Miembro
 
Registrado: ago 2021
Posts: 867
Poder: 3
ermendalenda Va por buen camino
Gracias a todos los por la información
me han comentado varias cosas sobre los que van a hacer Veri*Factu(Envio):
*La Huella y el encadenamiento es necesaria, alguien ha comentado que para verifactu no lo es, pero debe estar equivocado, me han enseñado el esquema.
*La huella SHA256 en Hexadecimal y MAYÚSCULAS
*Se deben subsanar los errores (de los registros que te devuelvan con error) y volver a remitir los registros subsanados(Ya diran como, supongo que como incidencia....)
Responder Con Cita
  #1303  
Antiguo 15-02-2024
sglorka sglorka is online now
Miembro
 
Registrado: mar 2017
Posts: 93
Poder: 8
sglorka Va por buen camino
Resumen del Seminario

Hola a todos, os pongo las ideas que he sacado del seminario de ayer por si pueden ser de interés para alguno. Espero no haber cometido ningún error.

1.- Recomiendan el uso del sistema VeriFactu como opción segura para ofrecer al cliente. La opción del requerimiento tiene implicaciones que son de difícil cumplimiento y te cargan con una responsabilidad, la conservación, que es complicada de asegurar para una instalación desatendida.

2.- La imposibilidad de remitir temporalmente los registros de facturación por problemas técnicos puntuales la entienden y se abren a que utilicemos el campo Incidencia (S) de la cabecera del mensaje para notificar dicha situación. Incluso hablaron de casos en los que sólo hay Internet a ciertas horas del día y que eso es plausible.

3.- Han dejado bien claro que los sistemas VeriFactu están excluidos de la conservación, firma electrónica, accesibilidad y eventos de los registros de facturación. El evento de entrada / salida de Verifactu sólo atañe en el caso de que, NO estando en VeriFactu, (debes tener eventos) quisieras cambiarlo y entrar en Modo Verifactu, entonces deberías generar ambos eventos de salida y entrada. Ya en el nuevo modo, desaparecerían.

El modo Verifactu se resume en, envío automático, consecutivo, encadenamiento de registros y generación de huellas para cada registro de facturación. Ya para factura impresa o electrónica, adición de Qr.
Hablaron sobre el control de flujo (n,t). En principio lo van a cambiar, ya que, el número máximo de envío de registros en un mismo mensaje agrupado ya está limitado, son 1000. Por lo tanto, el parámetro “n” carece de sentido. Sí, van a utilizar el parámetro “t” en segundos.

4.- Aunque han dicho que van a mantener los servicios diferenciados para la remisión de registros a través de VeriFactu y a través de requerimiento, tiene la idea de que, dichos registros, contengan la misma información, por lo que se avecina otro cambio en la estructura del registro de alta y de anulación

5.- Piensan unificar en el mismo mensaje de envío, registros de alta y de anulación.

6.- La huella hash ya no será del nodo registro de facturación sino que se construirá con ciertos campos del xml que ya indicarán. Y lo más importante es que un error en esta huella no será considerado como motivo de rechazo sino como aceptada con errores.

7.- Dejaron entrever, que la idea final es que sólo exista un método de envío de registros de facturación a la aeat, por lo que al final, tenderemos a un híbrido entre el SII y VeriFactu como sistema de envío. Por ello, la idea de adherirse al SII para no cumplir con VeriFactu deberíamos desecharla.

8.- Los certificados electrónicos de terceros serán admisibles para remitir los registros de facturación de un obligado tributario, idéntico al SII.
Responder Con Cita
  #1304  
Antiguo 15-02-2024
pablog2k pablog2k is offline
Miembro
 
Registrado: may 2017
Posts: 85
Poder: 7
pablog2k Va por buen camino
gran resumen, de acuerdo con lo dicho, gracias compañero
Responder Con Cita
  #1305  
Antiguo 15-02-2024
keno_71 keno_71 is offline
Miembro
 
Registrado: feb 2008
Posts: 27
Poder: 0
keno_71 Va por buen camino
Buenos días, gracias por el resumen a todos. Entonces si el sistema es Verifactu tienes que utilizar un certificado para enviar pero no para firmar la factura. El certificado tiene que estar instalado en todos los ordenadores que envíen.
Responder Con Cita
  #1306  
Antiguo 15-02-2024
ermendalenda ermendalenda is offline
Miembro
 
Registrado: ago 2021
Posts: 867
Poder: 3
ermendalenda Va por buen camino
Sigo pensabdo que van a mezclar verifactu con la factura electronica
Responder Con Cita
  #1307  
Antiguo 15-02-2024
ermendalenda ermendalenda is offline
Miembro
 
Registrado: ago 2021
Posts: 867
Poder: 3
ermendalenda Va por buen camino
Sigo pensabdo que en el xml van a mezclar verifactu con la factura electronica y Tarde o temprano meterán las líneas de los conceptos facturados.
Responder Con Cita
  #1308  
Antiguo 16-02-2024
CarlosMz CarlosMz is offline
Miembro
 
Registrado: jul 2020
Posts: 23
Poder: 0
CarlosMz Va por buen camino
Cita:
Empezado por sglorka Ver Mensaje
Hola a todos, os pongo las ideas que he sacado del seminario de ayer por si pueden ser de interés para alguno. Espero no haber cometido ningún error.

1.- Recomiendan el uso del sistema VeriFactu como opción segura para ofrecer al cliente. La opción del requerimiento tiene implicaciones que son de difícil cumplimiento y te cargan con una responsabilidad, la conservación, que es complicada de asegurar para una instalación desatendida.

2.- La imposibilidad de remitir temporalmente los registros de facturación por problemas técnicos puntuales la entienden y se abren a que utilicemos el campo Incidencia (S) de la cabecera del mensaje para notificar dicha situación. Incluso hablaron de casos en los que sólo hay Internet a ciertas horas del día y que eso es plausible.

3.- Han dejado bien claro que los sistemas VeriFactu están excluidos de la conservación, firma electrónica, accesibilidad y eventos de los registros de facturación. El evento de entrada / salida de Verifactu sólo atañe en el caso de que, NO estando en VeriFactu, (debes tener eventos) quisieras cambiarlo y entrar en Modo Verifactu, entonces deberías generar ambos eventos de salida y entrada. Ya en el nuevo modo, desaparecerían.

El modo Verifactu se resume en, envío automático, consecutivo, encadenamiento de registros y generación de huellas para cada registro de facturación. Ya para factura impresa o electrónica, adición de Qr.
Hablaron sobre el control de flujo (n,t). En principio lo van a cambiar, ya que, el número máximo de envío de registros en un mismo mensaje agrupado ya está limitado, son 1000. Por lo tanto, el parámetro “n” carece de sentido. Sí, van a utilizar el parámetro “t” en segundos.

4.- Aunque han dicho que van a mantener los servicios diferenciados para la remisión de registros a través de VeriFactu y a través de requerimiento, tiene la idea de que, dichos registros, contengan la misma información, por lo que se avecina otro cambio en la estructura del registro de alta y de anulación

5.- Piensan unificar en el mismo mensaje de envío, registros de alta y de anulación.

6.- La huella hash ya no será del nodo registro de facturación sino que se construirá con ciertos campos del xml que ya indicarán. Y lo más importante es que un error en esta huella no será considerado como motivo de rechazo sino como aceptada con errores.

7.- Dejaron entrever, que la idea final es que sólo exista un método de envío de registros de facturación a la aeat, por lo que al final, tenderemos a un híbrido entre el SII y VeriFactu como sistema de envío. Por ello, la idea de adherirse al SII para no cumplir con VeriFactu deberíamos desecharla.

8.- Los certificados electrónicos de terceros serán admisibles para remitir los registros de facturación de un obligado tributario, idéntico al SII.
Excelente resumen, muchas gracias.

Si el sistema es SOLO verifactu, no se aplica el registro de eventos en ningún caso ? Ni entrada al sistema, salida,... ?

Si el Hash se calculará sobre ciertos campos no tendremos que serializar primero el XML para obtener el nodo, entiendo ?
Responder Con Cita
  #1309  
Antiguo 16-02-2024
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Algunas de las diapositivas que considero más importantes en la presentación.
Espero que aclaren las cosas junto con la explicaciones que habéis ido comentando...












Diferencias entre VERI*FACTU y no VERI*FACTU:


__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.

Última edición por Neftali [Germán.Estévez] fecha: 16-02-2024 a las 10:04:11.
Responder Con Cita
  #1310  
Antiguo 16-02-2024
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Y aquí adjunto algunas que son más técnicas (y porque en el mensaje anterior ya no me va a dejar añadir más...












__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.

Última edición por Neftali [Germán.Estévez] fecha: 16-02-2024 a las 10:07:23.
Responder Con Cita
  #1311  
Antiguo 16-02-2024
sglorka sglorka is online now
Miembro
 
Registrado: mar 2017
Posts: 93
Poder: 8
sglorka Va por buen camino
Cita:
Empezado por CarlosMz Ver Mensaje
Excelente resumen, muchas gracias.

Si el sistema es SOLO verifactu, no se aplica el registro de eventos en ningún caso ? Ni entrada al sistema, salida,... ?

Si el Hash se calculará sobre ciertos campos no tendremos que serializar primero el XML para obtener el nodo, entiendo ?
No hay eventos en modo VeriFactu, de ningún tipo.
Como el hash se va a calcular sobre campos concretos, lo podrás obtener antes de crear el xml por lo tanto, no tienes que obtenerlo del xml generado.
Responder Con Cita
  #1312  
Antiguo 16-02-2024
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por Sistel Ver Mensaje
También aclararon que si se usa la opción Verifactu (opción que recomendaron encarecidamente), para el envío de las facturas se podrá emplear no sólo el certificado digital del obligado tributario sino también el de un tercero.
En este caso, el tercero deberá ser Colaborador Social y tener un documento por el que el obligado tributario le autoriza.
El modelo es éste

Añadido el documento al FTP del club y añadido enlace al mensaje #1 (recopilatorio).
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #1313  
Antiguo 16-02-2024
CarlosMz CarlosMz is offline
Miembro
 
Registrado: jul 2020
Posts: 23
Poder: 0
CarlosMz Va por buen camino
Cita:
Empezado por sglorka Ver Mensaje
No hay eventos en modo VeriFactu, de ningún tipo.
Como el hash se va a calcular sobre campos concretos, lo podrás obtener antes de crear el xml por lo tanto, no tienes que obtenerlo del xml generado.
Se simplifica bastante, muchas gracias
Responder Con Cita
  #1314  
Antiguo 16-02-2024
Avatar de ramherfer
ramherfer ramherfer is offline
Miembro
 
Registrado: may 2013
Ubicación: Valencia
Posts: 51
Poder: 11
ramherfer Va por buen camino
Una pregunta a ver si alguien me puede aclarar una duda que tengo desde hace tiempo.
¿Se deben generar los xml de cada factura por separado?
¿Luego de generados se genera el soap para enviar?
Gracias anticipadas.
__________________
Se humilde para admitir tus errores, inteligente para aprender de ellos y maduro para corregirlos.
Responder Con Cita
  #1315  
Antiguo 16-02-2024
ermendalenda ermendalenda is offline
Miembro
 
Registrado: ago 2021
Posts: 867
Poder: 3
ermendalenda Va por buen camino
Cita:
Empezado por ramherfer Ver Mensaje
Una pregunta a ver si alguien me puede aclarar una duda que tengo desde hace tiempo.
¿Se deben generar los xml de cada factura por separado?
¿Luego de generados se genera el soap para enviar?
Gracias anticipadas.
En el supuesto de acogerte a envio inmediato: Comp no tienes que conservarlo puedes hacerlo como quieras, pero debes tener en cuenta que te pueden contestar en el resp del soap al enviar que el próximo envío el número de xmls por ejemplo sea 10 registros encapsulados en el mismo soap o 300segunfos de espera. Entonces lo recomendable es que generes el xml por un lado y encapsules en el soap al enviar.
Responder Con Cita
  #1316  
Antiguo 16-02-2024
Avatar de ramherfer
ramherfer ramherfer is offline
Miembro
 
Registrado: may 2013
Ubicación: Valencia
Posts: 51
Poder: 11
ramherfer Va por buen camino
Cita:
Empezado por ermendalenda Ver Mensaje
En el supuesto de acogerte a envio inmediato: Comp no tienes que conservarlo puedes hacerlo como quieras, pero debes tener en cuenta que te pueden contestar en el resp del soap al enviar que el próximo envío el número de xmls por ejemplo sea 10 registros encapsulados en el mismo soap o 300segunfos de espera. Entonces lo recomendable es que generes el xml por un lado y encapsules en el soap al enviar.
Claro, ahora comentan que la huella va calculada de datos especificos de la factura (mucho más sencillo) y antes era del nodo <RegistroFacturacion>, que esto no facilitaba las cosas, de ahí mi duda.

Vale perfecto tiene lógica, mientras encapsulas calculas la huella desde los datos de factura, no de ningún nodo. mil gracias como siempre @ermendalenda.

A ver si se aclara esta gente de una maldita vez.
__________________
Se humilde para admitir tus errores, inteligente para aprender de ellos y maduro para corregirlos.
Responder Con Cita
  #1317  
Antiguo 16-02-2024
ermendalenda ermendalenda is offline
Miembro
 
Registrado: ago 2021
Posts: 867
Poder: 3
ermendalenda Va por buen camino
Cita:
Empezado por ramherfer Ver Mensaje
Claro, ahora comentan que la huella va calculada de datos especificos de la factura (mucho más sencillo) y antes era del nodo <RegistroFacturacion>, que esto no facilitaba las cosas, de ahí mi duda.

Vale perfecto tiene lógica, mientras encapsulas calculas la huella desde los datos de factura, no de ningún nodo. mil gracias como siempre @ermendalenda.

A ver si se aclara esta gente de una maldita vez.
A mi me da un poco igual de donde se calcule, como genero el xml a pelo puedo elegir los nodos que quiera para calcular el hash antes de grabar el xml.
Supongo que ya cada uno tendrá sus complicaciones.
Lo que si tienes que calcular elhash antes de generar el qr de la factura, eso está claro, la explicacion de calcularla mientras encapsulas el soap antes de encapsular no es muy correcta, ya que en el qr, casi seguro va a ir parte del hash calculado, al igual que ticketbai con la firma, es la única forma que tiene para garantizar que no cambies algo entre la emisión y el envío.

Última edición por ermendalenda fecha: 16-02-2024 a las 13:04:11.
Responder Con Cita
  #1318  
Antiguo 16-02-2024
Avatar de ramherfer
ramherfer ramherfer is offline
Miembro
 
Registrado: may 2013
Ubicación: Valencia
Posts: 51
Poder: 11
ramherfer Va por buen camino
Cita:
Empezado por ermendalenda Ver Mensaje
A mi me da un poco igual de donde se calcule, como genero el xml a pelo puedo elegir los nodos que quiera para calcular el hash antes de grabar el xml.
Supongo que ya cada uno tendrá sus complicaciones.
Lo que si tienes que calcular elhash antes de generar el qr de la factura, eso está claro, la explicacion de calcularla mientras encapsulas el soap antes de encapsular no es muy correcta, ya que en el qr, casi seguro va a ir parte del hash calculado, al igual que ticketbai con la firma, es la única forma que tiene para garantizar que no cambies algo entre la emisión y el envío.
Aqui ya me he perdido.... el hash antes de generar el qr de la factura

Si que me gustaría ver un ejemplo de como encapsulas uno o varios xml generados con anterioridad. Me sería de mucha ayuda
__________________
Se humilde para admitir tus errores, inteligente para aprender de ellos y maduro para corregirlos.
Responder Con Cita
  #1319  
Antiguo 17-02-2024
ermendalenda ermendalenda is offline
Miembro
 
Registrado: ago 2021
Posts: 867
Poder: 3
ermendalenda Va por buen camino
Cita:
Empezado por ramherfer Ver Mensaje
Aqui ya me he perdido.... el hash antes de generar el qr de la factura

Si que me gustaría ver un ejemplo de como encapsulas uno o varios xml generados con anterioridad. Me sería de mucha ayuda
Yo te lo pongo pero no sé si te vas a liar más, ya que yo trabajo en Vb6 para generar el xml y despuñess las firmas y encapsulamientos soaps lo hago en php con llamadas desde curl.
En Delphi hay otras formas que los compañeros del foro seguro que te pueden guiar.

Mira el código para generar el XML (A pelo) es de esta forma:
Código:
close #92
Open "C:\xmls\" & nombre_fichero & ".xml" For Output  As #92
 Print #92, "<?xml version=" & Chr(34) & "1.0" & Chr(34) & " encoding=" & Chr(34) & "UTF-8" & Chr(34) & "?>"
               Print #92, "<?xml version=" & Chr(34) & "1.0" & Chr(34) & " encoding=" & Chr(34) & "UTF-8" & Chr(34) & "?>"
                If es_anulacion Then
                    
                    Print #92, "<sum:BajaFactuSistemaFacturacion xmlns:sum=" & Chr(34) & "https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd" & Chr(34) & " xmlns:sum1=" & Chr(34) & "https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd" & Chr(34) & ">"
                Else
                    Print #92, "<sum:AltaFactuSistemaFacturacion xmlns:sum=" & Chr(34) & "https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroLR.xsd" & Chr(34) & " xmlns:sum1=" & Chr(34) & "https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/tike/cont/ws/SuministroInformacion.xsd" & Chr(34) & ">"
                End If
                Print #92, "<sum1:Cabecera>"
                Print #92, "<sum1:IDVersion>" & version_vfactu & "</sum1:IDVersion>"
 Print #92, "<sum1:ObligadoEmision>"
                Print #92, "<sum1:NombreRazon>" & TEXT_TO_UTF8(nombre_empresa) & "</sum1:NombreRazon>"
                Print #92, "<sum1:NIF>" & nif & "</sum1:NIF>"
                Print #92, "</sum1:ObligadoEmision>"
               select case tipo 

                    "anulacion"
                        Print #92, "<sum1:TipoRegistroAEAT>T3</sum1:TipoRegistroAEAT>"
                    
                     "sustitutiva"
                            Print #92, "<sum1:TipoRegistroAEAT>T1</sum1:TipoRegistroAEAT>"
                     "normal"
                            Print #92, "<sum1:TipoRegistroAEAT>T0</sum1:TipoRegistroAEAT>"
               end select
***Y ahora lo que voy a escribir lo voy guardando en la variable datohash para calcular el hash cuando tenga en la variable lo que necesite
datoxml = "<sum:RegistroFacturacion>"
                datohash = datoxml
                If es_anulacion = False Then
    
                    Print #92, "<sum:RegistroAltaFacturas>" & datoxml;
                Else
                    Print #92, "<sum:RegistroAnulacionFacturas>" & datoxml;
                End If
                
                 datoxml = "<sum1:IDFactura>"
                datohash = datohash & datoxml
                Print #92, datoxml;
                .......
****AL FINAL CALCULO EL HASH USANDO LAS API DE WINDOWS****
***  CryptCreateHash, ¿¿¿CryptAcquireContext, etc... de la libreria  "advapi32.dll"*****

                huella = UCase(CreateHashString(datohash, CALG_SHA_256))
                    
*** Inserto el hash en el xml y el resto de nodos
                   Print #92, "<sum1:Huella>" & huella & "</sum1:Huella>"
                    
                    Print #92, "<sum1:TipoHash>01</sum1:TipoHash>"
                    Print #92, "</sum:DatosControl>"
                    If es_anulacion Then
                        Print #92, "</sum:RegistroAnulacionFacturas>"
                        Print #92, "</sum:BajaFactuSistemaFacturacion>"
                    Else
                        Print #92, "</sum:RegistroAltaFacturas>"
                        Print #92, "</sum:AltaFactuSistemaFacturacion>"
                    End If
                   close #92
Por otro lado puedo encapsular en php, ya que en VB6 desconozco la forma, pero en mi caso hemos pagado a una empresa la programación y el servicio de conservación y le vamos a enviar los xmls sin encapsular para que hagan toda la hilera de verificación del encadenamiento, validación schema xml-xsd, conservación, encapsulamiento, envios y control de errores, el envio lo harán con su certificado y ellos le dan este servicio a cada cliente al que le cobraremos un precio "razonable", y me libero de la parte peor. Cada cliente recibirá o podrá consultar el reporte de los envios y si hay errores se avisará y se tomará las medidas según cada caso, esto ya lo tenemos definido.
Responder Con Cita
  #1320  
Antiguo 17-02-2024
ermendalenda ermendalenda is offline
Miembro
 
Registrado: ago 2021
Posts: 867
Poder: 3
ermendalenda Va por buen camino
codigo ejemplo php encapsulamiento y envio

Aquí te dejo un encapsulamiento y envio, totalmente funcional para face y faceb2b en entornos de prueba y producción, si aprendes como funciona lo puedes modificar para cualquier definición que hagan teniendo en cuenta que yo le paso el path donde tengo el fichero y los datos por curl de esta forma:
Código:
curl --connect-timeout 10 --insecure -A "FacturaePHP/1.7.1" -H "SOAPAction: https://webservice.face.gob.es#enviarFactura" --data "@C:\xml\Facturare_FICTICIO_fichero.xml" --cert-type P12 --cert c:\....\fichero_certificado.pfx:clave -H "Content-Type: text/xml" https://se-face-webservice.redsara.es/facturasspp2 -o C:\respuestas\Respuesta_face_o.html -D C:\respuestas\Respuesta_face_D.html
Código PHP:
 <?php 
//ASIGNA EL ENTORNO QUE VAMOS A USAR  $endpoint como variable de uso GLOBALS
//************************************
//*************  FACE   **************
//************************************
//  ENTORNO DE PRODUCCION
//$endpoint= "https://webservice.face.gob.es/facturasspp2" :
      
//  ENTORNO DE PRUEBAS
$endpoint"https://se-face-webservice.redsara.es/facturasspp2";      
//************************************


//************************************
//************  FACEB2B   ************
//************************************
//  ENTORNO DE PRODUCCION
//$endpoint= "https://ws.faceb2b.gob.es/sv1/invoice" :

//  ENTORNO DE PRUEBAS
//$endpoint= "https://se-ws-faceb2b.redsara.es/sv1/invoice";
//************************************





//**Asigna a $datos la variable de la llamada curl (fichero) que contiene 2 variables separadas por signo "="
$datos $_GET['fichero'];

//***Asigno $datos a un array ya que contiene 2 campos 
$varias=explode("=",$datos);
//***El primer campo del array contiene el nombre del fichero del certificado

// **EJEMPLO PFX $dir_cert = ($_SERVER['DOCUMENT_ROOT'].'/certs/Certificado.pfx' );
//variable de uso GLOBALS
$dir_cert = ($_SERVER['DOCUMENT_ROOT'].'/certs/'.$varias[1] );

//***El segundo campo del array contiene el password del certificado
//variable de uso GLOBALS
$clave=$varias[2];

//variable de uso GLOBALS
$filename=$varias[3];
$NombreFichero=$varias[3];

//variable de uso GLOBALS
$xml2=file_get_contents("php://input");


//variable de uso GLOBALS
$version "1.7.1";

// Cargamos la factura en una instancia de FacturaeFile

//$invoice2 = new InvoiceTest();

//$invoice2->EnviarFactura($xml2);
//*****************************
//****** ENVIAR POR FACE ******
//*****************************
    
$invoice = new FacturaeFile();
    
$invoice=$GLOBALS["xml2"];


    
    
$nulo=null;
    
$face = new FaceTrait();

    
$res =$face->sendInvoice("verifactu@gmail.com"$invoice);


//*****************************
//***** ENVIAR POR FACEB2B ****
//*****************************

//    $invoice = new FacturaeFile();
//    $invoice=$GLOBALS["xml2"];
//    $nulo=null;
//    $face = new FaceB2BTrait();

//    $res =$face->sendInvoice("verifactu@gmail.com", $invoice);




/**
 * Gets both public and private keys from a PKCS#12 certificate store or a PEM
 * file (X.509 certificate).
 */
class KeyPairReader {
  private 
$publicChain = [];
  private 
$privateKey null;


  
/**
   * Get public certificates chain from child to top CA
   * @return string[] Array of PEM strings
   */
  
public function getPublicChain() {
    return 
$this->publicChain;
  }


  
/**
   * Get public key
   * @return string|null Certificate for the Public Key in PEM format
   */
  
public function getPublicKey() {
    return empty(
$this->publicChain) ? null $this->publicChain[0];
  }


  
/**
   * Get private key
   * @return \OpenSSLAsymmetricKey|resource|null Decrypted Private Key
   */
  
public function getPrivateKey() {
    return 
$this->privateKey;
  }


  
/**
   * KeyPairReader constructor
   *
   * @param string      $publicPath  Path to public key in PEM or PKCS#12 file
   * @param string|null $privatePath Path to private key (null for PKCS#12)
   * @param string      $passphrase  Private key passphrase
   */
  
public function __construct($publicPath$privatePath=null$passphrase="") {
    if (
is_null($privatePath)) {
      
$this->readPkcs12($GLOBALS["dir_cert"], $passphrase);
    } else {
      
$this->readX509($GLOBALS["dir_cert"], $privatePath$passphrase);
    }
  }


  
/**
   * Read a X.509 certificate and PEM encoded private key
   *
   * @param string $publicPath  Path to public key PEM file
   * @param string $privatePath Path to private key PEM file
   * @param string $passphrase  Private key passphrase
   */
  
private function readX509($publicPath$privatePath$passphrase) {
    if (!
is_file($GLOBALS["dir_cert"]) || !is_file($privatePath)) return;

    
// Validate and normalize public key
    
$publicKey openssl_x509_read(file_get_contents($GLOBALS["dir_cert"]));
    if (empty(
$publicKey)) return;
    
openssl_x509_export($publicKey$publicKeyPem);
    
$this->publicChain = array($publicKeyPem);
    
    
// Decrypt private key
    
$this->privateKey openssl_pkey_get_private(file_get_contents($privatePath), $passphrase);
  }


  
/**
   * Read a PKCS#12 Certificate Store
   *
   * @param string $certPath   The certificate store file name
   * @param string $passphrase Password for unlocking the PKCS#12 file
   */
  
private function readPkcs12($certPath$passphrase) {
    if (!
is_file($certPath)) return;
    if (
openssl_pkcs12_read(file_get_contents($certPath), $store$passphrase)) {
      
$this->publicChain = array($store['cert']);
      if (!empty(
$store['extracerts'])) {
        
$this->publicChain array_merge($this->publicChain$store['extracerts']);
      }
      
$this->privateKey openssl_pkey_get_private($store['pkey']);
      unset(
$store);
    }
  }

}
class 
XmlTools {

  
/**
   * Escape XML value
   * @param  string $value Input value
   * @return string        Escaped input
   */
  
public function escape($value) {
    return 
htmlspecialchars($valueENT_XML1'UTF-8');
  }


  
/**
   * Generate random ID
   *
   * This method is used for generating random IDs required when signing the
   * document.
   *
   * @return int Random number
   */
  
public function randomId() {
    if (
function_exists('random_int')) return random_int(0x100000000x7FFFFFFF);
    return 
rand(100000999999);
  }


  
/**
   * Inject namespaces
   * @param  string          $xml   Input XML
   * @param  string|string[] $newNs Namespaces
   * @return string                 Canonicalized XML with new namespaces
   */
  
public function injectNamespaces($xml$newNs) {
    if (!
is_array($newNs)) $newNs = array($newNs);
    
$xml explode(">"$xml2);
    
$oldNs explode(" "$xml[0]);
    
$elementName array_shift($oldNs);

    
// Combine and sort namespaces
    
$xmlns = array();
    
$attributes = array();
    foreach (
array_merge($oldNs$newNs) as $name) {
      if (
strpos($name'xmlns:') === 0) {
        
$xmlns[] = $name;
      } else {
        
$attributes[] = $name;
      }
    }
    
sort($xmlns);
    
sort($attributes);
    
$ns array_merge($xmlns$attributes);

    
// Generate new XML element
    
$xml $elementName " " implode(' '$ns) . ">" $xml[1];
    return 
$xml;
  }


  
/**
   * To Base64
   * @param  string  $bytes  Input
   * @param  boolean $pretty Pretty Base64 response
   * @return string          Base64 response
   */
  
public function toBase64($bytes$pretty=false) {
    
$res base64_encode($bytes);
    return 
$pretty $this->prettify($res) : $res;
  }


  
/**
   * Prettify
   * @param  string $input Input string
   * @return string        Multi-line resposne
   */
  
private function prettify($input) {
    return 
chunk_split($input76"\n");
  }


  
/**
   * Get digest in SHA-512
   * @param  string  $input  Input string
   * @param  boolean $pretty Pretty Base64 response
   * @return string          Digest
   */
  
public function getDigest($input$pretty=false) {
    return 
$this->toBase64(hash("sha512"$inputtrue), $pretty);
  }


  
/**
   * Get certificate
   * @param  string  $pem    Certificate for the public key in PEM format
   * @param  boolean $pretty Pretty Base64 response
   * @return string          Base64 Certificate
   */
  
public function getCert($pem$pretty=true) {
    
$pem str_replace("-----BEGIN CERTIFICATE-----"""$pem);
    
$pem str_replace("-----END CERTIFICATE-----"""$pem);
    
$pem str_replace("\n"""str_replace("\r"""$pem));
    if (
$pretty$pem $this->prettify($pem);
    return 
$pem;
  }




  
/**
   * Get signature in SHA-1
   * @param  string  $payload    Data to sign
   * @param  string  $privateKey Private Key
   * @param  boolean $pretty     Pretty Base64 response
   * @return string              Base64 Signature
   */
  
public function getSignature($payload$privateKey$pretty=true) {
    
openssl_sign($payload$signature$privateKey);
    return 
$this->toBase64($signature$pretty);
  }


}

Class 
Faceb2bTrait {
  
/**
   * Get web namespace
   * @return string Web namespace
   */
  
protected function getWebNamespace() {
    return 
"https://webservice.faceb2b.gob.es";
  }


  
/**
   * Send invoice
   * @param  FacturaeFile      $invoice    Invoice
   * @param  FacturaeFile|null $attachment Optional attachment
   * @return SimpleXMLElement              Response
   */
  
public function sendInvoice($invoice$attachment=null) {
    
$tools = new XmlTools();
    
$req '<web:SendInvoice><request>';

    
$req .= '<invoiceFile>' .
        
'<content>' $tools->toBase64($GLOBALS["xml2"]) . '</content>' .
        
'<name>' $GLOBALS["NombreFichero"] . '</name>' .
        
'<mime>text/xml</mime>' // Mandatory MIME type
      
'</invoiceFile>';

    if (!
is_null($attachment)) {
      
$req .= '<attachmentFile>' .
          
'<content>' $tools->toBase64($attachment->getData()) . '</content>' .
          
'<name>' $attachment->getFilename() . '</name>' .
          
'<mime>' $attachment->getMimeType() . '</mime>' .
        
'</attachmentFile>';
    }

    
$req .= '</request></web:SendInvoice>';
    
//$soap=new SoapClient1();
$soap = new FacturaeFile();
      
    return 
$soap->request($req);
  }


  
/**
   * Get invoice details
   * @param  string           $regId Registry number
   * @return SimpleXMLElement        Response
   */
  
public function getInvoiceDetails($regId) {
    return 
$this->request('<web:GetInvoiceDetails><request>' .
      
'<registryNumber>' $regId '</registryNumber>' .
      
'</request></web:GetInvoiceDetails>');
  }


  
/**
   * Request invoice cancellation
   * @param  string           $regId   Registry number
   * @param  string           $reason  Reason code
   * @param  string|null      $comment Optional comments
   * @return SimpleXMLElement          Response
   */
  
public function requestInvoiceCancellation($regId$reason$comment=null) {
    
$req '<web:RequestInvoiceCancellation><request>';
    
$req .= '<registryNumber>' $regId '</registryNumber>';
    
$req .= '<reason>' $reason '</reason>';
    if (!
is_null($comment)) {
      
$req .= '<comment>' $comment '</comment>';
    }
    
$req .= '</request></web:RequestInvoiceCancellation>';

    return 
$this->request($req);
  }


  
/**
   * Get registered invoices
   * @param  string|null      $receivingUnit Receiving unit code
   * @return SimpleXMLElement                Response
   */
  
public function getRegisteredInvoices($receivingUnit=null) {
    
$req '<web:GetRegisteredInvoices><request>';
    if (
is_null($receivingUnit)) {
      
$req .= '<receivingUnit>' $receivingUnit '</receivingUnit>';
    }
    
$req .= '</request></web:GetRegisteredInvoices>';
    return 
$this->request($req);
  }


  
/**
   * Get invoice cancellations
   * @return SimpleXMLElement Response
   */
  
public function getInvoiceCancellations() {
    return 
$this->request('<web:GetInvoiceCancellations><request>' .
      
'</request></web:GetInvoiceCancellations>');
  }


  
/**
   * Download invoice
   * @param  string           $regId    Registry number
   * @param  boolean          $validate Validate invoice
   * @return SimpleXMLElement           Response
   */
  
public function downloadInvoice($regId$validate=true) {
    
$req '<web:DownloadInvoice><request>';
    
$req .= '<registryNumber>' $regId '</registryNumber>';
    if (
$validate) {
      
$req .= '<signatureValidationMode>validate</signatureValidationMode>';
    }
    
$req .= '</request></web:DownloadInvoice>';
    return 
$this->request($req);
  }


  
/**
   * Confirm invoice download
   * @param  string           $regId   Registry number
   * @return SimpleXMLElement          Response
   */
  
public function confirmInvoiceDownload($regId) {
    return 
$this->request('<web:ConfirmInvoiceDownload><request>' .
      
'<registryNumber>' $regId '</registryNumber>' .
      
'</request></web:ConfirmInvoiceDownload>');
  }


  
/**
   * Reject invoice
   * @param  string           $regId   Registry number
   * @param  string           $reason  Reason code
   * @param  string|null      $comment Optional comments
   * @return SimpleXMLElement          Response
   */
  
public function rejectInvoice($regId$reason$comment=null) {
    
$req '<web:RejectInvoice><request>';
    
$req .= '<registryNumber>' $regId '</registryNumber>';
    
$req .= '<reason>' $reason '</reason>';
    if (!
is_null($comment)) {
      
$req .= '<comment>' $comment '</comment>';
    }
    
$req .= '</request></web:RejectInvoice>';
    return 
$this->request($req);
  }


  
/**
   * Mark invoice as paid
   * @param  string           $regId   Registry number
   * @return SimpleXMLElement          Response
   */
  
public function markInvoiceAsPaid($regId) {
    return 
$this->request('<web:MarkInvoiceAsPaid><request>' .
      
'<registryNumber>' $regId '</registryNumber>' .
      
'</request></web:MarkInvoiceAsPaid>');
  }


  
/**
   * Accept invoice cancellation
   * @param  string           $regId   Registry number
   * @return SimpleXMLElement          Response
   */
  
public function acceptInvoiceCancellation($regId) {
    return 
$this->request('<web:AcceptInvoiceCancellation><request>' .
      
'<registryNumber>' $regId '</registryNumber>' .
      
'</request></web:AcceptInvoiceCancellation>');
  }


  
/**
   * Reject invoice cancellation
   * @param  string           $regId   Registry number
   * @param  string           $comment Comment
   * @return SimpleXMLElement          Response
   */
  
public function rejectInvoiceCancellation($regId$comment) {
    return 
$this->request('<web:RejectInvoiceCancellation><request>' .
      
'<registryNumber>' $regId '</registryNumber>' .
      
'<comment>' $comment '</comment>' .
      
'</request></web:RejectInvoiceCancellation>');
  }



  
/**
   * Get codes
   * @param  string           $type Code type
   * @return SimpleXMLElement       Response
   */
  
public function getCodes($type="") {
    return 
$this->request('<web:GetCodes><request>' .
      
'<codeType>' $type '</codeType>' .
      
'</request></web:GetCodes>');
  }
}
//trait FaceTrait {
class FaceTrait {
  
/**
   * Get web namespace
   * @return string Web namespace
   */
  
protected function getWebNamespace() {
    return 
"https://webservice.face.gob.es";
  }
  
/**
   * Send invoice
   * @param  string           $email       Email address
   * @param  FacturaeFile     $invoice     Invoice
   * @param  FacturaeFile[]   $attachments Attachments
   * @return SimpleXMLElement              Response
   */
  
public function sendInvoice($email$invoice$attachments=array()) {
    
$tools = new XmlTools();
    
$req '<web:enviarFactura><request>';
    
$req .= '<correo>' $email '</correo>';
    
$req .= '<factura>' .
        
'<factura>' $tools->toBase64($GLOBALS["xml2"]) . '</factura>' .
        
'<nombre>' $GLOBALS["NombreFichero"] . '</nombre>' .
        
'<mime>application/xml</mime>' // Mandatory MIME type
      
'</factura>';
    
$req .= '<anexos>';
    foreach (
$attachments as $file) {
      
$req .= '<anexo>' .
          
'<anexo>' $tools->toBase64($file->getData()) . '</anexo>' .
          
'<nombre>' $file->getFilename() . '</nombre>' .
          
'<mime>' $file->getMimeType() . '</mime>' .
        
'</anexo>';
    }
    
$req .= '</anexos>';
    
$req .= '</request></web:enviarFactura>';

//echo "*** Esta es la variable de envio req: ";
//echo $req;
//echo " *** FIN VARIABLE REQ *** ";


    //$soap=new SoapClient1();
    
$soap = new FacturaeFile();
      
    
$ok=$soap->request($req);
  }


  
/**
   * Cancel invoice 
   * @param  string           $regId  Invoice register ID
   * @param  string           $reason Cancelation reason
   * @return SimpleXMLElement         Response
   */
  
public function cancelInvoice($regId$reason) {
    return 
$this->request('<web:anularFactura>' .
      
'<numeroRegistro>' $regId '</numeroRegistro>' .
      
'<motivo>' $reason '</motivo>' .
      
'</web:anularFactura>');
  }

  
/**
   * Get invoice status codes
   * @return SimpleXMLElement Response
   */
  
public function getStatus() {
    return 
$this->request('<web:consultarEstados></web:consultarEstados>');
  }


  
/**
   * Get administrations
   * @param  boolean          $onlyTopLevel Get only top level administrations
   * @return SimpleXMLElement               Response
   */
  
public function getAdministrations($onlyTopLevel=true) {
    
$tag "consultarAdministraciones";
    if (!
$onlyTopLevel$tag .= "Repositorio";
    return 
$this->request("<web:$tag></web:$tag>");
  }


  
/**
   * Get units
   * @param  string|null      $code Administration code
   * @return SimpleXMLElement       Response
   */
  
public function getUnits($code=null) {
    if (
is_null($code)) return $this->request('<web:consultarUnidades></web:consultarUnidades>');
    return 
$this->request('<web:consultarUnidadesPorAdministracion>' .
      
'<codigoDir>' $code '</codigoDir>' .
      
'</web:consultarUnidadesPorAdministracion>');
  }


  
/**
   * Get NIFs
   * @param  string|null      $code Administration code
   * @return SimpleXMLElement       Response
   */
  
public function getNifs($code=null) {
    if (
is_null($code)) return $this->request('<web:consultarNIFs></web:consultarNIFs>');
    return 
$this->request('<web:consultarNIFsPorAdministracion>' .
      
'<codigoDir>' $code '</codigoDir>' .
      
'</web:consultarNIFsPorAdministracion>');
  }


  
/**
   * Get invoice
   * @param  string|string[]  $regId Invoice register ID(s)
   * @return SimpleXMLElement        Response
   */
  
public function getInvoices($regId) {
    if (
is_string($regId)) {
      return 
$this->request('<web:consultarFactura>' .
        
'<numeroRegistro>' $regId '</numeroRegistro>' .
        
'</web:consultarFactura>');
    }
    
$req '<web:consultarListadoFacturas><request>';
    foreach (
$regId as $id$req .= '<numeroRegistro>' $id '</numeroRegistro>';
    
$req .= '</request></web:consultarListadoFacturas>';
    return 
$this->request($req);
  }



}
trait 
StageableTrait {
  private 
$production true;

  
/**
   * Set production environment
   * @param boolean $production Is production
   */
  
public function setProduction($production) {
    
$this->production $production;
  }


  
/**
   * Is production
   * @return boolean Is production
   */
  
public function isProduction() {
    return 
$this->production;
  }
}
/**
 * Facturae File
 *
 * Represents a file that can be used as an attachment for an invoice or to
 * send information to a Web Service.
 */
class FacturaeFile {
  const 
REQUEST_EXPIRATION 60// In seconds

  
private $publicKey;
  private 
$privateKey;

  private 
$filename;
  private 
$data;
  private 
$mime;

/**
   * Get web namespace
   * @return string Web namespace
   */
  
protected function getWebNamespace() {
    return 
"https://webservice.face.gob.es";
  }


public function 
request($body) {

$tools = new XmlTools();
    

$nulo=null;


//DATOS SIGN

$policy= array(
    
"name" => "Politica de Firma FacturaE v3.1",
    
"url" => "http://www.facturae.es/politica_de_firma_formato_facturae/politica_de_firma_formato_facturae_v3_1.pdf",
    
"digest" => "Ohixl6upD6av8N7pEvDABhEL6hM=");
    
// Generate random IDs
    
    // Load public and private keys
    
$reader = new KeyPairReader($GLOBALS["dir_cert"], $nulo$GLOBALS["clave"]);
    
$publicChain2 $reader->getPublicChain();
    
$privateKey2 $reader->getPrivateKey();
    
$signPolicy2 $policy;
    unset(
$reader);


    
//No usado Comprueba si hay key publica y privada y devueleve 1=hay 0=no hay
    //return (!empty($publicChain2) && !empty($privateKey2));


    
$reader = new KeyPairReader($GLOBALS["dir_cert"], null$GLOBALS["clave"]);
    
//$publicChain1 = $reader->getPublicChain();
    
$publicKey1 $publicChain2;
     
$publicChain1 $publicChain2;

    
$privateKey1 $reader->getPrivateKey();
    
$signPolicy1 $signPolicy2;
    unset(
$reader);

    
$tools = new XmlTools();

    
// Generate random IDs for this request
    
$bodyId "BodyId-" $tools->randomId();
    
$certId "CertId-" $tools->randomId();
    
$keyId "KeyId-" $tools->randomId();
    
$strId "SecTokId-" $tools->randomId();
    
$timestampId "TimestampId-" $tools->randomId();
    
$sigId "SignatureId-" $tools->randomId();

    
// Define namespaces array
    
$ns = array(
      
"soapenv" => 'xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"',
      
"web" => 'xmlns:web="' $this->getWebNamespace() . '"',
      
"ds" => 'xmlns:ds="http://www.w3.org/2000/09/xmldsig#"',
      
"wsu" => 'xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"',
      
"wsse" => 'xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"'
    
);

    
// Generate request body
    
$reqBody '<soapenv:Body wsu:Id="' $bodyId '">' $body '</soapenv:Body>';
    
$bodyDigest $tools->getDigest($tools->injectNamespaces($reqBody$ns));

    
// Generate timestamp
    
$timeCreated time();
    
$timeExpires $timeCreated self::REQUEST_EXPIRATION;
    
$reqTimestamp '<wsu:Timestamp wsu:Id="' $timestampId '">' .
        
'<wsu:Created>' date('c'$timeCreated) . '</wsu:Created>' .
        
'<wsu:Expires>' date('c'$timeExpires) . '</wsu:Expires>' .
      
'</wsu:Timestamp>';
    
$timestampDigest $tools->getDigest(
      
$tools->injectNamespaces($reqTimestamp$ns)
    );

    
// Generate request header
    
$reqHeader '<soapenv:Header>';
    
$reqHeader .= '<wsse:Security soapenv:mustUnderstand="1">' ;
    
$reqHeader .= '<wsse:BinarySecurityToken ' .
      
'EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ' .
      
'wsu:Id="' $certId '" ' .
      
'ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">' .
        
$tools->getCert($publicKey1[0], false) .
      
'</wsse:BinarySecurityToken>';

    
// Generate signed info
    
$signedInfo '<ds:SignedInfo>' .
        
'<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315">' .
        
'</ds:CanonicalizationMethod>' .
        
'<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></ds:SignatureMethod>' .
        
'<ds:Reference URI="#' $timestampId '">' .
          
'<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"></ds:DigestMethod>' .
          
'<ds:DigestValue>' $timestampDigest '</ds:DigestValue>' .
        
'</ds:Reference>' .
        
'<ds:Reference URI="#' $bodyId '">' .
          
'<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha512"></ds:DigestMethod>' .
          
'<ds:DigestValue>' $bodyDigest '</ds:DigestValue>' .
        
'</ds:Reference>' .
      
'</ds:SignedInfo>';
    
$signedInfoPayload $tools->injectNamespaces($signedInfo$ns);

    
// Add signature and KeyInfo to header
    
$reqHeader .= '<ds:Signature Id="' $sigId '">' .
      
$signedInfo .
      
'<ds:SignatureValue>' .
        
$tools->getSignature($signedInfoPayload$privateKey1false) .
      
'</ds:SignatureValue>';
    
$reqHeader .= '<ds:KeyInfo Id="' $keyId '">' .
      
'<wsse:SecurityTokenReference wsu:Id="' $strId '">' .
        
'<wsse:Reference URI="#' $certId '" ' .
        
'ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3">' .
        
'</wsse:Reference>' .
      
'</wsse:SecurityTokenReference>' .
      
'</ds:KeyInfo>';
    
$reqHeader .= '</ds:Signature>';

    
// Add timestamp and close header
    
$reqHeader .= $reqTimestamp;
    
$reqHeader .= '</wsse:Security>';
    
$reqHeader .= '</soapenv:Header>';

    
// Generate final request
    
$req '<soapenv:Envelope>' $reqHeader $reqBody '</soapenv:Envelope>';
    
$req $tools->injectNamespaces($req$ns);
    
$req '<?xml version="1.0" encoding="UTF-8"?>' $req;

    
// Extract SOAP action from "<web:ACTION></web:ACTION>"
    
$soapAction substr($body5strpos($body'>')-5);
    
$soapAction $this->getWebNamespace() . "#$soapAction";

    
$ch curl_init();
    
curl_setopt_array($ch, array(
      
CURLOPT_URL => $GLOBALS['endpoint'],
      
CURLOPT_RETURNTRANSFER => 1,
      
CURLOPT_SSL_VERIFYPEER => 0,
      
CURLOPT_TIMEOUT => 30,
      
CURLOPT_POST => 1,
      
CURLOPT_POSTFIELDS => $req,
      
CURLOPT_HTTPHEADER => array(
        
"Content-Type: text/xml",
        
"SOAPAction: " $soapAction
      
),
      
CURLOPT_USERAGENT => "FacturaePHP/" $GLOBALS["version"]
    ));
    
$res curl_exec($ch);
    
curl_close($ch);
    unset(
$ch);


    
//// Parse response
    
    
$xml = new \DOMDocument();
    
$xml->loadXML($res);
    
$xml $xml->getElementsByTagName('Body')->item(0)->getElementsByTagName('*')->item(0);
$child $xml->getElementsByTagName('codigo');
 
foreach (
$child as $chi
{
    echo 
$chi->nodeName "=" $chi->nodeValue "\r\n" ;
 }
    
$child $xml->getElementsByTagName('descripcion');

foreach (
$child as $chi
{
    echo 
$chi->nodeName "=" $chi->nodeValue "\r\n" ;
 }
    
$child $xml->getElementsByTagName('codigo Seguimiento');

foreach (
$child as $chi
{
    echo 
$chi->nodeName "=" $chi->nodeValue "\r\n" ;
 }
    
$child $xml->getElementsByTagName('codigoSeguimiento');

foreach (
$child as $chi
{
    echo 
$chi->nodeName "=" $chi->nodeValue "\r\n" ;
 }


//echo  "---- FIN RESULTADO ----"  . "\r\n" . "---- RESPUESTA COMPLETA  ----"  . "\r\n" . $res . "\r\n" . "---- FIN RESPUESTA COMPLETA ----" .  $req;

//if ($res->resultado->codigo == 0) {
//  // La factura ha sido aceptada
//  echo "Número de registro => " . $res->factura->numeroRegistro;
//} else {
//  // FACe ha rechazado la factura
//}

//return $req;  
}



  
/**
   * Get data
   * @return string Data
   */
  
public function getData() {
    return 
$this->data;
  }


  
/**
   * Get filename
   * @return string Filename
   */
  
public function getFilename() {
    return 
$this->filename;
  }


  
/**
   * Get MIME type
   * @return string MIME type
   */
  
public function getMimeType() {
    return 
$this->mime;
  }
}




?>
[/php]
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Hijo de Informáticos gluglu Humor 3 13-03-2007 11:05:35
Adictos informaticos ... Trigger Humor 2 11-10-2004 12:18:32
Nosotros los Informáticos Trigger Humor 1 10-10-2004 14:58:09
Patrón de los Informáticos. obiwuan Varios 20 10-09-2003 14:44:54
Chistes Informaticos jhonny Humor 2 11-08-2003 21:59:09


La franja horaria es GMT +2. Ahora son las 11:14:10.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi