GUIAS DE REMISION ELECT SUNAT - SHA-256

HMG en Español

Moderator: Rathinagiri

Post Reply
User avatar
edufloriv
Posts: 240
Joined: Thu Nov 08, 2012 3:42 am
DBs Used: DBF, MariaDB, MySQL, MSSQL, MariaDB
Location: PERU

GUIAS DE REMISION ELECT SUNAT - SHA-256

Post by edufloriv »

Saludos amigos, yo de nuevo.

Estoy implementando la segunda parte para el envio de guias de remisión electrónica a Sunat, que es la obtención del ticket.

Este es mi código como lo tengo hasta ahora:

Code: Select all

*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
 // EJEMPLO cZipFile: 20522209636-09-T001-00000461.zip
 // dentro del zip se encuentra el .xml con el nombre 20522209636-09-T001-00000461.xml
 // cUrl es una url de prueba, no es de producción

FUNC SunatGRE_GetTicket( cZipFile )

LOCAL cCPEName           := STRTRAN( cZipFile , ".zip" )
LOCAL cZipFileContent    := FileStr( cZipFile )
LOCAL cBase64ContentFile := hb_Base64Encode( cZipFileContent, Len( cZipFileContent ) )
LOCAL cZipHash           := "" //?? Hash del archivo zip enviado. Debe calcularse el hash del archivo zip haciendo uso del algoritmo SHA-256.
LOCAL cUrl               := "https://gre-test.nubefact.com/v1/contribuyente/gem/comprobantes/" + cCPEName
LOCAL cToken             := hb_memoread( "token_id.txt" ) //aqui leo el token obtenido en el proceso anterior en el que EDK me ayudó.
LOCAL cBody              := ""

//   oRestApi := ApiRestOpen()
//   IF ! EMPTY(oRestApi)

      hZip  := { => }
      hZip ["nomArchivo"] := cZipFile
      hZip ["arcGreZip"]  := cBase64ContentFile
      hZip ["hashZip"]    := cZipHash //<- usar algoritmo SHA-256.

      hBody := { => }
      hBody ["archivo"]   := hZip

      cJson := hb_jsonEncode( hBody , .T. )
      hb_memowrit( "sunat_body.txt" , cJson )
      
      //cBody is x-www-form-urlencoded
//      hb_HEval ( hBody, { | cKey, cValue | cBody += IF ( !Empty ( cBody ), "&", "" ) + AllTrim ( cKey ) + "=" + tip_URLEncode( cValue ) } )

/*      cResp := ApiRestSend( oRestApi , "POST" , "application/json" , cURL , cBody , , "application/x-www-form-urlencoded" )
      hb_jsondecode( cResp , @aData )
      hb_memowrit( 'respuesta_sunat.txt' , cResp )
      hBody := Nil
      IF VALTYPE(aData) = 'H'
      ENDIF

   ENDIF
   oRestApi := NIL
*/
RETURN( cHash )
Sunat da estas indicaciones para hacer el request:
gre-getticket.png
gre-getticket.png (46.22 KiB) Viewed 6067 times
Mi pregunta es ¿ como hago para obtener el hash del zip usando algoritmo SHA-256. ? - Gracias anticipadas amigos y saludos.

P.D. Adjunto un zip por si desean hacer pruebas.
Attachments
20522209636-09-T001-00000461.zip
(4.2 KiB) Downloaded 139 times

Eduardo Flores Rivas


LIMA - PERU
User avatar
edufloriv
Posts: 240
Joined: Thu Nov 08, 2012 3:42 am
DBs Used: DBF, MariaDB, MySQL, MSSQL, MariaDB
Location: PERU

Re: GUIAS DE REMISION ELECT SUNAT - SHA-256

Post by edufloriv »

Amigos,

Ya lo encontré, era super simple:

Code: Select all

FUNC SunatGRE_GetTicket( cZipFile ) // EJEMPLO cZipFile: 20522209636-09-T001-00001234.zip

