API REST SUNAT - GUIAS DE REMISION ELECTRONICAS

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

API REST SUNAT - GUIAS DE REMISION ELECTRONICAS

Post by edufloriv »

Saludos amigos,

Esperando se encuentren todos bien. Estoy tratando de consumir una api de Sunat (entidad reguladora de impuestos acá en Perú). Esta api me debe retornar un token con el que después podré realizar el envío de guías electrónicas.
La documentación de Sunat indica esto para realizar el request:
En la cabecera (Header) se debe enviar el siguiente parámetro:
Content-Type Application/json
El cuerpo (Body) de la consulta deberá ser de tipo “x-www-form-urlencoded” y se debe
enviar los siguientes parámetros:
grant_type : password
scope : https://api-cpe.sunat.gob.pe
client_id : <client_id> generado en menú SOL
client_secret : <client_secret> generado en menú SOL
username : <Número de RUC> + <Usuario SOL>
password : <Contraseña SOL>

Donde:
- El parámetro grant_type tiene valor fijo
También dá un json de ejemplo para realizar pruebas con Postman:
gre-token-2.png
gre-token-2.png (29.46 KiB) Viewed 4847 times
Y esta debería ser la respuesta de la api, debería devolver el token, el tipo de token y el tiempo de vigencia:
gre-token-3.png
gre-token-3.png (185.32 KiB) Viewed 4847 times
Yo tengo así mi código:

Code: Select all

* ------------------------------------------------------------------------
FUNC SunatGRE_GetToken

LOCAL cJson , aJson , cCliDoc , hBody , oRestApi
LOCAL aData := {}

   oRestApi := ApiRestOpen()
   IF ! EMPTY(oRestApi)
//  esta url es para realizar pruebas :
      cURL  := "https://gre-test.nubefact.com/v1/clientessol/test-85e5b0ae-255c-4891-a595-0b98c65c9854/oauth2/token"
      hBody := { => }
      hBody ["grant_type"]    := "password"
      hBody ["scope"]         := "https://api-cpe.sunat.gob.pe"
      hBody ["client_id"]     := "test-85e5b0ae-255c-4891-a595-0b98c65c9854"
      hBody ["client_secret"] := "test-Hty/M6QshYvPgItX2P0+Kw=="
      hBody ["username"]      := "20522209636MODDATOS"
      hBody ["password "]     := "MODDATOS"
      cJson := hb_jsonEncode( hBody , .F. )
      cResp := ApiRestSend( oRestApi , "POST" , "application/json" , cURL , cJson , , "application/x-www-form-urlencoded" )
      hb_jsondecode( cResp , @aData )
      hb_memowrit( 'respuesta_sunat.txt' , cResp )
      hBody := Nil
      IF VALTYPE(aData) = 'H'
         cToken := aData["access_token"]
         cTipo  := aData["token_type"]
         cExpir := aData["expires_in"]
         msginfo("Token: "+cToken)
      ENDIF
   ENDIF
   oRestApi := NIL

RETURN

*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
* FUNCION   : ApiRestOpen
* COMENTARIO:
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------

FUNCTION ApiRestOpen

LOCAL oRestApi := ""
LOCAL nTimeOut := 20  //seconds

//Init
BEGIN SEQUENCE WITH {|o| break(o)}
	oRestApi := Win_OleCreateObject( "MSXML2.ServerXMLHTTP" )
//                          nResolve         nConnect        nSend               nRecieve
	oRestApi:setTimeouts( nTimeout * 1000 , nTimeout * 1000 , nTimeout * 1000 , nTimeout * 1000 )
RECOVER
     MsgStop( "Microsoft XML Core Services (MSXML) 6.0 is not installed."+CRLF+;
          "Download and install MSXML 6.0 from http://msdn.microsoft.com/xml"+CRLF+;
          "before continuing.")
END SEQUENCE

RETURN( oRestApi )


*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
* FUNCION   : ApiRestSend
* COMENTARIO:
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------

FUNCTION ApiRestSend( oRestApi, cMethod, cContentType, cUrl, cBody, cToken, cContentType2 )

LOCAL cReturn

/*
cContentType:
"application/json;charset=utf-8"
"application/x-www-form-urlencoded"
"application/xml"
*/

DO EVENTS

