Exemplo de integração com a API dos Correios via AdvPL

No artigo de hoje, vou mostrar para vocês como fazer a integração com a API dos Correios.

Pessoal, o exemplo apresentado aqui foi disponibilizado com a ajuda do grande Fernando Sauer ( LinkedIn ). No caso, essa customização basicamente se comunica com o WSDL dos correios (documentação disponível em https://www.correios.com.br/atendimento/ferramentas/sistemas/arquivos/web-service-de-rastreamento ).

Depois de fazer essa comunicação, é buscado o resultado em XML, e então conforme as posições do texto é definido um retorno em array.

Para utilizar, é necessário ter um usuário e senha com acesso ao SRO XML dos Correios. No caso, para armazenar essas informações, crie os parâmetros MV_X_CORSE (Correios Senha) e MV_X_CORUS (Correios Usuário).

Abaixo o código fonte desenvolvido:

//Bibliotecas
#Include "TOTVS.ch"
 
/*/{Protheus.doc} User Function zCorreios
Função que realiza a consulta de um rastreio direto nos correios e monta um array com o resultado
@author Fernando Sauer
@since 01/02/2021
@version 1.0
@type function
@return aInfRast, Array, Retorna um array com as informações do rastreio
@example aDados := u_zCorreios("XXAA01010101")
@obs Documentação da API: https://www.correios.com.br/atendimento/ferramentas/sistemas/arquivos/web-service-de-rastreamento
    Exemplo documentado e adaptado por Daniel Atilio
	Abaixo as posições do Array de retorno:
	aInfRast[01] --> Data de atualização da informação nos Correios
	aInfRast[02] --> Hora de atualização da informação nos Correios
	aInfRast[03] --> Descrição do status do rastreamento
	aInfRast[04] --> Local do código de Rastreamento
	aInfRast[05] --> Código de Rastreamento
	aInfRast[06] --> Município do Rastreamento
	aInfRast[07] --> Estado do Objeto  de Rastreamento
	aInfRast[08] --> Endereço de retirada
/*/
 
User Function zCorreios(cRastreio)
	Local aArea     := GetArea()
	Local oWsdl
	Local xRet
	Local cError    := ""
	Local cWarning  := ""
	Local cResp     := ""
	Local lContinua := .T.

	//Retorno Último rastreio
	Local nPosIni 	:= 0
	Local nPosFim	:= 0
	Local nLeitura  := 0
	Local dDtRast	:= ""
	Local cHrRast	:= ""
	Local cDesRast	:= ""
	Local cLcRast	:= ""
	Local cCodRast	:= ""
	Local cMunRast	:= ""
	Local cEstRast	:= ""
	Local cEndereco := ""
	Local aInfRast 	:= Array(8)
	Local cLograd	:= ""		//Logradouro
	Local cNumero	:= ""		//Número
	Local cLocalid	:= ""		//Localidade
	
	//Usuário e senha dos Correios - "Habilitar Acesso ao SRO XML [Solicitação]"
	Local cPWDCo := SuperGetMv("MV_X_CORSE", .F., 'XXXXXXXX')
	Local cUsuCo := SuperGetMv("MV_X_CORUS", .F., 'YYYYYYYY')

	Default cRastreio := ""

	//Código precisa estar preenchido
	If ! Empty(cRastreio)
		MsgInfo("Código de rastreio em branco")
	Else
		
		//Faz a comunicação com a API
		oWsdl := TWsdlManager():New()
		oWsdl:lSSLInsecure := .T.
		If xRet := ! oWsdl:ParseURL( "https://webservice.correios.com.br/service/rastro/Rastro.wsdl" )
			MsgInfo( "Erro Parse: " + oWsdl:cError )
			lContinua := .F.
		EndIf
		
		//Define a operação como buscaEventos
		If lContinua .And. xRet := !oWsdl:SetOperation( "buscaEventos" )  
			MsgInfo( "Erro SetOperation: " + oWsdl:cError )
			lContinua := .F.
		EndIf

		//Se não houve erros
		If lContinua
			cMsgWs := '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:res="http://resource.webservice.correios.com.br/">
			cMsgWs += '<soapenv:Header/>'
			cMsgWs += '<soapenv:Body>'
			cMsgWs += '<res:buscaEventos>
			cMsgWs += '<usuario>' + cUsuCo + '</usuario>
			cMsgWs += '<senha>' + cPWDCo + '</senha>
			cMsgWs += '<tipo>L</tipo>
			cMsgWs += '<resultado>U</resultado>
			cMsgWs += '<lingua>101</lingua>
			cMsgWs += '<objetos>'+ AllTrim(cRastreio) + '</objetos>
			cMsgWs += '</res:buscaEventos>
			cMsgWs += '</soapenv:Body>
			cMsgWs += '</soapenv:Envelope>
			
			//Busca o resultado da consulta
			xRet     := oWsdl:SendSoapMsg(cMsgWs)
			xRet     := oWsdl:SendSoapMsg(cMsgWs)
			cResp    := oWsdl:GetParsedResponse()
			cRespost := oWsdl:GetSoapResponse()
			oXml     := XmlParser( cRespost, "_", @cError, @cWarning )

			//Data de atualização da informação nos Correios
			nPosIni  := At("<data>",  cRespost) + 6
			nPosFim  := At("</data>", cRespost)
			nLeitura := nPosFim - nPosIni
			dDtRast	 := SubStr(cRespost, nPosIni, nLeitura)

			//Hora de atualização da informação nos Correios
			nPosIni  := At("<hora>",  cRespost) + 6
			nPosFim  := At("</hora>", cRespost)
			nLeitura := nPosFim - nPosIni
			cHrRast	 := SubStr(cRespost, nPosIni, nLeitura)

			//Descrição do status do rastreamento
			nPosIni  := At("<descricao>",  cRespost) + 11
			nPosFim  := At("</descricao>", cRespost)
			nLeitura := nPosFim - nPosIni
			cDesRast := SubStr(cRespost, nPosIni, nLeitura)
			cDesRast := DecodeUTF8(cDesRast, "cp1252")

			//Local do código de Rastreamento
			nPosIni  := At("<local>",  cRespost) + 7
			nPosFim  := At("</local>", cRespost)
			nLeitura := nPosFim - nPosIni
			cLcRast	 := SubStr(cRespost, nPosIni, nLeitura)
			cLcRast  := DecodeUTF8(cLcRast, "cp1252")

			//Código de Rastreamento
			nPosIni  := At("<numero>",  cRespost) + 8
			nPosFim  := At("</numero>", cRespost)
			nLeitura := nPosFim - nPosIni
			cCodRast := SubStr(cRespost, nPosIni, nLeitura)
			cCodRast := DecodeUTF8(cCodRast, "cp1252")

			//Município do Rastreamento
			nPosIni  := At("<cidade>",  cRespost) + 8
			nPosFim  := At("</cidade>", cRespost)
			nLeitura := nPosFim - nPosIni
			cMunRast := SubStr(cRespost, nPosIni, nLeitura)
			cMunRast := DecodeUTF8(cMunRast, "cp1252")

			//Estado do Objeto  de Rastreamento
			nPosIni  := At("<uf>",  cRespost) + 4
			nPosFim  := At("</uf>", cRespost)
			nLeitura := nPosFim - nPosIni
			cEstRast := SubStr(cRespost, nPosIni, nLeitura)
			cEstRast := DecodeUTF8(cEstRast, "cp1252")

			//Endereço de retirada
			If "<endereco>" $ cRespost
				nPosIni   := At("<endereco>",  cRespost) + 10
				nPosFim   := At("</endereco>", cRespost)
				nLeitura  := nPosFim - nPosIni
				cEndereco := SubStr(cRespost, nPosIni, nLeitura)
				cEndereco := DecodeUTF8(cEndereco, "cp1252")

				nPosIni  := At("<logradouro>",  cEndereco) + 12
				nPosFim  := At("</logradouro>", cEndereco)
				nLeitura := nPosFim - nPosIni
				cLograd  := SubStr(cEndereco, nPosIni, nLeitura)
				cLograd  := DecodeUTF8(cLograd, "cp1252")

				nPosIni  := At("<numero>",  cEndereco) + 8
				nPosFim  := At("</numero>", cEndereco)
				nLeitura := nPosFim - nPosIni
				cNumero  := SubStr(cEndereco, nPosIni, nLeitura)
				cNumero  := DecodeUTF8(cNumero, "cp1252")
				
				nPosIni  := At("<localidade>",  cEndereco) + 12
				nPosFim  := At("</localidade>", cEndereco)
				nLeitura := nPosFim - nPosIni
				cLocalid := SubStr(cEndereco, nPosIni, nLeitura)
				cLocalid := DecodeUTF8(cLocalid, "cp1252")
				
				cEndereco := cLograd + ", " + cNumero + " " + cLocalid

			Else
				cEndereco := ""
			EndIf
			
			//Define o retorno
			aInfRast[01] := dDtRast
			aInfRast[02] := cHrRast
			aInfRast[03] := cDesRast
			aInfRast[04] := cLcRast
			aInfRast[05] := cCodRast
			aInfRast[06] := Capital(cMunRast)
			aInfRast[07] := cEstRast
			aInfRast[08] := Capital(cEndereco)
		EndIf
	EndIf

	RestArea(aArea)
Return aInfRast

Bom pessoal, por hoje é só.

Abraços e até a próxima.

Dan Atilio (Daniel Atilio)
Especialista em Engenharia de Software pela FIB. Entusiasta de soluções Open Source. E blogueiro nas horas vagas.

2 Responses

  1. Leonardo Barrozo dos Santos disse:

    Estou desenvolvendo um programa quase igual ao seu para os correios.

    // Cria o objeto da classe TWsdlManager
    oWsdl := TWsdlManager():New()
    oWsdl:lSSLInsecure := .T.

    xRet := oWsdl:ParseURL(“https://apphom.correios.com.br/SigepMasterJPA/AtendeClienteService/AtendeCliente?wsdl”)
    If xRet == .F.
    Alert( “Erro 0: ” + oWsdl:cError )
    Return
    EndIf

    xRet := oWsdl:SetOperation( “verificaDisponibilidadeServico” )
    If xRet == .F.
    Alert( “Erro 1: ” + oWsdl:cError )
    Return
    EndIf

    cMsgWs := ”
    cMsgWs += ”
    cMsgWs += ”
    cMsgWs += ”
    cMsgWs += ‘17000190’
    cMsgWs += ‘04162’
    cMsgWs += ‘05311900’
    cMsgWs += ‘05311900’
    cMsgWs += ‘sigep’
    cMsgWs += ‘n5f9t8’
    cMsgWs += ”
    cMsgWs += ”
    cMsgWs += ”

    //Busca o resultado da consulta
    xRet := oWsdl:SendSoapMsg(cMsgWs)
    If xRet == .F.
    Alert( “Erro 2: ” + oWsdl:cError ) //ERRO AQUI: SOAP Fault Code: soap:Client SOAP Fault String: Error reading XMLStreamReader.
    Return
    EndIf

    cResp := oWsdl:GetParsedResponse()
    cRespost := oWsdl:GetSoapResponse()

    Esse exemplo acima é do próprio manual para teste.

    Apresenta o erro (SOAP Fault Code: soap:Client SOAP Fault String: Error reading XMLStreamReader.)

    Você poderia me ajudar? Já aconteceu com você esse tipo de erro?

Deixe uma resposta