LOCAL cCPEName           := STRTRAN( cZipFile , ".zip" )
LOCAL cZipFileContent    := FileStr( cZipFile )
LOCAL cBase64ContentFile := hb_Base64Encode( cZipFileContent, Len( cZipFileContent ) )
LOCAL cZipHash           := hb_SHA256(cBase64ContentFile) //<-casi intuitivo :)
LOCAL cUrl               := "https://gre-test.nubefact.com/v1/contribuyente/gem/comprobantes/" + cCPEName
LOCAL cToken             := hb_memoread( "token_id.txt" )
LOCAL cBody              := ""

//   oRestApi := ApiRestOpen()
//   IF ! EMPTY(oRestApi)

      hZip  := { => }
      hZip ["nomArchivo"] := cZipFile
      hZip ["arcGreZip"]  := cBase64ContentFile
      hZip ["hashZip"]    := cZipHash //<- usar algoritmo SHA-256.

      hBody := { => }
      hBody ["archivo"]   := hZip

      cJson := hb_jsonEncode( hBody , .T. )
      hb_memowrit( "sunat_body.txt" , cJson )
Y ya mi body para el request me queda así:
body-gre-ticket.png
body-gre-ticket.png (19.07 KiB) Viewed 6049 times
Lo encontré en el foro de harbour de google. Mil gracias por su atención y saludos.

Eduardo Flores Rivas


LIMA - PERU
edk
Posts: 999
Joined: Thu Oct 16, 2014 11:35 am
Location: Poland

Re: GUIAS DE REMISION ELECT SUNAT - SHA-256

Post by edk »

Intente utilizar la función

Code: Select all

cZipHash := hb_SHA256 ( cBase64ContentFile, .F. )
La función devuelve el hash SHA265 en formato hexadecimal.
No me gusta el cuerpo JSON de muestra que publicaste: la clave "arcGreZip" tiene un valor que, según la documentación, es el contenido del archivo codificado en Base64, y aquí hay caracteres que no pueden aparecer en Base64. De manera similar con la clave "hashZip", normalmente debería ser una cadena hexadecimal y, en el ejemplo, ¿es parte del valor de la clave "arcGreZip"?

Eduardo, te pregunto por curiosidad, ¿cómo firmaste el archivo xml con un certificado?
edk
Posts: 999
Joined: Thu Oct 16, 2014 11:35 am
Location: Poland

Re: GUIAS DE REMISION ELECT SUNAT - SHA-256

Post by edk »

Ah, ya lo has hecho. :mrgreen:
User avatar
edufloriv
Posts: 240
Joined: Thu Nov 08, 2012 3:42 am
DBs Used: DBF, MariaDB, MySQL, MSSQL, MariaDB
Location: PERU

Re: GUIAS DE REMISION ELECT SUNAT - SHA-256

Post by edufloriv »

Hola EDK,

Gracias por responder, efectivamente tengo un problema, mi código quedó así:

Code: Select all

*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------

FUNC SunatGRE_GetTicket( cZipFile ) // EJEMPLO cZipFile: 20522209636-09-T001-00001234.zip