BEGIN SEQUENCE WITH {|o| break(o)}

	set( _SET_CODEPAGE, 'UTF8' )
	oRestApi:Open( cMethod , cUrl , .F. )
	oRestApi:setRequestHeader("Content-Type",cContentType)
   IF VALTYPE(cContentType2) = 'C'
      oRestApi:setRequestHeader("Content-Type",cContentType2)
   ENDIF
   IF VALTYPE(cToken) = 'C'
      oRestApi:setRequestHeader("Authorization" , "Token token=" + cToken)
   ENDIF
   IF VALTYPE(cBody) = 'C'
      oRestApi:Send( cBody )
   ELSE
      oRestApi:Send()
   ENDIF
	set( _SET_CODEPAGE, "ESWIN" )

	IF oRestApi:Status <> 200
		BREAK "HTTP status: " + hb_NToS(oRestApi:status) + " "  + oRestApi:statusText 
	ENDIF

//	cReturn := oRestApi:ResponseBody()
	cReturn := oRestApi:ResponseText()

RECOVER USING oErr

	cReturn := "!ERROR!" + CRLF + HB_TRANSLATE( IF (ValType(oErr) = 'O' , oErr:Description , oErr ) , 'ESWIN' )
 
END SEQUENCE
 	
RETURN cReturn

Pero a mi me retorna lo siguiente (contenido de respuesta_sunat.txt):
gre-token-4.png
gre-token-4.png (9.48 KiB) Viewed 4847 times
Al parecer estoy armando mal el request. Lo que no entiendo es como colocar ese atributo "urlencoded" al body. Agradeceré su gentil ayuda.

Eduardo Flores Rivas


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

Re: API REST SUNAT - GUIAS DE REMISION ELECTRONICAS

Post by edk »

Ahí lo tienes, aquí tienes la solución:

Code: Select all

      cURL  := "https://gre-test.nubefact.com/v1/clientessol/test-85e5b0ae-255c-4891-a595-0b98c65c9854/oauth2/token"
      hBody := { => }
      hBody ["grant_type"]    := "password"
      hBody ["scope"]         := "https://api-cpe.sunat.gob.pe"
      hBody ["client_id"]     := "test-85e5b0ae-255c-4891-a595-0b98c65c9854"
      hBody ["client_secret"] := "test-Hty/M6QshYvPgItX2P0+Kw=="
      hBody ["username"]      := "20522209636MODDATOS"
      hBody ["password"]      := "MODDATOS"
      //cJson := hb_jsonEncode( hBody , .F. )
      
      cBody := ""
      hb_HEval ( hBody, { | cKey, cValue | cBody += IF ( !Empty ( cBody ), "&", "" ) + AllTrim ( cKey ) + "=" + tip_URLEncode( cValue ) } )
      //cBody is x-www-form-urlencoded

      cResp := ApiRestSend( oRestApi , "POST" , "application/json" , cURL , cBody , , "application/x-www-form-urlencoded" )
Tenga en cuenta que x-www-form-urlencoded no es un formato json sino un sting que envía parámetros como una extensión de URL.

También tuvo un error en la definición de la clave hBody ["password "] (hay un espacio innecesario). Debería ser hBody ["password"].
User avatar
edufloriv
Posts: 240
Joined: Thu Nov 08, 2012 3:42 am
DBs Used: DBF, MariaDB, MySQL, MSSQL, MariaDB
Location: PERU

Re: API REST SUNAT - GUIAS DE REMISION ELECTRONICAS

Post by edufloriv »

Tocayo, muchas gracias, funciona !!

Así me devuelve la respuesta.
{
"access_token":"test-eyJhbGciOiJIUzUxMiJ9.ImE1NTFkMTI2LTgwYzAtNDRmYS04NjRiLTRiNGQ3Zjk3ZWE2NSI.JEQQGteYhHnepJyS0a_ao3KnzAvBKiL8ARUIZqxE-Ue2p8fBSZ7sg7ywqueFQJdG3yGKl1i83DKXUluRgiBWSw",
"token_type":"JWT",
"expires_in":3600
}
Ya te debo varias cervezas amigo. Un gran abrazo y que tengas excelente día.

Eduardo Flores Rivas


LIMA - PERU
Post Reply