LOCAL cCPEName           := STRTRAN( cZipFile , ".zip" )
LOCAL cCPENume           := SUBSTR( cCPEName , 16 , 13 )
LOCAL cZipFileContent    := hb_memoread( cZipFile ) //FileStr( cZipFile )
LOCAL cBase64ContentFile := hb_Base64Encode( cZipFileContent, Len( cZipFileContent ) )
LOCAL cZipHash           := hb_SHA256( cZipFileContent , NIL ) //
LOCAL cUrl               := "https://gre-test.nubefact.com/v1/contribuyente/gem/comprobantes/" + cCPEName
LOCAL cToken             := hb_memoread( "token_id.txt" )
LOCAL cAutoriza          := "Bearer " + cToken
LOCAL cBody              := ""
LOCAL cTicket            := ""
LOCAL cFecRec            := ""
LOCAL aData              := {}
LOCAL cPrevSele          := SELECT()
LOCAL hBody , hZip

   oRestApi := ApiRestOpen()
   IF ! EMPTY(oRestApi)

      hZip  := { => }
      hZip ["nomArchivo"] := cZipFile
      hZip ["arcGreZip"]  := cBase64ContentFile
      hZip ["hashZip"]    := cZipHash

      hBody := { => }
      hBody ["archivo"]   := hZip

      cJson := hb_jsonEncode( hBody , .T. )
      hb_memowrit( "sunat_envio.txt" , cUrl + chr(10) + cAutoriza + chr(10) + cJson )
      
      cResp := ApiRestSend( oRestApi , "POST" , "application/json" , cUrl , hb_jsonEncode( hBody , .F. ) , cAutoriza )
      hb_jsonDecode( cResp , @aData )
      hb_memowrit( 'sunat_respuesta.txt' , cResp )
      hBody := Nil
      hZip  := Nil
      IF VALTYPE(aData) = 'H'
         cTicket := aData["numTicket"]
         cFecRec := aData["fecRecepcion"]
         SELE GUIAC
         SET ORDER TO TAG GCxDoc
         DBSEEK(cCPENume)
         IF FOUND()
            IF RED_RLOCK()
               GUIAC->GC_TKTNUM := cTicket
               GUIAC->GC_TKTFEC := cFecRec
               RED_UNLOCK()
            ENDIF
         ENDIF
         SELE &cPrevSele
         msginfo("Ticket: "+cTicket)
      ELSE
         cError := hb_memoread('sunat_respuesta.txt')
         msginfo(cError)
      ENDIF

   ENDIF
   oRestApi := NIL

RETURN
Pero me devuelve: INTERNAL ERROR 500. Usando Insomnia y cargando los valores que grabo en el archivo "sunat_envio.txt" me indica lo siguiente:
insomnia-1.png
insomnia-1.png (119.19 KiB) Viewed 6032 times
Me indica que el .zip esta corrupto. Amigo mio, te estoy enviando un .zip con el proyecto, espero tengas un poco de tiempo para ayudarme. Saludos cordiales desde Perú.
Attachments
SunatGuias.rar
(2.2 MiB) Downloaded 126 times

Eduardo Flores Rivas


LIMA - PERU
edk
Posts: 999
Joined: Thu Oct 16, 2014 11:35 am
Location: Poland

Re: GUIAS DE REMISION ELECT SUNAT - SHA-256

Post by edk »

O tal vez intente contar el hash SHA256, no el contenido de Base64, sino el contenido binario del archivo ZIP (cZipFileContent)

También verifique que si decodifica la cadena Base64 a binario y la guarda como otro archivo .zip, sea el mismo que el original.
A veces, configurar una página de códigos hace que los bytes se "traduzcan" a la página de códigos especificada. Puede intentar configurar la página de códigos en "EN" y luego codificar el contenido del archivo en Base64.
User avatar
edufloriv
Posts: 240
Joined: Thu Nov 08, 2012 3:42 am
DBs Used: DBF, MariaDB, MySQL, MSSQL, MariaDB
Location: PERU

Re: GUIAS DE REMISION ELECT SUNAT - SHA-256

Post by edufloriv »

Saludos amigos,

Solucionado el problema :D

Reemplazar:

Code: Select all

LOCAL cBase64ContentFile := hb_Base64Encode( cZipFileContent, Len( cZipFileContent ) )
Por:

Code: Select all

LOCAL cBase64ContentFile := hb_Base64Encode( cZipFileContent )
Así es, hay que retirar el 2do parametro. ¿ Porque ? ni ídea amigos, pero funciona. Encontré esta respuesta en este link: https://forums.fivetechsupport.com/view ... =3&t=35637

Gracias a todos y en especial a EDK que siempre me ayuda mucho. Un abrazo.

Eduardo Flores Rivas


LIMA - PERU
Post Reply